Rust implementation of NextGraph, a Decentralized and local-first web 3.0 ecosystem https://nextgraph.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nextgraph-rs/ng-verifier/src/types.rs

435 lines
12 KiB

// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
//! Types for Verifier
use core::fmt;
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
//use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
//use oxigraph::store::Store;
//use oxigraph::model::GroundQuad;
//use yrs::{StateVector, Update};
use ng_repo::{errors::NgError, types::*};
use ng_net::types::*;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum SessionPeerLastSeq {
V0(u64),
V1((u64, Sig)),
}
impl SessionPeerLastSeq {
pub fn ser(&self) -> Result<Vec<u8>, NgError> {
Ok(serde_bare::to_vec(self)?)
}
pub fn deser(ser: &[u8]) -> Result<Self, NgError> {
Ok(serde_bare::from_slice(ser).map_err(|_| NgError::SerializationError)?)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VerifierType {
/// nothing will be saved on disk during the session
Memory,
/// will save all user data locally, with RocksDb backend on native, and on webapp, will save only the session and wallet, not the data itself
Save,
/// the verifier will be remote. a Noise connection will be opened
/// optional peerId to connect to. If None, will try any that has the flag `can_verify`
Remote(Option<PubKey>),
/// IndexedDb based rocksdb compiled to WASM... not ready yet. obviously. only works in the browser
WebRocksDb,
// Server, this type is for Server Broker that act as verifier. They answer to VerifierType::Remote types of verifier. deprecated
}
impl VerifierType {
pub fn is_memory(&self) -> bool {
match self {
Self::Memory => true,
_ => false,
}
}
pub fn is_persistent(&self) -> bool {
match self {
Self::Save => true,
_ => false,
}
}
}
//type LastSeqFn = fn(peer_id: PubKey, qty: u16) -> Result<u64, NgError>;
pub type LastSeqFn = dyn Fn(PubKey, u16) -> Result<u64, NgError> + 'static + Sync + Send;
// peer_id: PubKey, seq_num:u64, event_ser: vec<u8>,
pub type OutboxWriteFn =
dyn Fn(PubKey, u64, Vec<u8>) -> Result<(), NgError> + 'static + Sync + Send;
// peer_id: PubKey,
pub type OutboxReadFn = dyn Fn(PubKey) -> Result<Vec<Vec<u8>>, NgError> + 'static + Sync + Send;
pub struct JsSaveSessionConfig {
pub last_seq_function: Box<LastSeqFn>,
pub outbox_write_function: Box<OutboxWriteFn>,
pub outbox_read_function: Box<OutboxReadFn>,
}
impl fmt::Debug for JsSaveSessionConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "JsSaveSessionConfig")
}
}
#[derive(Debug)]
pub enum VerifierConfigType {
/// nothing will be saved on disk during the session
Memory,
/// only the session information is saved locally. the UserStorage is not saved.
JsSaveSession(JsSaveSessionConfig),
/// will save all user data locally, with RocksDb backend
RocksDb(PathBuf),
/// the verifier will be remote. a Noise connection will be opened
/// optional peerId to connect to. If None, will try any that has the flag `can_verify`
/// // TODO: Pass the AppConfig
Remote(Option<PubKey>),
/// IndexedDb based rocksdb compiled to WASM... not ready yet. obviously. only works in the browser
WebRocksDb,
}
impl VerifierConfigType {
pub(crate) fn should_load_last_seq_num(&self) -> bool {
match self {
Self::JsSaveSession(_) | Self::RocksDb(_) => true,
_ => false,
}
}
pub(crate) fn is_persistent(&self) -> bool {
match self {
Self::RocksDb(_) => true,
_ => false,
}
}
#[allow(dead_code)]
pub(crate) fn is_in_memory(&self) -> bool {
match self {
Self::Memory | Self::JsSaveSession(_) => true,
_ => false,
}
}
}
#[derive(Debug)]
pub struct VerifierConfig {
pub config_type: VerifierConfigType,
/// not used for Memory
pub user_master_key: [u8; 32],
/// not used for Memory
pub peer_priv_key: PrivKey,
pub user_priv_key: PrivKey,
pub private_store_read_cap: Option<ObjectRef>,
pub private_store_id: Option<RepoId>,
pub public_store_id: Option<RepoId>,
pub protected_store_id: Option<RepoId>,
}
pub type CancelFn = Box<dyn FnOnce() + Sync + Send>;
//
// APP PROTOCOL (between APP and VERIFIER)
//
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppFetchContentV0 {
Get, // does not subscribe. more to be detailed
Subscribe, // more to be detailed
Update,
//Invoke,
ReadQuery, // more to be detailed
WriteQuery, // more to be detailed
}
impl AppFetchContentV0 {
pub fn get_or_subscribe(subscribe: bool) -> Self {
if !subscribe {
AppFetchContentV0::Get
} else {
AppFetchContentV0::Subscribe
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NgAccessV0 {
ReadCap(ReadCap),
Token(Digest),
#[serde(with = "serde_bytes")]
ExtRequest(Vec<u8>),
Key(BlockKey),
Inbox(Digest),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum TargetBranchV0 {
Chat,
Stream,
Context,
Ontology,
BranchId(BranchId),
Named(String), // branch or commit
Commits(Vec<ObjectId>), // only possible if access to their branch is given. must belong to the same branch.
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NuriTargetV0 {
UserSite, // targets the whole data set of the user
PublicStore,
ProtectedStore,
PrivateStore,
AllDialogs,
Dialog(String), // shortname of a Dialog
AllGroups,
Group(String), // shortname of a Group
Repo(RepoId),
Identity(UserId),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NuriV0 {
pub target: NuriTargetV0,
pub entire_store: bool, // If it is a store, will (try to) include all the docs belonging to the store
pub object: Option<ObjectId>, // used only for FileGet. // cannot be used for queries. only to download an object (file,commit..)
pub branch: Option<TargetBranchV0>, // if None, the main branch is chosen
pub overlay: Option<OverlayLink>,
pub access: Vec<NgAccessV0>,
pub topic: Option<TopicId>,
pub locator: Vec<PeerAdvert>,
}
impl NuriV0 {
pub fn new_repo_target_from_string(repo_id_string: String) -> Result<Self, NgError> {
let repo_id: RepoId = repo_id_string.as_str().try_into()?;
Ok(Self {
target: NuriTargetV0::Repo(repo_id),
entire_store: false,
object: None,
branch: None,
overlay: None,
access: vec![],
topic: None,
locator: vec![],
})
}
pub fn new_private_store_target() -> Self {
Self {
target: NuriTargetV0::PrivateStore,
entire_store: false,
object: None,
branch: None,
overlay: None,
access: vec![],
topic: None,
locator: vec![],
}
}
pub fn new(_from: String) -> Self {
todo!();
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppRequestCommandV0 {
Fetch(AppFetchContentV0),
Pin,
UnPin,
Delete,
Create,
FileGet, // needs the Nuri of branch/doc/store AND ObjectId
FilePut, // needs the Nuri of branch/doc/store
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AppRequestV0 {
pub command: AppRequestCommandV0,
pub nuri: NuriV0,
pub payload: Option<AppRequestPayload>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppRequest {
V0(AppRequestV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum DocQuery {
V0(String), // Sparql
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GraphUpdate {
add: Vec<String>,
remove: Vec<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum DiscreteUpdate {
/// A yrs::Update
#[serde(with = "serde_bytes")]
YMap(Vec<u8>),
#[serde(with = "serde_bytes")]
YXml(Vec<u8>),
#[serde(with = "serde_bytes")]
YText(Vec<u8>),
/// An automerge::Patch
#[serde(with = "serde_bytes")]
Automerge(Vec<u8>),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DocUpdate {
heads: Vec<ObjectId>,
graph: Option<GraphUpdate>,
discrete: Option<DiscreteUpdate>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DocAddFile {
pub filename: Option<String>,
pub object: ObjectRef,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DocCreate {
store: StoreRepo,
content_type: BranchContentType,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DocDelete {
/// Nuri of doc to delete
nuri: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppRequestPayloadV0 {
Create(DocCreate),
Query(DocQuery),
Update(DocUpdate),
AddFile(DocAddFile),
//RemoveFile
Delete(DocDelete),
//Invoke(InvokeArguments),
SmallFilePut(SmallFile),
RandomAccessFilePut(String), // content_type
RandomAccessFilePutChunk((u32, serde_bytes::ByteBuf)), // end the upload with an empty vec
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppRequestPayload {
V0(AppRequestPayloadV0),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum DiscretePatch {
/// A yrs::Update
#[serde(with = "serde_bytes")]
YMap(Vec<u8>),
#[serde(with = "serde_bytes")]
YXml(Vec<u8>),
#[serde(with = "serde_bytes")]
YText(Vec<u8>),
/// An automerge::Patch
#[serde(with = "serde_bytes")]
Automerge(Vec<u8>),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GraphPatch {
/// oxigraph::model::GroundQuad serialized to n-quads with oxrdfio
pub adds: Vec<String>,
pub removes: Vec<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum DiscreteState {
/// A yrs::StateVector
#[serde(with = "serde_bytes")]
YMap(Vec<u8>),
#[serde(with = "serde_bytes")]
YXml(Vec<u8>),
#[serde(with = "serde_bytes")]
YText(Vec<u8>),
// the output of Automerge::save()
#[serde(with = "serde_bytes")]
Automerge(Vec<u8>),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GraphState {
pub tuples: Vec<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AppState {
heads: Vec<ObjectId>,
graph: Option<GraphState>, // there is always a graph present in the branch. but it might not have been asked in the request
discrete: Option<DiscreteState>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AppPatch {
heads: Vec<ObjectId>,
graph: Option<GraphPatch>,
discrete: Option<DiscretePatch>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FileName {
pub heads: Vec<ObjectId>,
pub name: Option<String>,
pub reference: ObjectRef,
pub nuri: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FileMetaV0 {
pub content_type: String,
pub size: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppResponseV0 {
State(AppState),
Patch(AppPatch),
Text(String),
File(FileName),
FileUploading(u32),
FileUploaded(ObjectRef),
#[serde(with = "serde_bytes")]
FileBinary(Vec<u8>),
FileMeta(FileMetaV0),
QueryResult, // see sparesults
Ok,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum AppResponse {
V0(AppResponseV0),
}