---
# System prepended metadata

title: node-to-node file share
tags: [Kizuna-architecture]

---

# node-to-node file share
###### tags: `Kizuna-architecture`
<style> .ui-infobar, #doc.markdown-body { max-width: 2000px; } </style>

## User Stories
- [As a user, I want to send files to a chat so that I can share my files.](https://beyonder.atlassian.net/browse/KIZUNA-63)
- [As a user, I want to send media files to a chat so that I can share my images/videos.](https://beyonder.atlassian.net/browse/KIZUNA-64)
- [As a user, I want to send voice notes to a chat/groupchat so that I can share that voice note](https://beyonder.atlassian.net/browse/KIZUNA-65)
- [I want to be notified of incoming file attachment message so I know that someone sent me a file](https://beyonder.atlassian.net/browse/KIZUNA-371)
- [I want to see media files sent to the chat so that I can check what they sent.](https://beyonder.atlassian.net/browse/KIZUNA-61)
- [I want to see shared files/media in a chat/group chat so that I can browse through previously sent files.](https://beyonder.atlassian.net/browse/KIZUNA-96)
- [I want to download files sent to the chat so that I can have it locally.](https://beyonder.atlassian.net/browse/KIZUNA-60)
- [I want to choose whether to auto download files/media ](https://beyonder.atlassian.net/browse/KIZUNA-331)(maybe move to preference?)
- [I want to choose whether to have preview of files/media](https://beyonder.atlassian.net/browse/KIZUNA-332)(maybe move to preference?)

## Notes
* 16Mb file size limit
* will become similar to P2PMessage
* chunking and DHT storage can be done for group file sending

## Entry Relationship Diagram
```mermaid
graph LR
    subgraph p2pmessage zome
        subgraph agents
            alice
            bobby
        end
        subgraph file chunks in DHT
            file_chunk_1
            file_chunk_2
            file_chunk_n
        end
        subgraph file metadata in source chains
            file_metadata_1
            alice.->|has in source chain|file_metadata_1
            bobby.->|has in source chain|file_metadata_1
            
            file_metadata_1.->file_chunk_1
            file_metadata_1.->file_chunk_2
            file_metadata_1.->file_chunk_n
        end
        
  end
```



## File Sharing (Using external chunking)

### Comments and Questions
* Is it safe storing chunks of files in DHT?
    * prolly not
    * maybe if we do encryption on chunks
* For synchronous comms, do we do encyrption or is it redundant because of QUIC? How about on Holo? is local device to HoloPort encrypted also?
* Is looping through chunks in the UI and calling a zome function per chunk efficient?
    * What is the size limit per call to a zome function from the UI? 
    * May provide an advantage in error recovery midway through uploads
* TODO: Asynchronous file sending
* Would be better if we can just send the chunks through call_remote
* No ecnryption design yet
* Guillem: seems prone to attacks; can we commit entry in DHT and just and send the link

### Entry Structure
```rust=
#[hdk_entry(id="file_metadata", visibility="private")]
struct FileMetadata {
   author: AgentPubKey,
   receiver: AgentPubKey,
   file_name: String,
   file_size: usize,
   file_type: String,
   time_sent: Timestamp,
   time_received: Option<Timestamp>,
   chunks: Vec<EntryHash> // addresses of each chunk in the DHT
}

#[hdk_entry(id="file_chunk", visibility="public")]
struct FileChunk(Vec<u8>);

pub struct FileMetadataOutput {
    author: AgentPubKey,
    receiver: AgentPubKey,
    file_name: String,
    file_size: usize,
    file_type: String,
    time_sent: Timestamp,
    time_received: Option<Timestamp>,
    chunks: Vec<EntryHash>
}

pub struct FileInput {
    pub receiver: AgentPubKey,
    pub file_name: String,
    pub file_size: usize,
    pub file_type: String,
    pub chunks: Vec<EntryHash>,
    pub hash: String
}

```

```mermaid
sequenceDiagram
    participant AUI as Alice_UI
    participant ACD as Alice_Conversation_Cell
    
    AUI-->>AUI: chunk file
    AUI-->>AUI: construct empty metadata struct
    loop for all file chunks
        rect rgba(0,255,0,0.5)
            AUI-->>ACD: call `upload_chunk`
            ACD-->>AUI: return chunk address in DHT
        end
            AUI-->>AUI: add chunk address to metadata
    end
    AUI-->>AUI: generate hash of entire file
    AUI-->>AUI: add file hash to metadata
    rect rgba(0,255,0,0.5)
        AUI-->>ACD: call `send_file`
        ACD-->>AUI: return FileMetadata
    end
```

## Zome functions
### upload_chunk
```rust=
// Function to commit a chunk of a file into the DHT. 
// Called iteratively in the front-end  over the chunks of a file.
pub(crate) fn upload_chunk(
    file_chunk_input: FileChunk
) -> ExternResult<EntryHash>
```

```mermaid
sequenceDiagram
    participant AUI as Alice_UI
    participant ACD as Alice_Conversation_Cell
    participant DHT as DHT
    
    ACD-->>ACD: construct FileChunk entry
    ACD-->>DHT: commit entry to DHT
    DHT-->>ACD: return address
    ACD-->>AUI: return address of FileChunk in DHT
    
```
### send_file
```rust=
// Function to send the file metadata synchronously from one agent to another.
pub(crate) fn send_file(
    file_input: FileInput
) -> ExternResult<FileMetadataOption>
```
```mermaid
sequenceDiagram
    participant AUI as Alice_UI
    participant ACD as Alice_Conversation_Cell
    participant BCD as Bobby_Conversation_Cell
    participant DHT as DHT

    
    loop for all chunk addresses
        rect rgba(0,0,255,0.3)
            ACD-->>DHT: call `get_bytes_from_chunks`
        end
        DHT-->>ACD: return file bytes 
    end
    ACD-->>ACD: compute file hash from bytes
    
    alt computed file hash != input file hash
        ACD-->>AUI: return error "file integrity check failed"
    else computed file hash = input file hash
        rect rgba(0,255,0,0.5)
            ACD-->>BCD: call_remote `receive_file_metadata`
            BCD-->>ACD: return call_remote result
        end
        alt call_remote ok
            ACD-->>ACD: construct FileMetadata entry
            ACD-->>ACD: commit FileMetadata entry to source chain
        else call_remote timeout
            Note over ACD: TODO: async case
        else call_remote unauthorized
            ACD-->>AUI: return error "No proper authorization"
        end
    end
```

### get_bytes_from_chunks
```rust=
// internal helper function
pub fn get_bytes_from_chunks(
    chunks_hashes: Vec<EntryHash>
) -> ExternResult<Vec<u8>>
```
```mermaid
sequenceDiagram
    participant ACD as Alice_Conversation_Cell
    participant DHT as DHT

    loop for all chunk addresses
        rect rgba(0,0,255,0.3)
            ACD-->>DHT: call `get_file_chunk`
        end
        DHT-->>ACD: return file chunk bytes
    end
    ACD-->>ACD: assemble file from bytes
    ACD-->>ACD: return file_bytes
```

### get_file_chunk
```rust=
// internal helper function
pub fn get_file_chunk(
    file_chunk_hash: FileChunk
) -> ExternResult<EntryHash>
```
```mermaid
sequenceDiagram
    participant ACD as Alice_Conversation_Cell
    participant DHT as DHT

    ACD-->>DHT: get entry of file chunk in DHT
    DHT-->>ACD: return entry
```


### receive_file_metadata
```rust=
pub(crate) fn receive_file_metadata(
    metadata_input: FileMetadataOutput
) -> ExternResult<FileMetadataOption>
```
```mermaid
sequenceDiagram
    participant ACD as Alice_Conversation_Cell
    participant BCD as Bobby_Conversation_Cell
    
    BCD-->>BCD: construct FileMetdataEntry
    BCD-->>BCD: generate and add timestamp to time_received field of FileMetadataEntry
    BCD-->>BCD: commit entry to source chain
    BCD-->>BCD: construct FileMetadataOutput from entry
    BCD-->>BUI: emit signal "file has been received"
    BCD-->>ACD: return FileMetadataOutput
```


## Validation
### Entries
### Links


