2024-04-11 15:51:56 +02:00
// mySecretInboxes provides functions to manage a user's secret inboxes
// User sends these inboxes out in messages to users
// They must check them for messages until they expire
package mySecretInboxes
//TODO: Prune expired inboxes we have checked sufficiently
import "seekia/internal/encoding"
import "seekia/internal/helpers"
import "seekia/internal/identity"
import "seekia/internal/messaging/inbox"
import "seekia/internal/messaging/secretInboxEpoch"
import "seekia/internal/myBlockedUsers"
import "seekia/internal/myDatastores/myMapList"
import "bytes"
import "sync"
import "errors"
// This will be locked whenever we update the map list
var updatingMySecretInboxesMapListMutex sync . Mutex
var mySecretInboxesMapListDatastore * myMapList . MyMapList
// This function must be called whenever an app user signs in
func InitializeMySecretInboxesDatastore ( ) error {
updatingMySecretInboxesMapListMutex . Lock ( )
defer updatingMySecretInboxesMapListMutex . Unlock ( )
newMySecretInboxesMapListDatastore , err := myMapList . CreateNewMapList ( "MySecretInboxes" )
if ( err != nil ) { return err }
mySecretInboxesMapListDatastore = newMySecretInboxesMapListDatastore
return nil
}
// This function will omit inboxes that we no longer need to download messages for
// This would be because they have been sufficiently checked and old enough that no new messages are being received
func GetAllMyActiveSecretInboxes ( myIdentityHash [ 16 ] byte , networkType byte ) ( [ ] [ 10 ] byte , error ) {
isValid , err := identity . VerifyIdentityHash ( myIdentityHash , false , "" )
if ( err != nil ) { return nil , err }
if ( isValid == false ) {
myIdentityHashHex := encoding . EncodeBytesToHexString ( myIdentityHash [ : ] )
return nil , errors . New ( "GetAllMyActiveSecretInboxes called with invalid myIdentityHash: " + myIdentityHashHex )
}
isValid = helpers . VerifyNetworkType ( networkType )
if ( isValid == false ) {
networkTypeString := helpers . ConvertByteToString ( networkType )
return nil , errors . New ( "GetAllMyActiveSecretInboxes called with invalid networkType: " + networkTypeString )
}
mySecretInboxesList , err := GetAllMySecretInboxes ( myIdentityHash , networkType )
if ( err != nil ) { return nil , err }
//TODO: We need code that keeps track of how many times we have checked a particular inbox after it has expired
// Then we will omit those inboxes
return mySecretInboxesList , nil
}
// This function will not return inboxes for users whom the user has blocked
func GetAllMySecretInboxes ( myIdentityHash [ 16 ] byte , networkType byte ) ( [ ] [ 10 ] byte , error ) {
isValid , err := identity . VerifyIdentityHash ( myIdentityHash , false , "" )
if ( err != nil ) { return nil , err }
if ( isValid == false ) {
myIdentityHashHex := encoding . EncodeBytesToHexString ( myIdentityHash [ : ] )
return nil , errors . New ( "GetAllMySecretInboxes called with invalid myIdentityHash: " + myIdentityHashHex )
}
isValid = helpers . VerifyNetworkType ( networkType )
if ( isValid == false ) {
networkTypeString := helpers . ConvertByteToString ( networkType )
return nil , errors . New ( "GetAllMySecretInboxes called with invalid networkType: " + networkTypeString )
}
mySecretInboxesMapList , err := mySecretInboxesMapListDatastore . GetMapList ( )
if ( err != nil ) { return nil , err }
allMySecretInboxesList := make ( [ ] [ 10 ] byte , 0 )
for _ , inboxMap := range mySecretInboxesMapList {
conversationMyIdentityHashString , exists := inboxMap [ "MyIdentityHash" ]
if ( exists == false ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Item missing MyIdentityHash." )
}
conversationMyIdentityHash , _ , err := identity . ReadIdentityHashString ( conversationMyIdentityHashString )
if ( err != nil ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Item contains invalid MyIdentityHash: " + conversationMyIdentityHashString )
}
if ( conversationMyIdentityHash != myIdentityHash ) {
continue
}
recipientIdentityHashString , exists := inboxMap [ "TheirIdentityHash" ]
if ( exists == false ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Item missing TheirIdentityHash" )
}
recipientIdentityHash , _ , err := identity . ReadIdentityHashString ( recipientIdentityHashString )
if ( err != nil ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Item contains invalid TheirIdentityHash: " + recipientIdentityHashString )
}
recipientIsBlocked , _ , _ , _ , err := myBlockedUsers . CheckIfUserIsBlocked ( recipientIdentityHash )
if ( err != nil ) { return nil , err }
if ( recipientIsBlocked == true ) {
continue
}
inboxNetworkTypeString , exists := inboxMap [ "NetworkType" ]
if ( exists == false ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Item missing NetworkType." )
}
inboxNetworkType , err := helpers . ConvertNetworkTypeStringToByte ( inboxNetworkTypeString )
if ( err != nil ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Item contains invalid NetworkType: " + inboxNetworkTypeString )
}
if ( inboxNetworkType != networkType ) {
continue
}
secretInboxSeedHex , exists := inboxMap [ "SecretInboxSeed" ]
if ( exists == false ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Item missing SecretInboxSeed." )
}
secretInboxSeed , err := encoding . DecodeHexStringToBytes ( secretInboxSeedHex )
if ( err != nil ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Contains invalid secretInboxSeed: Not Hex." )
}
if ( len ( secretInboxSeed ) != 22 ) {
return nil , errors . New ( "mySecretInboxesMapList is malformed: Contains invalid secretInboxSeed: Invalid length." )
}
secretInboxSeedArray := [ 22 ] byte ( secretInboxSeed )
currentSecretInbox , _ , err := inbox . GetSecretInboxAndSealerKeyFromSecretInboxSeed ( secretInboxSeedArray )
if ( err != nil ) { return nil , err }
allMySecretInboxesList = append ( allMySecretInboxesList , currentSecretInbox )
}
return allMySecretInboxesList , nil
}
//Outputs:
// -bool: My secret inbox found
// -[16]byte: Conversation my identity hash
// -[16]byte: Conversation recipient identity hash
// -byte: Secret inbox network type
// -[32]byte: Secret inbox sealer key
// -int64: Secret inbox start time
// -int64: Secret inbox expiration time
// -error
func GetMySecretInboxInfo ( secretInbox [ 10 ] byte ) ( bool , [ 16 ] byte , [ 16 ] byte , byte , [ 32 ] byte , int64 , int64 , error ) {
mySecretInboxesMapList , err := mySecretInboxesMapListDatastore . GetMapList ( )
if ( err != nil ) { return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , err }
for _ , inboxMap := range mySecretInboxesMapList {
secretInboxSeedHex , exists := inboxMap [ "SecretInboxSeed" ]
if ( exists == false ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map missing SecretInboxSeed" )
}
secretInboxSeed , err := encoding . DecodeHexStringToBytes ( secretInboxSeedHex )
if ( err != nil ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxes map list malformed: Contains invalid secretInboxSeed: Not Hex." )
}
if ( len ( secretInboxSeed ) != 22 ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxes map list malformed: Contains invalid secretInboxSeed: Invalid length." )
}
secretInboxSeedArray := [ 22 ] byte ( secretInboxSeed )
currentSecretInbox , currentSecretInboxSealerKey , err := inbox . GetSecretInboxAndSealerKeyFromSecretInboxSeed ( secretInboxSeedArray )
if ( err != nil ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxes map list malformed: Contains invalid secretInboxSeed." )
}
if ( currentSecretInbox != secretInbox ) {
continue
}
conversationMyIdentityHashString , exists := inboxMap [ "MyIdentityHash" ]
if ( exists == false ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map missing MyIdentityHash" )
}
conversationMyIdentityHash , _ , err := identity . ReadIdentityHashString ( conversationMyIdentityHashString )
if ( err != nil ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map contains invalid MyIdentityHash: " + conversationMyIdentityHashString )
}
conversationTheirIdentityHashString , exists := inboxMap [ "TheirIdentityHash" ]
if ( exists == false ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map missing TheirIdentityHash" )
}
conversationTheirIdentityHash , _ , err := identity . ReadIdentityHashString ( conversationTheirIdentityHashString )
if ( err != nil ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map contains invalid TheirIdentityHash: " + conversationTheirIdentityHashString )
}
inboxNetworkTypeString , exists := inboxMap [ "NetworkType" ]
if ( exists == false ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map missing NetworkType" )
}
inboxNetworkType , err := helpers . ConvertNetworkTypeStringToByte ( inboxNetworkTypeString )
if ( err != nil ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map contains invalid NetworkType: " + inboxNetworkTypeString )
}
inboxStartTimeString , exists := inboxMap [ "InboxStartTime" ]
if ( exists == false ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map missing InboxStartTime" )
}
inboxStartTimeInt64 , err := helpers . ConvertStringToInt64 ( inboxStartTimeString )
if ( err != nil ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "Malformed mySecretInboxesMapList: Invalid secret inbox start time: " + inboxStartTimeString )
}
inboxEndTimeString , exists := inboxMap [ "InboxEndTime" ]
if ( exists == false ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "MySecretInboxesMapList is malformed: Inbox map missing InboxEndTime" )
}
inboxEndTimeInt64 , err := helpers . ConvertStringToInt64 ( inboxEndTimeString )
if ( err != nil ) {
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , errors . New ( "Malformed mySecretInboxesMapList: Invalid secret inbox end time: " + inboxEndTimeString )
}
return true , conversationMyIdentityHash , conversationTheirIdentityHash , inboxNetworkType , currentSecretInboxSealerKey , inboxStartTimeInt64 , inboxEndTimeInt64 , nil
}
return false , [ 16 ] byte { } , [ 16 ] byte { } , 0 , [ 32 ] byte { } , 0 , 0 , nil
}
//Outputs:
// -bool: Parameters exist
// -bool: My current epoch secret inbox seed exists
// -[22]byte: My current epoch secret inbox seed
// -bool: My next epoch secret inbox seed exists
// -[22]byte: My next epoch secret inbox seed
// -error
2024-06-11 06:59:06 +02:00
func GetMySecretInboxSeedsForMessage ( myIdentityHash [ 16 ] byte , recipientIdentityHash [ 16 ] byte , networkType byte , messageCreationTimeUnix int64 ) ( bool , bool , [ 22 ] byte , bool , [ 22 ] byte , error ) {
2024-04-11 15:51:56 +02:00
isValid , err := identity . VerifyIdentityHash ( myIdentityHash , false , "" )
if ( err != nil ) { return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , err }
if ( isValid == false ) {
myIdentityHashHex := encoding . EncodeBytesToHexString ( myIdentityHash [ : ] )
return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , errors . New ( "GetMySecretInboxSeedsForMessage called with invalid myIdentityHash: " + myIdentityHashHex )
}
isValid = helpers . VerifyNetworkType ( networkType )
if ( isValid == false ) {
networkTypeString := helpers . ConvertByteToString ( networkType )
return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , errors . New ( "GetMySecretInboxSeedsForMessage called with invalid networkType: " + networkTypeString )
}
2024-06-11 06:59:06 +02:00
parametersExist , currentEpochStartTime , currentEpochEndTime , nextEpochStartTime , nextEpochEndTime , err := secretInboxEpoch . GetSecretInboxEpochStartAndEndTimes ( networkType , messageCreationTimeUnix )
2024-04-11 15:51:56 +02:00
if ( err != nil ) { return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , err }
if ( parametersExist == false ) {
return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , nil
}
myIdentityHashString , _ , err := identity . EncodeIdentityHashBytesToString ( myIdentityHash )
if ( err != nil ) {
myIdentityHashHex := encoding . EncodeBytesToHexString ( myIdentityHash [ : ] )
return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , errors . New ( "VerifyIdentityHash failed to verify identity hash: " + myIdentityHashHex )
}
recipientIdentityHashString , _ , err := identity . EncodeIdentityHashBytesToString ( recipientIdentityHash )
if ( err != nil ) {
recipientIdentityHashHex := encoding . EncodeBytesToHexString ( recipientIdentityHash [ : ] )
return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , errors . New ( "GetMySecretInboxSeedsForMessage called with invalid recipient identity hash: " + recipientIdentityHashHex )
}
// We retrieve all secret inboxes for this conversation, and find an inbox that exists for the entire desired epoch duration
networkTypeString := helpers . ConvertByteToString ( networkType )
lookupMap := map [ string ] string {
"MyIdentityHash" : myIdentityHashString ,
"TheirIdentityHash" : recipientIdentityHashString ,
"NetworkType" : networkTypeString ,
}
anyItemsFound , foundItemsMapList , err := mySecretInboxesMapListDatastore . GetMapListItems ( lookupMap )
if ( err != nil ) { return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , err }
if ( anyItemsFound == false ) {
return true , false , [ 22 ] byte { } , false , [ 22 ] byte { } , nil
}
//Outputs:
// -bool: Inbox found
// -[22]byte: Secret inbox seed
// -error
getSecretInboxSeedForEpoch := func ( epochStartTime int64 , epochEndTime int64 ) ( bool , [ 22 ] byte , error ) {
for _ , inboxMap := range foundItemsMapList {
inboxStartTimeString , exists := inboxMap [ "InboxStartTime" ]
if ( exists == false ) {
return false , [ 22 ] byte { } , errors . New ( "MySecretInboxesMapList is malformed: Item missing InboxStartTime" )
}
inboxStartTimeInt64 , err := helpers . ConvertStringToInt64 ( inboxStartTimeString )
if ( err != nil ) {
return false , [ 22 ] byte { } , errors . New ( "MySecretInboxesMapList is malformed: Invalid secret inbox start time: " + inboxStartTimeString )
}
inboxEndTimeString , exists := inboxMap [ "InboxEndTime" ]
if ( exists == false ) {
return false , [ 22 ] byte { } , errors . New ( "MySecretInboxesMapList is malformed: Item missing InboxEndTime" )
}
inboxEndTimeInt64 , err := helpers . ConvertStringToInt64 ( inboxEndTimeString )
if ( err != nil ) {
return false , [ 22 ] byte { } , errors . New ( "MySecretInboxesMapList is malformed: Invalid secret inbox end time: " + inboxEndTimeString )
}
if ( inboxStartTimeInt64 > epochStartTime || inboxEndTimeInt64 < epochEndTime ) {
continue
}
secretInboxSeedHex , exists := inboxMap [ "SecretInboxSeed" ]
if ( exists == false ) {
return false , [ 22 ] byte { } , errors . New ( "MySecretInboxesMapList is malformed: Item missing SecretInboxSeed" )
}
secretInboxSeed , err := encoding . DecodeHexStringToBytes ( secretInboxSeedHex )
if ( err != nil ) {
return false , [ 22 ] byte { } , errors . New ( "MySecretInboxesMapList is malformed: Invalid secret inbox seed: " + secretInboxSeedHex )
}
if ( len ( secretInboxSeed ) != 22 ) {
return false , [ 22 ] byte { } , errors . New ( "MySecretInboxesMapList is malformed: Invalid secret inbox seed: " + secretInboxSeedHex )
}
secretInboxSeedArray := [ 22 ] byte ( secretInboxSeed )
return true , secretInboxSeedArray , nil
}
return false , [ 22 ] byte { } , nil
}
foundCurrentEpochInboxSeed , currentEpochInboxSeed , err := getSecretInboxSeedForEpoch ( currentEpochStartTime , currentEpochEndTime )
if ( err != nil ) { return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , err }
foundNextEpochInboxSeed , nextEpochInboxSeed , err := getSecretInboxSeedForEpoch ( nextEpochStartTime , nextEpochEndTime )
if ( err != nil ) { return false , false , [ 22 ] byte { } , false , [ 22 ] byte { } , err }
return true , foundCurrentEpochInboxSeed , currentEpochInboxSeed , foundNextEpochInboxSeed , nextEpochInboxSeed , nil
}
//Outputs:
// -bool: Parameters exist
// -error
2024-06-11 06:59:06 +02:00
func AddMySecretInboxSeeds ( myIdentityHash [ 16 ] byte , theirIdentityHash [ 16 ] byte , networkType byte , messageCreationTime int64 , currentSecretInboxSeed [ 22 ] byte , nextSecretInboxSeed [ 22 ] byte ) ( bool , error ) {
2024-04-11 15:51:56 +02:00
isValid , err := identity . VerifyIdentityHash ( myIdentityHash , false , "" )
if ( err != nil ) { return false , err }
if ( isValid == false ) {
myIdentityHashHex := encoding . EncodeBytesToHexString ( myIdentityHash [ : ] )
return false , errors . New ( "AddMySecretInboxSeeds called with invalid myIdentityHash: " + myIdentityHashHex )
}
isValid , err = identity . VerifyIdentityHash ( theirIdentityHash , false , "" )
if ( err != nil ) { return false , err }
if ( isValid == false ) {
theirIdentityHashHex := encoding . EncodeBytesToHexString ( theirIdentityHash [ : ] )
return false , errors . New ( "AddMySecretInboxSeeds called with invalid theirIdentityHash: " + theirIdentityHashHex )
}
isValid = helpers . VerifyNetworkType ( networkType )
if ( isValid == false ) {
networkTypeString := helpers . ConvertByteToString ( networkType )
return false , errors . New ( "AddMySecretInboxSeeds called with invalid networkType: " + networkTypeString )
}
updatingMySecretInboxesMapListMutex . Lock ( )
defer updatingMySecretInboxesMapListMutex . Unlock ( )
2024-06-11 06:59:06 +02:00
parametersExist , currentSecretInboxStartTime , currentSecretInboxEndTime , nextSecretInboxStartTime , nextSecretInboxEndTime , err := secretInboxEpoch . GetSecretInboxEpochStartAndEndTimes ( networkType , messageCreationTime )
2024-04-11 15:51:56 +02:00
if ( err != nil ) { return false , err }
if ( parametersExist == false ) {
return false , nil
}
mySecretInboxesMapList , err := mySecretInboxesMapListDatastore . GetMapList ( )
if ( err != nil ) { return false , err }
addSecretInboxSeedToMapList := func ( secretInboxSeed [ 22 ] byte , inboxStartTime int64 , inboxEndTime int64 ) error {
// We see if an entry already exists for this inbox
for _ , inboxMap := range mySecretInboxesMapList {
currentSecretInboxSeedString , exists := inboxMap [ "SecretInboxSeed" ]
if ( exists == false ) {
return errors . New ( "mySecretInboxesMapListDatastore is malformed: Item missing SecretInboxSeed" )
}
currentSecretInboxSeedBytes , err := encoding . DecodeHexStringToBytes ( currentSecretInboxSeedString )
if ( err != nil ) {
return errors . New ( "mySecretInboxesMapListDatastore is malformed: Item contains invalid SecretInboxSeed: Not Hex." )
}
if ( len ( currentSecretInboxSeedBytes ) != 22 ) {
return errors . New ( "mySecretInboxesMapListDatastore is malformed: Item contains invalid SecretInboxSeed: Invalid length." )
}
areEqual := bytes . Equal ( currentSecretInboxSeedBytes , secretInboxSeed [ : ] )
if ( areEqual == false ) {
continue
}
conversationMyIdentityHashString , exists := inboxMap [ "MyIdentityHash" ]
if ( exists == false ) {
return errors . New ( "Malformed mySecretInboxesMapListDatastore: Item missing MyIdentityHash" )
}
conversationMyIdentityHash , _ , err := identity . ReadIdentityHashString ( conversationMyIdentityHashString )
if ( err != nil ) {
return errors . New ( "Malformed mySecretInboxesMapListDatastore: Item contains invalid MyIdentityHash: " + conversationMyIdentityHashString )
}
if ( conversationMyIdentityHash != myIdentityHash ) {
// This should never happen. Secret inbox seeds are generated randomly.
return errors . New ( "Trying to add a secret inbox seed which already exists for a different identity." )
}
conversationTheirIdentityHashString , exists := inboxMap [ "TheirIdentityHash" ]
if ( exists == false ) {
return errors . New ( "Malformed mySecretInboxesMapListDatastore: Item missing TheirIdentityHash" )
}
conversationTheirIdentityHash , _ , err := identity . ReadIdentityHashString ( conversationTheirIdentityHashString )
if ( err != nil ) {
return errors . New ( "Malformed mySecretInboxesMapListDatastore: Item contains invalid TheirIdentityHash: " + conversationTheirIdentityHashString )
}
if ( conversationTheirIdentityHash != theirIdentityHash ) {
// This should never happen. Secret inbox seeds are generated randomly.
return errors . New ( "Trying to add a secret inbox seed which already exists for a different recipient identity." )
}
inboxNetworkTypeString , exists := inboxMap [ "NetworkType" ]
if ( exists == false ) {
return errors . New ( "Malformed mySecretInboxesMapListDatastore: Item missing NetworkType" )
}
inboxNetworkType , err := helpers . ConvertNetworkTypeStringToByte ( inboxNetworkTypeString )
if ( err != nil ) {
return errors . New ( "Malformed mySecretInboxesMapListDatastore: Item contains invalid NetworkType: " + inboxNetworkTypeString )
}
if ( inboxNetworkType != networkType ) {
// This should never happen. Secret inbox seeds are generated randomly.
return errors . New ( "Trying to add a secret inbox seed that already exists with a different networkType." )
}
existingInboxStartTimeString , exists := inboxMap [ "InboxStartTime" ]
if ( exists == false ) {
return errors . New ( "mySecretInboxesMapListDatastore is malformed: Item missing InboxStartTime" )
}
existingInboxStartTime , err := helpers . ConvertStringToInt64 ( existingInboxStartTimeString )
if ( err != nil ) {
return errors . New ( "Malformed mySecretInboxesMapList: Invalid secret inbox start time: " + existingInboxStartTimeString )
}
existingInboxEndTimeString , exists := inboxMap [ "InboxEndTime" ]
if ( exists == false ) {
return errors . New ( "mySecretInboxesMapListDatastore is malformed: Item missing InboxEndTime" )
}
existingInboxEndTime , err := helpers . ConvertStringToInt64 ( existingInboxEndTimeString )
if ( err != nil ) {
return errors . New ( "Malformed mySecretInboxesMapList: Invalid secret inbox end time: " + existingInboxEndTimeString )
}
// We see if the existing inbox start/end times are earlier/later than what we have recorded
// This would only happen if secret inbox epoch duration was changed
if ( inboxStartTime >= existingInboxStartTime && inboxEndTime <= existingInboxEndTime ) {
// Existing inbox range bounds are valid.
// Nothing to change
return nil
}
// Inbox range must be expanded
// Secret inbox epoch duration must have changed (or sender is malicious)
newInboxStartTime := min ( existingInboxStartTime , inboxStartTime )
newInboxEndTime := max ( existingInboxEndTime , inboxEndTime )
newSecretInboxStartTimeString := helpers . ConvertInt64ToString ( newInboxStartTime )
newSecretInboxEndTimeString := helpers . ConvertInt64ToString ( newInboxEndTime )
inboxMap [ "InboxStartTime" ] = newSecretInboxStartTimeString
inboxMap [ "InboxEndTime" ] = newSecretInboxEndTimeString
return nil
}
// This is only reached if inbox map does not exist
// We create and append a new inbox map
myIdentityHashString , _ , err := identity . EncodeIdentityHashBytesToString ( myIdentityHash )
if ( err != nil ) {
myIdentityHashHex := encoding . EncodeBytesToHexString ( myIdentityHash [ : ] )
return errors . New ( "VerifyIdentityHash failed to verify myIdentityHash: " + myIdentityHashHex )
}
theirIdentityHashString , _ , err := identity . EncodeIdentityHashBytesToString ( theirIdentityHash )
if ( err != nil ) {
theirIdentityHashHex := encoding . EncodeBytesToHexString ( theirIdentityHash [ : ] )
return errors . New ( "VerifyIdentityHash failed to verify theirIdentityHash: " + theirIdentityHashHex )
}
secretInboxSeedHex := encoding . EncodeBytesToHexString ( secretInboxSeed [ : ] )
networkTypeString := helpers . ConvertByteToString ( networkType )
secretInboxStartTimeString := helpers . ConvertInt64ToString ( currentSecretInboxStartTime )
secretInboxEndTimeString := helpers . ConvertInt64ToString ( currentSecretInboxEndTime )
newInboxMap := map [ string ] string {
"MyIdentityHash" : myIdentityHashString ,
"TheirIdentityHash" : theirIdentityHashString ,
"SecretInboxSeed" : secretInboxSeedHex ,
"NetworkType" : networkTypeString ,
"InboxStartTime" : secretInboxStartTimeString ,
"InboxEndTime" : secretInboxEndTimeString ,
}
mySecretInboxesMapList = append ( mySecretInboxesMapList , newInboxMap )
return nil
}
err = addSecretInboxSeedToMapList ( currentSecretInboxSeed , currentSecretInboxStartTime , currentSecretInboxEndTime )
if ( err != nil ) { return false , err }
err = addSecretInboxSeedToMapList ( nextSecretInboxSeed , nextSecretInboxStartTime , nextSecretInboxEndTime )
if ( err != nil ) { return false , err }
err = mySecretInboxesMapListDatastore . OverwriteMapList ( mySecretInboxesMapList )
if ( err != nil ) { return false , err }
return true , nil
}