Support parallel channel reset

This commit is contained in:
Ali 2023-01-31 20:14:34 +01:00
parent 7be540c30b
commit a40ce690ee
6 changed files with 1301 additions and 763 deletions

View File

@ -209,7 +209,7 @@ public func accountWithId(accountManager: AccountManager<TelegramAccountManagerT
return postbox.transaction { transaction -> (PostboxCoding?, LocalizationSettings?, ProxySettings?, NetworkSettings?) in
var state = transaction.getState()
if state == nil, let backupData = backupData {
let backupState = AuthorizedAccountState(isTestingEnvironment: beginWithTestingEnvironment, masterDatacenterId: backupData.masterDatacenterId, peerId: PeerId(backupData.peerId), state: nil)
let backupState = AuthorizedAccountState(isTestingEnvironment: beginWithTestingEnvironment, masterDatacenterId: backupData.masterDatacenterId, peerId: PeerId(backupData.peerId), state: nil, invalidatedChannels: [])
state = backupState
let dict = NSMutableDictionary()
dict.setObject(MTDatacenterAuthInfo(authKey: backupData.masterDatacenterKey, authKeyId: backupData.masterDatacenterKeyId, saltSet: [], authKeyAttributes: [:])!, forKey: backupData.masterDatacenterId as NSNumber)

View File

@ -320,7 +320,7 @@ public func sendAuthorizationCode(accountManager: AccountManager<TelegramAccount
}
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
if let otherwiseReloginDays = otherwiseReloginDays, let value = forcedPasswordSetupNotice(otherwiseReloginDays) {
@ -885,7 +885,7 @@ public func authorizeWithCode(accountManager: AccountManager<TelegramAccountMana
}
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
if let otherwiseReloginDays = otherwiseReloginDays, let value = forcedPasswordSetupNotice(otherwiseReloginDays) {
@ -949,7 +949,7 @@ public func authorizeWithPassword(accountManager: AccountManager<TelegramAccount
}
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
/*transaction.updatePeersInternal([user], update: { current, peer -> Peer? in
return peer
})*/
@ -1019,7 +1019,7 @@ public func loginWithRecoveredAccountData(accountManager: AccountManager<Telegra
}
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
@ -1160,7 +1160,7 @@ public func signUpWithName(accountManager: AccountManager<TelegramAccountManager
let user = TelegramUser(user: user)
let appliedState = account.postbox.transaction { transaction -> Void in
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
if let hole = account.postbox.seedConfiguration.initializeChatListWithHole.topLevel {
transaction.replaceChatListHole(groupId: .root, index: hole.index, hole: nil)
}

View File

@ -421,7 +421,7 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u
return messageTimestamps
}
private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<PeerId>, activeChannelIds: Set<PeerId>, referencedReplyMessageIds: ReferencedReplyMessageIds, referencedGeneralMessageIds: Set<MessageId>, peerIdsRequiringLocalChatState: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<PeerId>, activeChannelIds: Set<PeerId>, referencedReplyMessageIds: ReferencedReplyMessageIds, referencedGeneralMessageIds: Set<MessageId>, peerIdsRequiringLocalChatState: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
var peers: [PeerId: Peer] = [:]
var channelStates: [PeerId: AccountStateChannelState] = [:]
@ -540,7 +540,7 @@ func initialStateWithDifference(postbox: Postbox, difference: Api.updates.Differ
}
}
func finalStateWithUpdateGroups(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, groups: [UpdateGroup]) -> Signal<AccountFinalState, NoError> {
func finalStateWithUpdateGroups(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, groups: [UpdateGroup], asyncResetChannels: (([(peer: Peer, pts: Int32?)]) -> Void)?) -> Signal<AccountFinalState, NoError> {
var updatedState = state
var hadReset = false
@ -664,10 +664,10 @@ func finalStateWithUpdateGroups(accountPeerId: PeerId, postbox: Postbox, network
collectedUpdates.append(Api.Update.updateDeleteChannelMessages(channelId: channelId, messages: [], pts: pts, ptsCount: ptsCount))
}
return finalStateWithUpdates(accountPeerId: accountPeerId, postbox: postbox, network: network, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty, shouldResetChannels: false, updatesDate: updatesDate)
return finalStateWithUpdates(accountPeerId: accountPeerId, postbox: postbox, network: network, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty, shouldResetChannels: false, updatesDate: updatesDate, asyncResetChannels: asyncResetChannels)
}
func finalStateWithDifference(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, difference: Api.updates.Difference) -> Signal<AccountFinalState, NoError> {
func finalStateWithDifference(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, difference: Api.updates.Difference, asyncResetChannels: (([(peer: Peer, pts: Int32?)]) -> Void)?) -> Signal<AccountFinalState, NoError> {
var updatedState = state
var messages: [Api.Message] = []
@ -726,7 +726,7 @@ func finalStateWithDifference(accountPeerId: PeerId, postbox: Postbox, network:
updatedState.addSecretMessages(encryptedMessages)
}
return finalStateWithUpdates(accountPeerId: accountPeerId, postbox: postbox, network: network, state: updatedState, updates: updates, shouldPoll: false, missingUpdates: false, shouldResetChannels: true, updatesDate: nil)
return finalStateWithUpdates(accountPeerId: accountPeerId, postbox: postbox, network: network, state: updatedState, updates: updates, shouldPoll: false, missingUpdates: false, shouldResetChannels: true, updatesDate: nil, asyncResetChannels: asyncResetChannels)
}
private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] {
@ -861,21 +861,25 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] {
return result
}
private func finalStateWithUpdates(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?) -> Signal<AccountFinalState, NoError> {
private func finalStateWithUpdates(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?, asyncResetChannels: (([(peer: Peer, pts: Int32?)]) -> Void)?) -> Signal<AccountFinalState, NoError> {
return network.currentGlobalTime
|> take(1)
|> mapToSignal { serverTime -> Signal<AccountFinalState, NoError> in
return finalStateWithUpdatesAndServerTime(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state, updates: updates, shouldPoll: shouldPoll, missingUpdates: missingUpdates, shouldResetChannels: shouldResetChannels, updatesDate: updatesDate, serverTime: Int32(serverTime))
return finalStateWithUpdatesAndServerTime(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state, updates: updates, shouldPoll: shouldPoll, missingUpdates: missingUpdates, shouldResetChannels: shouldResetChannels, updatesDate: updatesDate, serverTime: Int32(serverTime), asyncResetChannels: asyncResetChannels)
}
}
private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?, serverTime: Int32) -> Signal<AccountFinalState, NoError> {
private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?, serverTime: Int32, asyncResetChannels: (([(peer: Peer, pts: Int32?)]) -> Void)?) -> Signal<AccountFinalState, NoError> {
var updatedState = state
var channelsToPoll = Set<PeerId>()
var channelsToPoll: [PeerId: Int32?] = [:]
if !updatedState.initialState.channelsToPollExplicitely.isEmpty {
channelsToPoll.formUnion(updatedState.initialState.channelsToPollExplicitely)
for peerId in updatedState.initialState.channelsToPollExplicitely {
if case .none = channelsToPoll[peerId] {
channelsToPoll[peerId] = Optional<Int32>.none
}
}
}
var missingUpdatesFromChannels = Set<PeerId>()
@ -884,11 +888,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
switch update {
case let .updateChannelTooLong(_, channelId, channelPts):
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
if !channelsToPoll.contains(peerId) {
if case .none = channelsToPoll[peerId] {
if let channelPts = channelPts, let channelState = state.channelStates[peerId], channelState.pts >= channelPts {
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip updateChannelTooLong by pts")
} else {
channelsToPoll.insert(peerId)
channelsToPoll[peerId] = channelPts
}
}
case let .updateChannelPinnedTopics(_, channelId, order):
@ -896,8 +900,8 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
updatedState.addUpdatePinnedTopicOrder(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)), threadIds: order.map(Int64.init))
} else {
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
if !channelsToPoll.contains(peerId) {
channelsToPoll.insert(peerId)
if case .none = channelsToPoll[peerId] {
channelsToPoll[peerId] = nil
}
}
case let .updateDeleteChannelMessages(channelId, messages, pts: pts, ptsCount):
@ -915,9 +919,9 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
}
}
} else {
if !channelsToPoll.contains(peerId) {
if case .none = channelsToPoll[peerId] {
//Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) state unknown")
channelsToPoll.insert(peerId)
channelsToPoll[peerId] = nil
}
}
case let .updateEditChannelMessage(apiMessage, pts, ptsCount):
@ -947,9 +951,9 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
}
}
} else {
if !channelsToPoll.contains(peerId) {
if case .none = channelsToPoll[peerId] {
//Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) state unknown")
channelsToPoll.insert(peerId)
channelsToPoll[peerId] = nil
}
}
} else {
@ -971,14 +975,14 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
updatedState.updateChannelState(peerId, pts: pts)
} else {
if !channelsToPoll.contains(peerId) {
if case .none = channelsToPoll[peerId] {
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) updateWebPage pts hole \(previousState.pts) + \(ptsCount) != \(pts)")
channelsToPoll.insert(peerId)
channelsToPoll[peerId] = nil
}
}
} else {
if !channelsToPoll.contains(peerId) {
channelsToPoll.insert(peerId)
if case .none = channelsToPoll[peerId] {
channelsToPoll[peerId] = nil
}
}
case let .updateChannelAvailableMessages(channelId, minId):
@ -1047,9 +1051,9 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
}
}
} else {
if !channelsToPoll.contains(message.id.peerId) {
if case .none = channelsToPoll[message.id.peerId] {
Logger.shared.log("State", "channel \(message.id.peerId) (\((updatedState.peers[message.id.peerId] as? TelegramChannel)?.title ?? "nil")) state unknown")
channelsToPoll.insert(message.id.peerId)
channelsToPoll[message.id.peerId] = nil
}
}
}
@ -1278,9 +1282,9 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
}
}
} else {
if !channelsToPoll.contains(peerId) {
if case .none = channelsToPoll[peerId] {
//Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) state unknown")
channelsToPoll.insert(peerId)
channelsToPoll[peerId] = nil
}
}
case let .updatePeerBlocked(peerId, blocked):
@ -1634,24 +1638,36 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
pollChannelSignals = []
} else if shouldResetChannels {
var channelPeers: [Peer] = []
for peerId in channelsToPoll.union(missingUpdatesFromChannels) {
for peerId in Set(channelsToPoll.keys).union(missingUpdatesFromChannels) {
if let peer = updatedState.peers[peerId] {
channelPeers.append(peer)
} else {
Logger.shared.log("State", "can't reset channel \(peerId): no peer found")
}
}
if !channelPeers.isEmpty {
let resetSignal = resetChannels(accountPeerId: accountPeerId, postbox: postbox, network: network, peers: channelPeers, state: updatedState)
|> map { resultState -> (AccountMutableState, Bool, Int32?) in
return (resultState, true, nil)
}
pollChannelSignals = [resetSignal]
} else {
if let asyncResetChannels = asyncResetChannels {
pollChannelSignals = []
asyncResetChannels(channelPeers.map({ peer -> (peer: Peer, pts: Int32?) in
var pts: Int32?
if let maybePts = channelsToPoll[peer.id] {
pts = maybePts
}
return (peer, pts)
}))
} else {
if !channelPeers.isEmpty {
let resetSignal = resetChannels(accountPeerId: accountPeerId, postbox: postbox, network: network, peers: channelPeers, state: updatedState)
|> map { resultState -> (AccountMutableState, Bool, Int32?) in
return (resultState, true, nil)
}
pollChannelSignals = [resetSignal]
} else {
pollChannelSignals = []
}
}
} else {
for peerId in channelsToPoll.union(missingUpdatesFromChannels) {
for peerId in Set(channelsToPoll.keys).union(missingUpdatesFromChannels) {
if let peer = updatedState.peers[peerId] {
pollChannelSignals.append(pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: updatedState.branch()))
} else {
@ -2442,7 +2458,7 @@ func keepPollingChannel(accountPeerId: PeerId, postbox: Postbox, network: Networ
|> delay(1.0, queue: .concurrentDefaultQueue())
}
private func resetChannels(accountPeerId: PeerId, postbox: Postbox, network: Network, peers: [Peer], state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
func resetChannels(accountPeerId: PeerId, postbox: Postbox, network: Network, peers: [Peer], state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
var inputPeers: [Api.InputDialogPeer] = []
for peer in peers {
if let inputPeer = apiInputPeer(peer) {
@ -3065,12 +3081,15 @@ func replayFinalState(
auxiliaryMethods: AccountAuxiliaryMethods,
finalState: AccountFinalState,
removePossiblyDeliveredMessagesUniqueIds: [Int64: PeerId],
ignoreDate: Bool
ignoreDate: Bool,
skipVerification: Bool
) -> AccountReplayedFinalState? {
let verified = verifyTransaction(transaction, finalState: finalState.state)
if !verified {
Logger.shared.log("State", "failed to verify final state")
return nil
if !skipVerification {
let verified = verifyTransaction(transaction, finalState: finalState.state)
if !verified {
Logger.shared.log("State", "failed to verify final state")
return nil
}
}
var peerIdsWithAddedSecretMessages = Set<PeerId>()

File diff suppressed because it is too large Load Diff

View File

@ -41,17 +41,47 @@ public class AuthorizedAccountState: AccountState {
}
}
public struct InvalidatedChannel: PostboxCoding, Equatable {
public var peerId: PeerId
public var pts: Int32?
public var validityMarker: Int64
public init(peerId: PeerId, pts: Int32?, validityMarker: Int64) {
self.peerId = peerId
self.pts = pts
self.validityMarker = validityMarker
}
public init(decoder: PostboxDecoder) {
self.peerId = PeerId(decoder.decodeInt64ForKey("i", orElse: 0))
self.pts = decoder.decodeOptionalInt32ForKey("p")
self.validityMarker = decoder.decodeInt64ForKey("m", orElse: 0)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt64(self.peerId.toInt64(), forKey: "i")
if let pts = self.pts {
encoder.encodeInt32(pts, forKey: "p")
} else {
encoder.encodeNil(forKey: "p")
}
encoder.encodeInt64(self.validityMarker, forKey: "m")
}
}
public let isTestingEnvironment: Bool
public let masterDatacenterId: Int32
public let peerId: PeerId
public let state: State?
public let invalidatedChannels: [InvalidatedChannel]
public required init(decoder: PostboxDecoder) {
self.isTestingEnvironment = decoder.decodeInt32ForKey("isTestingEnvironment", orElse: 0) != 0
self.masterDatacenterId = decoder.decodeInt32ForKey("masterDatacenterId", orElse: 0)
self.peerId = PeerId(decoder.decodeInt64ForKey("peerId", orElse: 0))
self.state = decoder.decodeObjectForKey("state", decoder: { return State(decoder: $0) }) as? State
self.invalidatedChannels = decoder.decodeObjectArrayWithDecoderForKey("invalidatedChannels")
}
public func encode(_ encoder: PostboxEncoder) {
@ -61,24 +91,31 @@ public class AuthorizedAccountState: AccountState {
if let state = self.state {
encoder.encodeObject(state, forKey: "state")
}
encoder.encodeObjectArray(self.invalidatedChannels, forKey: "invalidatedChannels")
}
public init(isTestingEnvironment: Bool, masterDatacenterId: Int32, peerId: PeerId, state: State?) {
public init(isTestingEnvironment: Bool, masterDatacenterId: Int32, peerId: PeerId, state: State?, invalidatedChannels: [InvalidatedChannel]) {
self.isTestingEnvironment = isTestingEnvironment
self.masterDatacenterId = masterDatacenterId
self.peerId = peerId
self.state = state
self.invalidatedChannels = invalidatedChannels
}
public func changedState(_ state: State) -> AuthorizedAccountState {
return AuthorizedAccountState(isTestingEnvironment: self.isTestingEnvironment, masterDatacenterId: self.masterDatacenterId, peerId: self.peerId, state: state)
return AuthorizedAccountState(isTestingEnvironment: self.isTestingEnvironment, masterDatacenterId: self.masterDatacenterId, peerId: self.peerId, state: state, invalidatedChannels: self.invalidatedChannels)
}
public func withInvalidatedChannels(_ invalidatedChannels: [InvalidatedChannel]) -> AuthorizedAccountState {
return AuthorizedAccountState(isTestingEnvironment: self.isTestingEnvironment, masterDatacenterId: self.masterDatacenterId, peerId: self.peerId, state: self.state, invalidatedChannels: invalidatedChannels)
}
public func equalsTo(_ other: AccountState) -> Bool {
if let other = other as? AuthorizedAccountState {
return self.isTestingEnvironment == other.isTestingEnvironment && self.masterDatacenterId == other.masterDatacenterId &&
self.peerId == other.peerId &&
self.state == other.state
self.state == other.state &&
self.invalidatedChannels == other.invalidatedChannels
} else {
return false
}

View File

@ -99,7 +99,7 @@ func _internal_exportAuthTransferToken(accountManager: AccountManager<TelegramAc
return updatedAccount.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, peerId: user.id, state: nil)
let state = AuthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: updatedAccount.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
return accountManager.transaction { transaction -> ExportAuthTransferTokenResult in
@ -127,7 +127,7 @@ func _internal_exportAuthTransferToken(accountManager: AccountManager<TelegramAc
return account.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
return accountManager.transaction { transaction -> ExportAuthTransferTokenResult in