139 views
# Message Identity Specifications (Draft v2) **Note: preceded by** [**Draft v1**](https://notes.status.im/CQ-GGYmAR3aM8qUABgedWg?both) The following specification details the methods and processes to handle user defined identity data, including: - ENS name data - Display name data - Profile image data ## Table of contents [toc] ## Protobuf structure ```protobuf // ChatIdentity represents the user defined identity associated with their public chat key message ChatIdentity { // Lamport timestamp of the chat message uint64 clock = 1; // ens_name is the valid ENS name associated with the chat key string ens_name = 2; // display_name is the user's chosen display name string display_name = 3; // profile_image is the image payload data string profile_image_payload = 4; } ``` ## JSON Examples **Display name with profile image** ```json { "identity": { "display_name": "lilblockchainz", "profile_image_payload": "QmR7GSQM93Cx5eAg6a6yRzNde1FQv7uL6X1o4k7zrJa3LX" } } ``` **ENS name with profile image** ```json { "identity": { "ens_name": "lilblockchainz.eth", "profile_image_payload": "QmR7GSQM93Cx5eAg6a6yRzNde1FQv7uL6X1o4k7zrJa3LX" } } ``` **No display name (defaults to random 3 word) with profile image** ```json { "identity": { "profile_image_payload": "QmR7GSQM93Cx5eAg6a6yRzNde1FQv7uL6X1o4k7zrJa3LX" } } ``` **Display name with no profile image (defaults to identicon)** ```json { "identity": { "display_name": "lilblockchainz" } } ``` **No message identity (defaults to random 3 word and identicon)** ```json { "ChatMessage": { "text": "Hey there!" } } ``` **Empty template** ```json { "identity": { "ens_name": "", "display_name": "", "profile_image_payload": "" } } ``` ## Persistence ### User's identity data ```sql CREATE TABLE IF NOT EXISTS chat_identity ( id INT PRIMARY KEY ON CONFLICT REPLACE, /* user's verified ENS name */ ens_name VARCHAR, /* user's display name */ display_name VARCHAR, /* profile image payload */ profile_image_payload VARCHAR, /* profile image source. The URL or IPFS address of the image file. */ profile_image_source VARCHAR, /* profile image source type, the ID of the source that the user chose */ /* UNKNOWN_SOURCE_TYPE = 0; // ENS_AVATAR uses the ENS record's resolver get-text-data.avatar data // if `source` is empty inspect record // if `source` is set use source URL // The parent `ChatMessageIdentity` must have a valid `ens_name` set ENS_AVATAR = 1; // IPFS_ADDRESS uses IPFS to get the image data // 'source' must be set // `source` is an IPFS address IPFS_ADDRESS = 2; // URL_ADDRESS uses a standard internet URL to the image data // `source` must be set // `source` is a URL URL_ADDRESS = 3; // RAW_PAYLOAD uses base64 encoded image data // `source` must be set // `source` is base64 encoded image data RAW_PAYLOAD = 4; */ profile_image_source_type INT, /* The last time that the profile image source was checked for changes */ profile_image_last_updated TIME, /* Option whether to use a chat identity */ active BOOL ); ``` ### Other user's (correspondants) identity data To efficiently handle identity data of messages from other identities the device should implement persistence. #### `contacts` **Note:** Update the existing `contacts` table to handle persistence ```sql CREATE TABLE IF NOT EXISTS message_identities ( /* chat_key the message author's public chat key, used as the index*/ chat_key VARCHAR PRIMARY KEY ON CONFLICT REPLACE, /* identity_hash the sha256 hash of the parsed ChatIdentity */ identity_hash VARCHAR NOT NULL, /* last_clock is the clock value of the last unique ChatIdentity hash,*/ /* used to determine which identity data should be given priority if */ /* the message sender changes their data multiple times since the last */ /* message pull */ last_clock INT, /* ens_name a valid ENS name associated with the user's chat key */ ens_name VARCHAR, /* display_name the given display name */ display_name VARCHAR, /* profile_image_payload the profile image payload data */ profile_image_payload VARCHAR ); ``` **`identity_hash`** The `identity_hash` is a sha256 hash of the parsed ChatIdentity protobuf, used to make checking for identity changes simple. #### `chats` Update to the `chats` table to include a new field `last_identity_clock`, this field will be used to track when the device has last sent a `ChatIdentity` message. Used for calculating if a `ChatIdentity` resend is required. ## Security precautions Any images that are sourced from remote sources will be downloaded to the local device of the user that wishes to use them as a source of their profile image. Sanitise and cache all images to be displayed by the device. ## Process flows ### Chat visualisation ```mermaid graph LR %% Intities subgraph chat [DeFi] m1(0x12e4... Hey):::u1 ci1[ChatIdentity 0x12e4...]:::ci m2(0xab3d... How are you?):::u2 ci2[ChatIdentity 0xab3d...]:::ci m3(0x12e4... I'm ok thanks):::u1 m4(0xab3d... Cool, do want to do some DeFi?):::u2 m5(0x12e4... Yeah, I've got my wallet loaded):::u1 m6(0x12e4... I'll ask my friend too):::u1 m7(0xab3d... Ok, that's great!):::u2 m8(0x98f6... Hey, I've got some DAO votes):::u3 ci3[ChatIdentity 0x98f6...]:::ci m9(0xab3d... Alright!):::u2 seg1[________ 2 days later ________] m10(0x12e4... Man! We made some mad gains):::u1 m11(0xab3d... Hell yeah, we did!):::u2 m12(0x98f6... I'm gunna invest in some cryptokitties):::u3 m13(0x12e4... What?! Wait!):::u1 m14(0x98f6... Don't stress):::u3 m15(0x1337... I've got some kitties for you):::u4 ci4[ChatIdentity 0x1337...]:::ci m16(0x98f6... Show me what you've got):::u3 seg2[________ 1 week later ________] m17(0xab3d... So Much CRYPTO!):::u2 ci7[ChatIdentity 0xab3d...]:::ci m18(0x12e4... Oh yeah, No FOMO 10x mo000o0o0oon):::u1 ci8[ChatIdentity 0x12e4...]:::ci m19(0x1337... Wanna get into the kittie game?):::u4 ci9[ChatIdentity 0x1337...]:::ci m20(0x12e4... Are kitties even Defi?):::u1 m21(0xab3d... Are they even legal):::u2 m22(0x1337... 100% ask your buddy):::u4 m23(0x98f6... Hey. You got anymore of that Eth?):::u3 ci10[ChatIdentity 0x98f6...]:::ci m24(0x98f6... I just need to hatch one more kittie):::u3 m25(0x98f6... That's all I need, just send me 0.1 Eth):::u3 m26(0x98f6... I'm good for it.):::u3 m27(0x98f6... I'm gunna need some eth for the gas too):::u3 seg3[________ 2 hours later ________] m28(0x98f6... guys?):::u3 end %% Styles / Classes classDef u1 fill:#afa classDef u2 fill:#aff classDef u3 fill:#ffa classDef u4 fill:#faa classDef ci fill:#bbf,color:#fff,stroke-dasharray: 5 5 ``` ### Setting Identity process flow ```mermaid graph TB %% Intities user((User)) subgraph status [Status App] subgraph status-react UI{UI} end subgraph status-go db[(db - chat_identity)] int[Chat identity management service] pims[Profile image management service] API[Chat identity management API Endpoint] end end ipfs{{IPFS}} ENS{{ENS avatar}} url[Remote server] disk[Local disk] %% Connections user -->|Step 1| UI UI -->|Step 2| API API -->|Step 3| int int -->|Step 4| pims pims -->|Optional| ipfs pims -->|Optional| ENS pims -->|Optional| url pims -->|Optional| disk int -->|Step 5| db ``` 1. User sets any of the following identity information - ENS name - Display name - Profile image source (if any) - Local device disk - URL - IPFS Address - ENS avatar 2. Identity data is sent to the `status-go` Chat Identity management API endpoint 3. API sends data to Chat Idendity management service 4. If any profile image data needs to be handled the Profile Image management service will handle this. - The main role of this service is to - Obtain the image bytes - Sanitise the image - Resize the image - return the resulting data to the requesting service 5. Store the identity data in the database ### Sending message process flow ```mermaid graph LR %% Intities user((User)) subgraph status [Status App] subgraph status-react UI{UI} end subgraph status-go db[(db - chat_identity)] int[Send message service] API[Send Message API Endpoint] end end network{{Waku Network}} %% Connections user --> UI UI --> API API -->|Step 1 & 2| int int -->|Step 3| db db -->|Step 3| int int -->|Step 4| network int -->|Step 5| network int -->|Step 6| db ``` 1. Standard unchanged send message API call 2. Check `last_identity_clock` of target chat - If `last_identity_clock` is greater than the target resend period (possibly 7 days) go to step 3 - Or if `last_identity_clock` is null go to step 3 3. query db for user identity data from `chat_identity` table, or memory store 4. Standard unchanged chat message broadcast to waku network - Go to step 5 & 6 if comming from step 3 5. Create and send `ChatIdentity` waku message to target chat 6. Update chat with new `last_identity_clock` ### Receiving message process flow ```mermaid graph BT %% Intities user((User)) subgraph status [Status App] subgraph status-react UI{UI} end subgraph status-go db[(db - message_identities)] ser[Get Messages service] API[Get Messages API Endpoint] end end network{{Waku Network}} %% Connections user --> UI -->|Step 10| user UI --> API -->|Step 9| UI API -->|Step 1| ser -->|Step 8| API ser -->|Step 2| network -->|Step 3 & 4| ser ser -->|Step 5| db -->|Step 6| ser ser -->|Step 7| db ``` 1. Standard unchanged get message API call 2. Standard call to Waku network / mailserver for new messages 3. Standard messages return 4. Parse messages - Parse chat messages like normal - Parse any `ChatIdentity` messages sent to the chat - Calculate hashes for all unique `ChatIdentity` messages - Assign `ChatIdentity` to memory mapping (`map[user_chat_key]ChatIdentity`) - ignore any duplicates or any `ChatIdentity` with a lower clock than in the mapping 5. Get `identity_hash` and `last_clock` stored in `message_identities` where the chat keys match the map indexes 6. Compare `identity_hash` and `last_clock` against each user chat key - If the new message clock is higher and the hash does not match proceed to step 7 - If no record was found for the chat key proceed to step 7 7. Update or create record in the database - Parse and sanitise the image data - Store image in local device db 8. Append to the `MessengerResponse.Contact` struct return data to API endpoint 9. Standard message response return 10. `status-react` populates new messages in the chat view with contact data - Setting the user display names, profile photos, etc // TODO check that syncing for identity will work