mirror of https://github.com/CympleTech/ESSE.git
15 changed files with 814 additions and 13 deletions
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
# esse_types |
||||
|
||||
ESSE bulit-in app open types. |
||||
|
||||
### Open Apps |
||||
- Group Chat |
||||
- Domain |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
[package] |
||||
name = "chat_types" |
||||
version = "0.1.0" |
||||
authors = ["CympleTech <dev@cympletech.com>"] |
||||
edition = "2021" |
||||
readme = "README.md" |
||||
description = "ESSE common chat types." |
||||
repository = "https://github.com/cympletech/esse_types/chat" |
||||
keywords = ["distributed", "p2p", "chat", "ESSE"] |
||||
license = "MIT/Apache-2.0" |
||||
|
||||
[dependencies] |
||||
serde = { version = "1", features = ["derive"] } |
||||
tdn_types = { version = "0.6", default-features = false } |
||||
@ -0,0 +1,65 @@
@@ -0,0 +1,65 @@
|
||||
use serde::{Deserialize, Serialize}; |
||||
use tdn_types::{group::GroupId, primitive::PeerId}; |
||||
|
||||
/// message type use in network.
|
||||
#[derive(Serialize, Deserialize, Clone)] |
||||
pub enum NetworkMessage { |
||||
String(String), // content
|
||||
Image(Vec<u8>), // image bytes.
|
||||
File(String, Vec<u8>), // filename, file bytes.
|
||||
Contact(String, GroupId, PeerId, Vec<u8>), // name, gid, addr, avatar bytes.
|
||||
Record(Vec<u8>, u32), // record audio bytes.
|
||||
Emoji, |
||||
Phone, |
||||
Video, |
||||
Invite(String), |
||||
Transfer(String), |
||||
} |
||||
|
||||
/// common message types.
|
||||
#[derive(Copy, Clone, Eq, PartialEq)] |
||||
pub enum MessageType { |
||||
String, |
||||
Image, |
||||
File, |
||||
Contact, |
||||
Record, |
||||
Emoji, |
||||
Phone, |
||||
Video, |
||||
Invite, |
||||
Transfer, |
||||
} |
||||
|
||||
impl MessageType { |
||||
pub fn to_int(&self) -> i64 { |
||||
match self { |
||||
MessageType::String => 0, |
||||
MessageType::Image => 1, |
||||
MessageType::File => 2, |
||||
MessageType::Contact => 3, |
||||
MessageType::Record => 4, |
||||
MessageType::Emoji => 5, |
||||
MessageType::Phone => 6, |
||||
MessageType::Video => 7, |
||||
MessageType::Invite => 8, |
||||
MessageType::Transfer => 9, |
||||
} |
||||
} |
||||
|
||||
pub fn from_int(i: i64) -> MessageType { |
||||
match i { |
||||
0 => MessageType::String, |
||||
1 => MessageType::Image, |
||||
2 => MessageType::File, |
||||
3 => MessageType::Contact, |
||||
4 => MessageType::Record, |
||||
5 => MessageType::Emoji, |
||||
6 => MessageType::Phone, |
||||
7 => MessageType::Video, |
||||
8 => MessageType::Invite, |
||||
9 => MessageType::Transfer, |
||||
_ => MessageType::String, |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
[package] |
||||
name = "cloud_types" |
||||
version = "0.1.0" |
||||
authors = ["CympleTech <dev@cympletech.com>"] |
||||
edition = "2021" |
||||
readme = "README.md" |
||||
description = "ESSE personal data cloud service types." |
||||
repository = "https://github.com/cympletech/esse_types/group" |
||||
keywords = ["distributed", "p2p", "cloud", "data", "storage", "ESSE"] |
||||
license = "MIT/Apache-2.0" |
||||
|
||||
[dependencies] |
||||
serde = { version = "1", features = ["derive"] } |
||||
tdn_types = { version = "0.6", default-features = false } |
||||
tdn_did = { version = "0.6", default-features = false } |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
use serde::{Deserialize, Serialize}; |
||||
use tdn_did::Proof; |
||||
use tdn_types::group::GroupId; |
||||
|
||||
/// Personal data cloud service default TDN GROUP ID.
|
||||
#[rustfmt::skip] |
||||
pub const CLOUD_ID: GroupId = GroupId([ |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 5, |
||||
]); |
||||
|
||||
/// ESSE service to peer layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerServerEvent(pub ServerEvent, pub Proof); |
||||
|
||||
/// ESSE peer to layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerPeerEvent(pub PeerEvent, pub Proof); |
||||
|
||||
/// ESSE service to peer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum ServerEvent { |
||||
/// check result status.
|
||||
/// params: provider name, is support request proxy.
|
||||
Status(String, bool), |
||||
} |
||||
|
||||
/// ESSE peer to service Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum PeerEvent { |
||||
/// check service status is ok.
|
||||
Check, |
||||
} |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
[package] |
||||
name = "dao_types" |
||||
version = "0.1.0" |
||||
authors = ["CympleTech <dev@cympletech.com>"] |
||||
edition = "2021" |
||||
readme = "README.md" |
||||
description = "ESSE dao service types." |
||||
repository = "https://github.com/cympletech/esse_types/dao" |
||||
keywords = ["distributed", "p2p", "DAO", "ESSE"] |
||||
license = "MIT/Apache-2.0" |
||||
|
||||
[dependencies] |
||||
chat_types = { path = "../chat", version = "0.1" } |
||||
serde = { version = "1", features = ["derive"] } |
||||
tdn_types = { version = "0.6", default-features = false } |
||||
tdn_did = { version = "0.6", default-features = false } |
||||
@ -0,0 +1,269 @@
@@ -0,0 +1,269 @@
|
||||
use serde::{Deserialize, Serialize}; |
||||
use tdn_did::Proof; |
||||
use tdn_types::{group::GroupId, primitive::PeerId}; |
||||
|
||||
use chat_types::NetworkMessage; |
||||
|
||||
/// Dao app(service) default TDN GROUP ID.
|
||||
#[rustfmt::skip] |
||||
pub const DAO_ID: GroupId = GroupId([ |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 3, |
||||
]); |
||||
|
||||
/// Group chat types. include: Encrypted, Private, Open.
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug, Eq, PartialEq)] |
||||
pub enum GroupType { |
||||
/// encrypted group type, data is encrypted, and it can need manager
|
||||
/// or take manager's zero-knowledge-proof.
|
||||
Encrypted, |
||||
/// private group type, data not encrypted, and need group manager agree.
|
||||
Private, |
||||
/// opened group type, data not encrypted, anyone can join this group.
|
||||
Open, |
||||
/// tmp group. can use descrip local tmp group chat.
|
||||
Tmp, |
||||
} |
||||
|
||||
impl GroupType { |
||||
pub fn to_i64(&self) -> i64 { |
||||
match self { |
||||
GroupType::Tmp => 0, |
||||
GroupType::Open => 1, |
||||
GroupType::Private => 2, |
||||
GroupType::Encrypted => 3, |
||||
} |
||||
} |
||||
|
||||
pub fn from_i64(u: i64) -> Self { |
||||
match u { |
||||
0 => GroupType::Tmp, |
||||
1 => GroupType::Open, |
||||
2 => GroupType::Private, |
||||
3 => GroupType::Encrypted, |
||||
_ => GroupType::Tmp, |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// DaoInfo transfer in the network.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum DaoInfo { |
||||
/// params: owner, owner_name, owner_avatar, Group ID, group_type, is_must_agree_by_manager,
|
||||
/// group_name, group_bio, group_avatar.
|
||||
Common( |
||||
GroupId, |
||||
String, |
||||
Vec<u8>, |
||||
GroupId, |
||||
GroupType, |
||||
bool, |
||||
String, |
||||
String, |
||||
Vec<u8>, |
||||
), |
||||
/// params: owner, owner_name, owner_avatar, Group ID, is_must_agree_by_manager, key_hash,
|
||||
/// group_name(bytes), group_bio(bytes), group_avatar(bytes).
|
||||
Encrypted( |
||||
GroupId, |
||||
String, |
||||
Vec<u8>, |
||||
GroupId, |
||||
bool, |
||||
Vec<u8>, |
||||
Vec<u8>, |
||||
Vec<u8>, |
||||
Vec<u8>, |
||||
), |
||||
} |
||||
|
||||
/// Dao chat connect data structure.
|
||||
/// params: Group ID, join_proof.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerConnect(pub GroupId, pub ConnectProof); |
||||
|
||||
/// Dao chat connect success result data structure.
|
||||
/// params: Group ID, group current height.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerResult(pub GroupId, pub i64); |
||||
|
||||
/// Dao chat connect proof.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum ConnectProof { |
||||
/// when is joined in group chat, can only use had to join (connect).
|
||||
/// params: proof.
|
||||
Common(Proof), |
||||
/// zero-knowledge-proof. not has account id.
|
||||
/// verify(proof, key_hash, current_peer_addr).
|
||||
Zkp(Proof), // TODO MOCK-PROOF
|
||||
} |
||||
|
||||
/// Dao chat join proof.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum JoinProof { |
||||
/// when join the open group chat.
|
||||
/// params: member name, member avatar.
|
||||
Open(String, Vec<u8>), |
||||
/// when is invate, it will take group_manager's proof for invate.
|
||||
/// params: invite_by_account, invite_proof, member name, member avatar.
|
||||
Invite(GroupId, Proof, String, Vec<u8>), |
||||
/// zero-knowledge-proof. not has account id.
|
||||
/// verify(proof, key_hash, current_peer_addr).
|
||||
Zkp(Proof), // TODO MOCK-PROOF
|
||||
} |
||||
|
||||
/// check result type.
|
||||
#[derive(Serialize, Deserialize, Debug)] |
||||
pub enum CheckType { |
||||
/// allow to create new group.
|
||||
Allow, |
||||
/// cannot created, remain = 0.
|
||||
None, |
||||
/// account is suspended.
|
||||
Suspend, |
||||
/// cannot created, no permission.
|
||||
Deny, |
||||
} |
||||
|
||||
impl CheckType { |
||||
pub fn to_u32(&self) -> u32 { |
||||
match self { |
||||
CheckType::Allow => 0, |
||||
CheckType::None => 1, |
||||
CheckType::Suspend => 2, |
||||
CheckType::Deny => 3, |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// ESSE Dao chat app's layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum LayerEvent { |
||||
/// offline. as BaseLayerEvent.
|
||||
Offline(GroupId), |
||||
/// suspend. as BaseLayerEvent.
|
||||
Suspend(GroupId), |
||||
/// actived. as BaseLayerEvent.
|
||||
Actived(GroupId), |
||||
/// check if account has permission to create group, and supported group types.
|
||||
Check, |
||||
/// result check.
|
||||
/// params: check type, provider name, remain, supported_group_types.
|
||||
CheckResult(CheckType, String, i64, Vec<GroupType>), |
||||
/// create a Group Chat.
|
||||
/// params: group_info, proof.
|
||||
Create(DaoInfo, Proof), |
||||
/// result create group success.
|
||||
/// params: Group ID, is_ok.
|
||||
CreateResult(GroupId, bool), |
||||
/// join group request. Group ID, Join Proof and info, request db id.
|
||||
Request(GroupId, JoinProof), |
||||
/// request need manager to handle.
|
||||
RequestHandle(GroupId, GroupId, PeerId, JoinProof, i64, i64), |
||||
/// manager handle request result. Group ID, request db id, is ok.
|
||||
RequestResult(GroupId, i64, bool), |
||||
/// agree join request.
|
||||
Agree(GroupId, DaoInfo), |
||||
/// reject join request. Group ID, if lost efficacy.
|
||||
Reject(GroupId, bool), |
||||
/// online group member. Group ID, member id, member address.
|
||||
MemberOnline(GroupId, GroupId, PeerId), |
||||
/// offline group member. Group ID, member id.
|
||||
MemberOffline(GroupId, GroupId), |
||||
/// sync online members.
|
||||
MemberOnlineSync(GroupId), |
||||
/// sync online members result.
|
||||
MemberOnlineSyncResult(GroupId, Vec<(GroupId, PeerId)>), |
||||
/// sync group event. Group ID, height, event.
|
||||
Sync(GroupId, i64, Event), |
||||
/// packed sync event request. Group ID, from.
|
||||
SyncReq(GroupId, i64), |
||||
/// packed sync event. Group ID, current height, from height, to height, packed events.
|
||||
Packed(GroupId, i64, i64, i64, Vec<PackedEvent>), |
||||
} |
||||
|
||||
impl LayerEvent { |
||||
/// get event's group id.
|
||||
pub fn gcd(&self) -> Option<&GroupId> { |
||||
match self { |
||||
Self::Offline(gcd) => Some(gcd), |
||||
Self::Suspend(gcd) => Some(gcd), |
||||
Self::Actived(gcd) => Some(gcd), |
||||
Self::Check => None, |
||||
Self::CheckResult(..) => None, |
||||
Self::Create(..) => None, |
||||
Self::CreateResult(gcd, _) => Some(gcd), |
||||
Self::Request(gcd, _) => Some(gcd), |
||||
Self::RequestHandle(gcd, ..) => Some(gcd), |
||||
Self::RequestResult(gcd, ..) => Some(gcd), |
||||
Self::Agree(gcd, ..) => Some(gcd), |
||||
Self::Reject(gcd, ..) => Some(gcd), |
||||
Self::MemberOnline(gcd, ..) => Some(gcd), |
||||
Self::MemberOffline(gcd, ..) => Some(gcd), |
||||
Self::MemberOnlineSync(gcd) => Some(gcd), |
||||
Self::MemberOnlineSyncResult(gcd, ..) => Some(gcd), |
||||
Self::Sync(gcd, ..) => Some(gcd), |
||||
Self::SyncReq(gcd, ..) => Some(gcd), |
||||
Self::Packed(gcd, ..) => Some(gcd), |
||||
} |
||||
} |
||||
|
||||
/// check if handle this, remote must online frist.
|
||||
pub fn need_online(&self) -> bool { |
||||
match self { |
||||
Self::Offline(..) => true, |
||||
Self::Suspend(..) => true, |
||||
Self::Actived(..) => true, |
||||
Self::RequestHandle(..) => true, |
||||
Self::RequestResult(..) => true, |
||||
Self::MemberOnline(..) => true, |
||||
Self::MemberOffline(..) => true, |
||||
Self::MemberOnlineSync(..) => true, |
||||
Self::MemberOnlineSyncResult(..) => true, |
||||
Self::Sync(..) => true, |
||||
Self::SyncReq(..) => true, |
||||
Self::Packed(..) => true, |
||||
_ => false, |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// Dao chat packed event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum PackedEvent { |
||||
GroupInfo, |
||||
GroupTransfer, |
||||
GroupManagerAdd, |
||||
GroupManagerDel, |
||||
GroupClose, |
||||
/// params: member id, member address, member name, member avatar.
|
||||
MemberInfo(GroupId, PeerId, String, Vec<u8>), |
||||
/// params: member id, member address, member name, member avatar, member join time.
|
||||
MemberJoin(GroupId, PeerId, String, Vec<u8>, i64), |
||||
/// params: member id,
|
||||
MemberLeave(GroupId), |
||||
/// params: member id, message, message time.
|
||||
MessageCreate(GroupId, NetworkMessage, i64), |
||||
/// had in before.
|
||||
None, |
||||
} |
||||
|
||||
/// Dao chat event.
|
||||
#[derive(Serialize, Deserialize, Clone)] |
||||
pub enum Event { |
||||
GroupInfo, |
||||
GroupTransfer, |
||||
GroupManagerAdd, |
||||
GroupManagerDel, |
||||
GroupClose, |
||||
/// params: member id, member address, member name, member avatar.
|
||||
MemberInfo(GroupId, PeerId, String, Vec<u8>), |
||||
/// params: member id, member address, member name, member avatar, member join time.
|
||||
MemberJoin(GroupId, PeerId, String, Vec<u8>, i64), |
||||
/// params: member id,
|
||||
MemberLeave(GroupId), |
||||
/// params: member id, message, height.
|
||||
MessageCreate(GroupId, NetworkMessage, i64), |
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
[package] |
||||
name = "data" |
||||
version = "0.1.0" |
||||
authors = ["CympleTech <dev@cympletech.com>"] |
||||
edition = "2021" |
||||
readme = "README.md" |
||||
description = "ESSE common data structure." |
||||
repository = "https://github.com/cympletech/esse_types/data" |
||||
keywords = ["distributed", "data", "ESSE"] |
||||
license = "MIT/Apache-2.0" |
||||
|
||||
[features] |
||||
default = ["tdn"] |
||||
tdn = ["tdn_did", "tdn_types"] |
||||
|
||||
[dependencies] |
||||
tdn_did = { version = "0.6", default-features = false, optional = true } |
||||
tdn_types = { version = "0.6", default-features = false, optional = true } |
||||
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
pub type DataId = [u8; 32]; |
||||
|
||||
pub trait OwnerId: Clone + Eq + PartialEq { |
||||
type Proof: Clone + Eq + PartialEq; |
||||
|
||||
fn len() -> usize; |
||||
fn proof_len() -> usize; |
||||
|
||||
fn verify(&self, data: &Data<Self>) -> bool; |
||||
fn id_to_bytes(&self) -> Vec<u8>; |
||||
fn proof_to_bytes(proof: &Self::Proof) -> Vec<u8>; |
||||
fn id_from_bytes(id_bytes: &[u8]) -> Result<Self, ()>; |
||||
fn proof_from_bytes(proof_bytes: &[u8]) -> Result<Self::Proof, ()>; |
||||
} |
||||
|
||||
/// common data structure.
|
||||
#[derive(Clone, Eq, PartialEq)] |
||||
pub struct Data<T: OwnerId> { |
||||
/// Data unique ID, default generate method is other fields hash.
|
||||
pub did: DataId, |
||||
/// ParentID, default is None.
|
||||
pub pid: Option<DataId>, |
||||
/// time lifetime, (from, to) timestamp.
|
||||
pub time: (i64, i64), |
||||
/// Owner's info.
|
||||
pub owner: T, |
||||
/// data owner proof. it can verify by owner.
|
||||
pub proof: T::Proof, |
||||
/// MIME type, and value bytes.
|
||||
pub value: (String, Vec<u8>), |
||||
} |
||||
|
||||
impl<T: OwnerId> Data<T> { |
||||
pub fn to_bytes(&self) -> Vec<u8> { |
||||
let mut bytes = vec![]; |
||||
bytes.extend_from_slice(&self.did); |
||||
if let Some(p) = self.pid { |
||||
bytes.extend_from_slice(&p); |
||||
} else { |
||||
bytes.extend_from_slice(&[0u8; 32]); |
||||
} |
||||
bytes.extend_from_slice(&mut self.time.0.to_le_bytes()); |
||||
bytes.extend_from_slice(&mut self.time.1.to_le_bytes()); |
||||
bytes.extend_from_slice(&mut self.owner.id_to_bytes()); |
||||
bytes.extend_from_slice(&mut T::proof_to_bytes(&self.proof)); |
||||
|
||||
let mut mime_bytes = self.value.0.as_bytes(); |
||||
bytes.extend_from_slice(&mut (mime_bytes.len() as u32).to_le_bytes()); |
||||
bytes.extend_from_slice(&mut mime_bytes); |
||||
bytes.extend_from_slice(&self.value.1); |
||||
|
||||
bytes |
||||
} |
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ()> { |
||||
if bytes.len() < 84 + T::len() + T::proof_len() { |
||||
return Err(()); |
||||
} |
||||
|
||||
let mut did_bytes = [0u8; 32]; |
||||
did_bytes.copy_from_slice(&bytes[0..32]); |
||||
let mut pid_bytes = [0u8; 32]; |
||||
pid_bytes.copy_from_slice(&bytes[32..64]); |
||||
let pid = if pid_bytes == [0u8; 32] { |
||||
None |
||||
} else { |
||||
Some(pid_bytes) |
||||
}; |
||||
let mut start_bytes = [0u8; 8]; |
||||
start_bytes.copy_from_slice(&bytes[64..72]); |
||||
let start_time = i64::from_le_bytes(start_bytes); |
||||
|
||||
let mut end_bytes = [0u8; 8]; |
||||
end_bytes.copy_from_slice(&bytes[72..80]); |
||||
let end_time = i64::from_le_bytes(end_bytes); |
||||
|
||||
let owner = T::id_from_bytes(&bytes[80..])?; |
||||
let proof = T::proof_from_bytes(&bytes[80 + T::len()..])?; |
||||
|
||||
let m_l = 80 + T::len() + T::proof_len(); |
||||
let mut mime_len_bytes = [0u8; 4]; |
||||
mime_len_bytes.copy_from_slice(&bytes[m_l..m_l + 4]); |
||||
let mime_len = u32::from_le_bytes(mime_len_bytes) as usize; |
||||
let last = &bytes[m_l + 4..]; |
||||
if last.len() < mime_len { |
||||
return Err(()); |
||||
} |
||||
let v_t = std::str::from_utf8(&last[0..mime_len]) |
||||
.map_err(|_| ())? |
||||
.to_owned(); |
||||
let v_v = last[mime_len..].to_vec(); |
||||
|
||||
Ok(Self { |
||||
pid, |
||||
owner, |
||||
proof, |
||||
did: did_bytes, |
||||
value: (v_t, v_v), |
||||
time: (start_time, end_time), |
||||
}) |
||||
} |
||||
} |
||||
|
||||
#[cfg(feature = "tdn")] |
||||
pub mod tdn; |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
use tdn_did::{Proof, PROOF_LENGTH}; |
||||
use tdn_types::group::{GroupId, GROUP_LENGTH}; |
||||
|
||||
use crate::{Data, OwnerId}; |
||||
|
||||
impl OwnerId for GroupId { |
||||
type Proof = Proof; |
||||
|
||||
fn len() -> usize { |
||||
PROOF_LENGTH |
||||
} |
||||
|
||||
fn proof_len() -> usize { |
||||
GROUP_LENGTH |
||||
} |
||||
|
||||
fn verify(&self, data: &Data<Self>) -> bool { |
||||
data.proof |
||||
.verify_bytes(&data.owner, &data.to_bytes()) |
||||
.is_ok() |
||||
} |
||||
|
||||
fn id_to_bytes(&self) -> Vec<u8> { |
||||
self.0.to_vec() |
||||
} |
||||
|
||||
fn proof_to_bytes(proof: &Self::Proof) -> Vec<u8> { |
||||
proof.0.clone() |
||||
} |
||||
|
||||
fn id_from_bytes(id_bytes: &[u8]) -> Result<Self, ()> { |
||||
if id_bytes.len() >= GROUP_LENGTH { |
||||
let mut bytes = [0u8; GROUP_LENGTH]; |
||||
bytes.copy_from_slice(&id_bytes[0..GROUP_LENGTH]); |
||||
Ok(GroupId(bytes)) |
||||
} else { |
||||
Err(()) |
||||
} |
||||
} |
||||
|
||||
fn proof_from_bytes(proof_bytes: &[u8]) -> Result<Self::Proof, ()> { |
||||
if proof_bytes.len() >= PROOF_LENGTH { |
||||
let bytes = proof_bytes[0..PROOF_LENGTH].to_vec(); |
||||
Ok(Proof(bytes)) |
||||
} else { |
||||
Err(()) |
||||
} |
||||
} |
||||
} |
||||
|
||||
pub type TdnData = Data<GroupId>; |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
[package] |
||||
name = "domain_types" |
||||
version = "0.1.0" |
||||
authors = ["CympleTech <dev@cympletech.com>"] |
||||
edition = "2021" |
||||
readme = "README.md" |
||||
description = "ESSE domain service types." |
||||
repository = "https://github.com/cympletech/esse_types/group" |
||||
keywords = ["distributed", "p2p", "domain", "ESSE"] |
||||
license = "MIT/Apache-2.0" |
||||
|
||||
[dependencies] |
||||
serde = { version = "1", features = ["derive"] } |
||||
tdn_types = { version = "0.6", default-features = false } |
||||
tdn_did = { version = "0.6", default-features = false } |
||||
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
use serde::{Deserialize, Serialize}; |
||||
use tdn_did::Proof; |
||||
use tdn_types::{group::GroupId, primitive::PeerId}; |
||||
|
||||
// Same ID can has many name !.
|
||||
|
||||
/// Group chat app(service) default TDN GROUP ID.
|
||||
#[rustfmt::skip] |
||||
pub const DOMAIN_ID: GroupId = GroupId([ |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 4, |
||||
]); |
||||
|
||||
/// ESSE domain service layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerServerEvent(pub ServerEvent, pub Proof); |
||||
|
||||
/// ESSE domain service layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerPeerEvent(pub PeerEvent, pub Proof); |
||||
|
||||
/// ESSE domain service to peer layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum ServerEvent { |
||||
/// check result status.
|
||||
/// params: provider name, is support request proxy.
|
||||
Status(String, bool), |
||||
/// register result.
|
||||
/// params: name, is_ok.
|
||||
Result(String, bool), |
||||
/// a identity info.
|
||||
/// params: user_name, user_ID, user_address, user_bio, user_avatar.
|
||||
Info(String, GroupId, PeerId, String, Vec<u8>), |
||||
/// not found a user by name.
|
||||
None(String), |
||||
/// current name is active.
|
||||
/// params: name, is_actived
|
||||
Actived(String, bool), |
||||
/// current name is deleted.
|
||||
/// params: name.
|
||||
Deleted(String), |
||||
/// response the make friend.
|
||||
/// params: remote_ID, name, is_ok.
|
||||
Response(GroupId, String, bool), |
||||
} |
||||
|
||||
/// ESSE domain peer to service layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum PeerEvent { |
||||
/// check service status is ok.
|
||||
Check, |
||||
/// register new unique identity to service.
|
||||
/// params: name, bio, avatar.
|
||||
Register(String, String, Vec<u8>), |
||||
/// update user info.
|
||||
/// params: name, bio, avatar.
|
||||
Update(String, String, Vec<u8>), |
||||
/// search a identity info.
|
||||
/// params: name.
|
||||
Search(String), |
||||
/// make a friend request,
|
||||
/// params: remote_name, my_name, request_remark.
|
||||
Request(String, String, String), |
||||
/// suspend the name.
|
||||
/// params: name.
|
||||
Suspend(String), |
||||
/// active the name.
|
||||
/// params: name.
|
||||
Active(String), |
||||
/// delete the name.
|
||||
/// params: name.
|
||||
Delete(String), |
||||
} |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
[package] |
||||
name = "group_types" |
||||
version = "0.1.0" |
||||
authors = ["Contact <contact@cypherlink.io>"] |
||||
edition = "2021" |
||||
readme = "README.md" |
||||
description = "ESSE group chat service types." |
||||
repository = "https://github.com/cympletech/esse_types/group" |
||||
keywords = ["distributed", "p2p", "group chat", "ESSE"] |
||||
license = "MIT/Apache-2.0" |
||||
|
||||
[dependencies] |
||||
chat_types = { path = "../chat", version = "0.1" } |
||||
serde = { version = "1", features = ["derive"] } |
||||
tdn_types = { version = "0.6", default-features = false } |
||||
tdn_did = { version = "0.6", default-features = false } |
||||
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
use serde::{Deserialize, Serialize}; |
||||
use tdn_did::Proof; |
||||
use tdn_types::{group::GroupId, primitive::PeerId}; |
||||
|
||||
use chat_types::NetworkMessage; |
||||
|
||||
/// Group chat app(service) default TDN GROUP ID.
|
||||
#[rustfmt::skip] |
||||
pub const GROUP_CHAT_ID: GroupId = GroupId([ |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 2, |
||||
]); |
||||
|
||||
/// Group chat connect data structure.
|
||||
/// params: Group ID, join_proof.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerConnect(pub GroupId, pub Proof); |
||||
|
||||
/// Group chat connect success result data structure.
|
||||
/// params: Group ID, group name, group current height.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub struct LayerResult(pub GroupId, pub String, pub i64); |
||||
|
||||
/// ESSE Group chat app's layer Event.
|
||||
#[derive(Serialize, Deserialize)] |
||||
pub enum LayerEvent { |
||||
/// offline. as BaseLayerEvent.
|
||||
Offline(GroupId), |
||||
/// suspend. as BaseLayerEvent.
|
||||
Suspend(GroupId), |
||||
/// actived. as BaseLayerEvent.
|
||||
Actived(GroupId), |
||||
/// online group member. Group ID, member id, member address.
|
||||
MemberOnline(GroupId, GroupId, PeerId), |
||||
/// offline group member. Group ID, member id.
|
||||
MemberOffline(GroupId, GroupId), |
||||
/// sync online members.
|
||||
MemberOnlineSync(GroupId), |
||||
/// sync online members result.
|
||||
MemberOnlineSyncResult(GroupId, Vec<(GroupId, PeerId)>), |
||||
/// Change the group name.
|
||||
GroupName(GroupId, String), |
||||
/// close the group chat.
|
||||
GroupClose(GroupId), |
||||
/// sync group event. Group ID, height, event.
|
||||
Sync(GroupId, i64, Event), |
||||
/// peer sync event request. Group ID, from.
|
||||
SyncReq(GroupId, i64), |
||||
/// sync members status.
|
||||
/// Group ID, current height, from height, to height,
|
||||
/// add members(height, member id, addr, name, avatar),
|
||||
/// leaved members(height, member id),
|
||||
/// add messages(height, member id, message, time).
|
||||
SyncRes( |
||||
GroupId, |
||||
i64, |
||||
i64, |
||||
i64, |
||||
Vec<(i64, GroupId, PeerId, String, Vec<u8>)>, |
||||
Vec<(i64, GroupId)>, |
||||
Vec<(i64, GroupId, NetworkMessage, i64)>, |
||||
), |
||||
} |
||||
|
||||
impl LayerEvent { |
||||
/// get event's group id.
|
||||
pub fn gcd(&self) -> &GroupId { |
||||
match self { |
||||
Self::Offline(gcd) => gcd, |
||||
Self::Suspend(gcd) => gcd, |
||||
Self::Actived(gcd) => gcd, |
||||
Self::MemberOnline(gcd, ..) => gcd, |
||||
Self::MemberOffline(gcd, ..) => gcd, |
||||
Self::MemberOnlineSync(gcd) => gcd, |
||||
Self::MemberOnlineSyncResult(gcd, ..) => gcd, |
||||
Self::GroupName(gcd, ..) => gcd, |
||||
Self::GroupClose(gcd) => gcd, |
||||
Self::Sync(gcd, ..) => gcd, |
||||
Self::SyncReq(gcd, ..) => gcd, |
||||
Self::SyncRes(gcd, ..) => gcd, |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// Group chat event.
|
||||
#[derive(Serialize, Deserialize, Clone)] |
||||
pub enum Event { |
||||
/// params: member id, member address, member name, member avatar.
|
||||
MemberJoin(GroupId, PeerId, String, Vec<u8>), |
||||
/// params: member id,
|
||||
MemberLeave(GroupId), |
||||
/// params: member id, message, message time.
|
||||
MessageCreate(GroupId, NetworkMessage, i64), |
||||
} |
||||
Loading…
Reference in new issue