225 lines
10 KiB
Go
225 lines
10 KiB
Go
|
|
// contentMetadata provides functions to store and retrieve metadata about profiles and messages
|
|
// Content metadata is stored in the database, so the content can be deleted and the metadata can still be retained
|
|
|
|
package contentMetadata
|
|
|
|
// Storing content metadata in the database enables:
|
|
// 1. We do not have to calculate the ProfileIsCanonical status and the attribute hashes for the same profile more than once
|
|
// 2. Hosts/Moderators can delete banned messages and still keep the cipher key hash to verify reviews for the messages
|
|
// 3. Hosts can delete banned profiles/messages and still be aware if those profile's/message's reviews are within their range
|
|
// Knowing if a profile's/message's reviews are within your range requires knowing the profile author/message inbox
|
|
// 4. Hosts can delete banned profiles and still be aware of why those profiles were banned (if their attributes were banned)
|
|
// We need to keep track of the profile's attribute hashes to be able to determine the profile's verdict consensus
|
|
// 5. It is faster to retrieve metadata than to read it from the profile/message
|
|
// This is because we do not need to read the entire message/profile into memory
|
|
|
|
// Profile metadata:
|
|
// -Profile version
|
|
// -Profile network type
|
|
// -Profile identity Hash
|
|
// -Profile broadcast time
|
|
// -Profile is disabled status
|
|
// -Profile is canonical status
|
|
// -Profile attribute hashes map
|
|
// Message metadata:
|
|
// -Message version
|
|
// -Message network type
|
|
// -Message size in bytes
|
|
// -Message Inbox
|
|
// -Message Cipher key hash
|
|
|
|
import "seekia/internal/encoding"
|
|
import "seekia/internal/badgerDatabase"
|
|
import "seekia/internal/profiles/readProfiles"
|
|
import "seekia/internal/messaging/readMessages"
|
|
|
|
import messagepack "github.com/vmihailenco/msgpack/v5"
|
|
|
|
import "errors"
|
|
|
|
//Outputs:
|
|
// -bool: Profile metadata exists
|
|
// -int: Profile Version
|
|
// -byte: Profile network type (1 == Mainnet, 2 == Testnet1)
|
|
// -[16]byte: Profile author identity Hash
|
|
// -int64: Profile broadcast time
|
|
// -bool: Profile is disabled
|
|
// -bool: Profile is canonical
|
|
// -map[int][27]byte: Map of Attribute identifier -> Attribute hash
|
|
// -error
|
|
func GetProfileMetadata(profileHash [28]byte)(bool, int, byte, [16]byte, int64, bool, bool, map[int][27]byte, error){
|
|
|
|
metadataExists, profileMetadata, err := badgerDatabase.GetProfileMetadata(profileHash)
|
|
if (err != nil) { return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
if (metadataExists == true){
|
|
|
|
type profileMetadataStruct struct{
|
|
ProfileVersion int
|
|
NetworkType byte
|
|
IdentityHash [16]byte
|
|
BroadcastTime int64
|
|
IsDisabled bool
|
|
IsCanonical bool
|
|
AttributeHashesMap map[int][27]byte
|
|
}
|
|
|
|
var profileMetadataObject profileMetadataStruct
|
|
|
|
err := encoding.DecodeMessagePackBytes(false, profileMetadata, &profileMetadataObject)
|
|
if (err != nil) {
|
|
return false, 0, 0, [16]byte{}, 0, false, false, nil, errors.New("Database malformed: contains invalid profile metadata: " + err.Error())
|
|
}
|
|
|
|
profileVersion := profileMetadataObject.ProfileVersion
|
|
profileNetworkType := profileMetadataObject.NetworkType
|
|
profileIdentityHash := profileMetadataObject.IdentityHash
|
|
profileBroadcastTime := profileMetadataObject.BroadcastTime
|
|
profileIsDisabled := profileMetadataObject.IsDisabled
|
|
profileIsCanonical := profileMetadataObject.IsCanonical
|
|
attributeHashesMap := profileMetadataObject.AttributeHashesMap
|
|
|
|
if (profileIsDisabled == true){
|
|
emptyMap := make(map[int][27]byte)
|
|
return true, profileVersion, profileNetworkType, profileIdentityHash, profileBroadcastTime, true, true, emptyMap, nil
|
|
}
|
|
|
|
return true, profileVersion, profileNetworkType, profileIdentityHash, profileBroadcastTime, false, profileIsCanonical, attributeHashesMap, nil
|
|
}
|
|
|
|
profileType, _, err := readProfiles.ReadProfileHashMetadata(profileHash)
|
|
if (err != nil) { return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
profileExists, profileBytes, err := badgerDatabase.GetUserProfile(profileType, profileHash)
|
|
if (err != nil) { return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
if (profileExists == false){
|
|
return false, 0, 0, [16]byte{}, 0, false, false, nil, nil
|
|
}
|
|
|
|
ableToRead, profileHash_Retrieved, profileVersion, profileNetworkType, profileIdentityHash, profileBroadcastTime, profileIsDisabled, rawProfileMap, err := readProfiles.ReadProfileAndHash(false, profileBytes)
|
|
if (err != nil) { return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
if (ableToRead == false){
|
|
return false, 0, 0, [16]byte{}, 0, false, false, nil, errors.New("Database corrupt: Contains invalid profile: " + err.Error())
|
|
}
|
|
if (profileHash != profileHash_Retrieved){
|
|
return false, 0, 0, [16]byte{}, 0, false, false, nil, errors.New("Database corrupt: Profile hash does not match profile entry key")
|
|
}
|
|
|
|
profileAttributeHashesMap, profileIsCanonical, err := readProfiles.GetProfileAttributeHashesMap(profileIdentityHash, profileVersion, profileNetworkType, rawProfileMap)
|
|
if (err != nil) { return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
profileVersionEncoded, err := encoding.EncodeMessagePackBytes(profileVersion)
|
|
if (err != nil){ return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
profileNetworkTypeEncoded, err := encoding.EncodeMessagePackBytes(profileNetworkType)
|
|
if (err != nil){ return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
identityHashEncoded, err := encoding.EncodeMessagePackBytes(profileIdentityHash)
|
|
if (err != nil){ return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
broadcastTimeEncoded, err := encoding.EncodeMessagePackBytes(profileBroadcastTime)
|
|
if (err != nil){ return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
isDisabledEncoded, err := encoding.EncodeMessagePackBytes(profileIsDisabled)
|
|
if (err != nil){ return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
isCanonicalEncoded, err := encoding.EncodeMessagePackBytes(profileIsCanonical)
|
|
if (err != nil){ return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
attributeHashesMapEncoded, err := encoding.EncodeMessagePackBytes(profileAttributeHashesMap)
|
|
if (err != nil){ return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
profileMetadataSlice := []messagepack.RawMessage{profileVersionEncoded, profileNetworkTypeEncoded, identityHashEncoded, broadcastTimeEncoded, isDisabledEncoded, isCanonicalEncoded, attributeHashesMapEncoded}
|
|
|
|
profileMetadataBytes, err := encoding.EncodeMessagePackBytes(profileMetadataSlice)
|
|
if (err != nil) { return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
err = badgerDatabase.AddProfileMetadata(profileHash, profileMetadataBytes)
|
|
if (err != nil) { return false, 0, 0, [16]byte{}, 0, false, false, nil, err }
|
|
|
|
return true, profileVersion, profileNetworkType, profileIdentityHash, profileBroadcastTime, profileIsDisabled, profileIsCanonical, profileAttributeHashesMap, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Message metadata exists
|
|
// -int: Message version
|
|
// -byte: Message network type (1 == Mainnet, 2 == Testnet1)
|
|
// -int: Message size in bytes
|
|
// -[10]byte: Message inbox
|
|
// -[25]byte: Message cipher key hash
|
|
// -error
|
|
func GetMessageMetadata(messageHash [26]byte)(bool, int, byte, int, [10]byte, [25]byte, error){
|
|
|
|
exists, messageMetadata, err := badgerDatabase.GetMessageMetadata(messageHash)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
if (exists == true){
|
|
|
|
type messageMetadataStruct struct{
|
|
MessageVersion int
|
|
MessageNetworkType byte
|
|
MessageSize int
|
|
MessageInbox [10]byte
|
|
MessageCipherKeyHash [25]byte
|
|
}
|
|
|
|
var messageMetadataObject messageMetadataStruct
|
|
|
|
err := encoding.DecodeMessagePackBytes(false, messageMetadata, &messageMetadataObject)
|
|
if (err != nil) {
|
|
return false, 0, 0, 0, [10]byte{}, [25]byte{}, errors.New("Database malformed: contains invalid message metadata: " + err.Error())
|
|
}
|
|
|
|
messageVersion := messageMetadataObject.MessageVersion
|
|
messageNetworkType := messageMetadataObject.MessageNetworkType
|
|
messageSize := messageMetadataObject.MessageSize
|
|
messageInbox := messageMetadataObject.MessageInbox
|
|
messageCipherKeyHash := messageMetadataObject.MessageCipherKeyHash
|
|
|
|
return true, messageVersion, messageNetworkType, messageSize, messageInbox, messageCipherKeyHash, nil
|
|
}
|
|
|
|
messageExists, messageBytes, err := badgerDatabase.GetChatMessage(messageHash)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
if (messageExists == false){
|
|
return false, 0, 0, 0, [10]byte{}, [25]byte{}, nil
|
|
}
|
|
|
|
ableToRead, messageHash_Retrieved, messageVersion, messageNetworkType, messageInbox, _, _, _, messageCipherKeyHash, _, _, err := readMessages.ReadChatMessagePublicDataAndHash(false, messageBytes)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
if (ableToRead == false){
|
|
return false, 0, 0, 0, [10]byte{}, [25]byte{}, errors.New("Database corrupt: Contains invalid message.")
|
|
}
|
|
if (messageHash != messageHash_Retrieved){
|
|
return false, 0, 0, 0, [10]byte{}, [25]byte{}, errors.New("Database corrupt: Chat message entry key does not match message hash.")
|
|
}
|
|
|
|
messageSize := len(messageBytes)
|
|
|
|
messageVersionEncoded, err := encoding.EncodeMessagePackBytes(messageVersion)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
|
|
messageNetworkTypeEncoded, err := encoding.EncodeMessagePackBytes(messageNetworkType)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
|
|
messageSizeEncoded, err := encoding.EncodeMessagePackBytes(messageSize)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
|
|
messageInboxEncoded, err := encoding.EncodeMessagePackBytes(messageInbox)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
|
|
messageCipherKeyHashEncoded, err := encoding.EncodeMessagePackBytes(messageCipherKeyHash)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
|
|
messageSlice := []messagepack.RawMessage{messageVersionEncoded, messageNetworkTypeEncoded, messageSizeEncoded, messageInboxEncoded, messageCipherKeyHashEncoded}
|
|
|
|
newMessageMetadata, err := encoding.EncodeMessagePackBytes(messageSlice)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
|
|
err = badgerDatabase.AddMessageMetadata(messageHash, newMessageMetadata)
|
|
if (err != nil) { return false, 0, 0, 0, [10]byte{}, [25]byte{}, err }
|
|
|
|
return true, messageVersion, messageNetworkType, messageSize, messageInbox, messageCipherKeyHash, nil
|
|
}
|
|
|
|
|
|
|