diff --git a/BUCK b/BUCK index bc6870f526..c9422e5f75 100644 --- a/BUCK +++ b/BUCK @@ -50,6 +50,8 @@ resource_dependencies = [ "//submodules/TelegramUI:TelegramUIResources", "//submodules/WalletUI:WalletUIAssets", "//submodules/WalletUI:WalletUIResources", + "//submodules/PasswordSetupUI:PasswordSetupUIResources", + "//submodules/PasswordSetupUI:PasswordSetupUIAssets", "//submodules/OverlayStatusController:OverlayStatusControllerResources", "//:AppResources", "//:AppStringResources", diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index d963ab180f..d0294f3d44 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -4820,7 +4820,7 @@ Any member of this group will be able to see messages in the channel."; "Wallet.Send.Balance" = "Balance: %@"; "Wallet.Send.AmountText" = "Grams to send"; "Wallet.Send.Confirmation" = "Confirmation"; -"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?"; +"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?\n\nFees: ~%3$@ grams"; "Wallet.Send.ConfirmationConfirm" = "Confirm"; "Wallet.Send.Send" = "Send"; "Wallet.Settings.Title" = "Wallet Settings"; @@ -4991,3 +4991,38 @@ Any member of this group will be able to see messages in the channel."; "Conversation.SwipeToReplyHintTitle" = "Swipe To Reply"; "Conversation.SwipeToReplyHintText" = "Swipe left on any message to reply to it."; + +"TwoFactorSetup.Intro.Title" = "Additional Password"; +"TwoFactorSetup.Intro.Text" = "You can set a password that will be\nrequired when you log in on a new device in addition to the code you get via SMS."; +"TwoFactorSetup.Intro.Action" = "Set Additional Password"; + +"TwoFactorSetup.Password.Title" = "Create Password"; +"TwoFactorSetup.Password.PlaceholderPassword" = "Password"; +"TwoFactorSetup.Password.PlaceholderConfirmPassword" = "Re-enter Password"; +"TwoFactorSetup.Password.Action" = "Create Password"; + +"TwoFactorSetup.Email.Title" = "Recovery Email"; +"TwoFactorSetup.Email.Text" = "You can set a recovery email to be able to reset password and restore access\nto your Telegram account."; +"TwoFactorSetup.Email.Placeholder" = "Your email address"; +"TwoFactorSetup.Email.Action" = "Continue"; +"TwoFactorSetup.Email.SkipAction" = "Skip setting email"; +"TwoFactorSetup.Email.SkipConfirmationTitle" = "No, seriously."; +"TwoFactorSetup.Email.SkipConfirmationText" = "If you forget your password, you will lose access to your Telegram account. There will be no way to restore it."; +"TwoFactorSetup.Email.SkipConfirmationSkip" = "Skip"; + +"TwoFactorSetup.EmailVerification.Title" = "Recovery Email"; +"TwoFactorSetup.EmailVerification.Text" = "Please enter code we've just emailed at %@"; +"TwoFactorSetup.EmailVerification.Placeholder" = "Code"; +"TwoFactorSetup.EmailVerification.Action" = "Continue"; +"TwoFactorSetup.EmailVerification.ChangeAction" = "Change Email"; +"TwoFactorSetup.EmailVerification.ResendAction" = "Resend Code"; + +"TwoFactorSetup.Hint.Title" = "Hint"; +"TwoFactorSetup.Hint.Text" = "You can create an optional hint for\nyour password."; +"TwoFactorSetup.Hint.Placeholder" = "Hint (optional)"; +"TwoFactorSetup.Hint.Action" = "Continue"; +"TwoFactorSetup.Hint.SkipAction" = "Skip setting hint"; + +"TwoFactorSetup.Done.Title" = "Password Set!"; +"TwoFactorSetup.Done.Text" = "Now password will be required when you log in on a new device in addition to the code you get via SMS."; +"TwoFactorSetup.Done.Action" = "Return to Settings"; diff --git a/Wallet/Strings/en.lproj/Localizable.strings b/Wallet/Strings/en.lproj/Localizable.strings index d94429257d..a7600f7b61 100644 --- a/Wallet/Strings/en.lproj/Localizable.strings +++ b/Wallet/Strings/en.lproj/Localizable.strings @@ -54,7 +54,7 @@ "Wallet.Send.Balance" = "Balance: %@"; "Wallet.Send.AmountText" = "Grams to send"; "Wallet.Send.Confirmation" = "Confirmation"; -"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?"; +"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?\n\nFees: ~%3$@ grams"; "Wallet.Send.ConfirmationConfirm" = "Confirm"; "Wallet.Send.Send" = "Send"; "Wallet.Settings.Title" = "Wallet Settings"; @@ -106,11 +106,11 @@ "Wallet.TransactionInfo.SenderHeader" = "SENDER"; "Wallet.TransactionInfo.CopyAddress" = "Copy Wallet Address"; "Wallet.TransactionInfo.AddressCopied" = "Address copied to clipboard."; -"Wallet.TransactionInfo.SendGrams" = "Send Grams"; +"Wallet.TransactionInfo.SendGrams" = "Send Grams to This Address"; "Wallet.TransactionInfo.CommentHeader" = "COMMENT"; "Wallet.TransactionInfo.StorageFeeHeader" = "STORAGE FEE"; "Wallet.TransactionInfo.OtherFeeHeader" = "TRANSACTION FEE"; -"Wallet.TransactionInfo.StorageFeeInfo" = "Blockchain validators collect a tiny fee for storing information about your decentralized wallet. [More info]()"; +"Wallet.TransactionInfo.StorageFeeInfo" = "Blockchain validators collect a tiny fee for storing information about your decentralized wallet and processing your transactions. [More info]()"; "Wallet.TransactionInfo.OtherFeeInfo" = "Blockchain validators collect a tiny fee for processing your decentralized transactions. [More info]()"; "Wallet.TransactionInfo.FeeInfoURL" = "https://telegram.org/wallet/fee"; "Wallet.WordCheck.Title" = "Test Time!"; diff --git a/submodules/Display/Display/TextAlertController.swift b/submodules/Display/Display/TextAlertController.swift index 2f88965a46..6590697d5c 100644 --- a/submodules/Display/Display/TextAlertController.swift +++ b/submodules/Display/Display/TextAlertController.swift @@ -171,6 +171,7 @@ public final class TextAlertContentNode: AlertContentNode { self.textNode.isLayerBacked = false self.textNode.isAccessibilityElement = true self.textNode.accessibilityLabel = text.string + self.textNode.insets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) if text.length != 0 { if let paragraphStyle = text.attribute(.paragraphStyle, at: 0, effectiveRange: nil) as? NSParagraphStyle { self.textNode.textAlignment = paragraphStyle.alignment @@ -292,7 +293,7 @@ public final class TextAlertContentNode: AlertContentNode { transition.updateFrame(node: titleNode, frame: titleFrame) let textFrame = CGRect(origin: CGPoint(x: insets.left + floor((contentWidth - textSize.width) / 2.0), y: titleFrame.maxY + spacing), size: textSize) - transition.updateFrame(node: self.textNode, frame: textFrame) + transition.updateFrame(node: self.textNode, frame: textFrame.offsetBy(dx: -1.0, dy: -1.0)) resultSize = CGSize(width: contentWidth + insets.left + insets.right, height: titleSize.height + spacing + textSize.height + actionsHeight + insets.top + insets.bottom) } else { diff --git a/submodules/PasswordSetupUI/BUCK b/submodules/PasswordSetupUI/BUCK index d909adc847..195891ab09 100644 --- a/submodules/PasswordSetupUI/BUCK +++ b/submodules/PasswordSetupUI/BUCK @@ -1,5 +1,21 @@ load("//Config:buck_rule_macros.bzl", "static_library") +apple_resource( + name = "PasswordSetupUIResources", + files = glob([ + "Resources/**/*", + ], exclude = ["Resources/**/.*"]), + visibility = ["PUBLIC"], +) + +apple_asset_catalog( + name = "PasswordSetupUIAssets", + dirs = [ + "PasswordSetupUIImages.xcassets", + ], + visibility = ["PUBLIC"], +) + static_library( name = "PasswordSetupUI", srcs = glob([ @@ -19,6 +35,11 @@ static_library( "//submodules/AlertUI:AlertUI", "//submodules/PresentationDataUtils:PresentationDataUtils", "//submodules/ItemListUI:ItemListUI", + "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/AppBundle:AppBundle", + "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode", + "//submodules/OverlayStatusController:OverlayStatusController", + "//submodules/rlottie:RLottieBinding", ], frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", diff --git a/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/Contents.json b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/Contents.json new file mode 100644 index 0000000000..da4a164c91 --- /dev/null +++ b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/Contents.json b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/Contents.json new file mode 100644 index 0000000000..38f0c81fc2 --- /dev/null +++ b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + }, + "properties" : { + "provides-namespace" : true + } +} \ No newline at end of file diff --git a/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/Contents.json b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/Contents.json new file mode 100644 index 0000000000..75b62ace42 --- /dev/null +++ b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "User.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/User.pdf b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/User.pdf new file mode 100644 index 0000000000..6ae0b01234 Binary files /dev/null and b/submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/User.pdf differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupDone.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupDone.tgs new file mode 100644 index 0000000000..456cc1e2fe Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupDone.tgs differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupHint.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupHint.tgs new file mode 100644 index 0000000000..c85dd321df Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupHint.tgs differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupIntro.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupIntro.tgs new file mode 100644 index 0000000000..8538275214 Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupIntro.tgs differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupMail.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMail.tgs new file mode 100644 index 0000000000..c8aa2e7b3b Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMail.tgs differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyClose.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyClose.tgs new file mode 100644 index 0000000000..f16eca5ada Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyClose.tgs differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyIdle.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyIdle.tgs new file mode 100644 index 0000000000..773ee9676b Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyIdle.tgs differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyPeek.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyPeek.tgs new file mode 100644 index 0000000000..07cca60ece Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyPeek.tgs differ diff --git a/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyTracking.tgs b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyTracking.tgs new file mode 100644 index 0000000000..ad52d48af3 Binary files /dev/null and b/submodules/PasswordSetupUI/Resources/TwoFactorSetupMonkeyTracking.tgs differ diff --git a/submodules/PasswordSetupUI/Sources/ManagedAnimationNode.swift b/submodules/PasswordSetupUI/Sources/ManagedAnimationNode.swift new file mode 100644 index 0000000000..e317b24242 --- /dev/null +++ b/submodules/PasswordSetupUI/Sources/ManagedAnimationNode.swift @@ -0,0 +1,256 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import RLottieBinding +import AppBundle +import GZip + +enum ManagedAnimationTrackState { + case intro + case loop + case outro +} + +private final class ManagedAnimationState { + var item: ManagedAnimationItem + + private let instance: LottieInstance + + let frameCount: Int + let fps: Double + + var startTime: Double? + var trackState: ManagedAnimationTrackState? + var trackingFrameState: (Int, Int)? + var frameIndex: Int? + + private let renderContext: DrawingContext + + init?(item: ManagedAnimationItem) { + guard let path = getAppBundle().path(forResource: item.name, ofType: "tgs") else { + return nil + } + guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { + return nil + } + guard let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024) else { + return nil + } + guard let instance = LottieInstance(data: unpackedData, cacheKey: item.name) else { + return nil + } + + self.item = item + self.instance = instance + + self.frameCount = Int(instance.frameCount) + self.fps = Double(instance.frameRate) + + self.renderContext = DrawingContext(size: instance.dimensions, scale: UIScreenScale, premultiplied: true, clear: true) + } + + func draw() -> UIImage? { + self.instance.renderFrame(with: Int32(self.frameIndex ?? 0), into: self.renderContext.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(self.renderContext.size.width * self.renderContext.scale), height: Int32(self.renderContext.size.height * self.renderContext.scale), bytesPerRow: Int32(self.renderContext.bytesPerRow)) + return self.renderContext.generateImage() + } +} + +enum ManagedAnimationActionAtEnd { + case pause + case advance + case loop +} + +struct ManagedAnimationTrack: Equatable { + let frameRange: Range +} + +struct ManagedAnimationItem: Equatable { + let name: String + var intro: ManagedAnimationTrack? + var loop: ManagedAnimationTrack? + var outro: ManagedAnimationTrack? +} + +final class ManagedAnimationNode: ASDisplayNode { + let intrinsicSize: CGSize + + private let imageNode: ASImageNode + private let displayLink: CADisplayLink + + private var items: [ManagedAnimationState] = [] + + var currentItemName: String? { + return self.items.first?.item.name + } + + init(size: CGSize) { + self.intrinsicSize = size + + self.imageNode = ASImageNode() + self.imageNode.displayWithoutProcessing = true + self.imageNode.displaysAsynchronously = false + self.imageNode.frame = CGRect(origin: CGPoint(), size: self.intrinsicSize) + + final class DisplayLinkTarget: NSObject { + private let f: () -> Void + + init(_ f: @escaping () -> Void) { + self.f = f + } + + @objc func event() { + self.f() + } + } + var displayLinkUpdate: (() -> Void)? + self.displayLink = CADisplayLink(target: DisplayLinkTarget { + displayLinkUpdate?() + }, selector: #selector(DisplayLinkTarget.event)) + + super.init() + + self.addSubnode(self.imageNode) + + self.displayLink.add(to: RunLoop.main, forMode: .common) + + displayLinkUpdate = { [weak self] in + self?.updateAnimation() + } + } + + private func updateAnimation() { + guard let item = self.items.first else { + return + } + let timestamp = CACurrentMediaTime() + var startTime: Double + let maybeTrackState: ManagedAnimationTrackState? + if let current = item.startTime { + startTime = current + } else { + startTime = timestamp + item.startTime = startTime + } + if let current = item.trackState { + maybeTrackState = current + } else if let _ = item.item.intro { + maybeTrackState = .intro + } else if let _ = item.item.loop { + maybeTrackState = .loop + } else if let _ = item.item.outro { + maybeTrackState = .outro + } else { + maybeTrackState = nil + } + if item.trackState != maybeTrackState { + item.trackState = maybeTrackState + item.startTime = timestamp + startTime = timestamp + } + + guard let trackState = maybeTrackState else { + self.items.removeFirst() + return + } + + var fps = item.fps + + let track: ManagedAnimationTrack + switch trackState { + case .intro: + track = item.item.intro! + case .loop: + track = item.item.loop! + if self.items.count > 1 { + //fps *= 2.0 + } + case .outro: + track = item.item.outro! + } + + let frameIndex: Int + if let (startFrame, endFrame) = item.trackingFrameState { + let duration: Double = 0.3 + var t = (timestamp - startTime) / duration + t = max(0.0, t) + t = min(1.0, t) + let frameOffset = Int(Double(startFrame) * (1.0 - t) + Double(endFrame) * t) + let lowerBound = min(track.frameRange.lowerBound, item.frameCount - 1) + let upperBound = min(track.frameRange.upperBound, item.frameCount) + frameIndex = max(lowerBound, min(upperBound, frameOffset)) + } else { + let frameOffset = Int((timestamp - startTime) * fps) + let lowerBound = min(track.frameRange.lowerBound, item.frameCount - 1) + let upperBound = min(track.frameRange.upperBound, item.frameCount) + if frameOffset >= upperBound - lowerBound { + switch trackState { + case .intro: + if let _ = item.item.loop { + item.trackState = .loop + item.startTime = timestamp + return + } else if let _ = item.item.outro { + item.trackState = .outro + item.startTime = timestamp + return + } else { + self.items.removeFirst() + return + } + case .loop: + if self.items.count > 1 { + if let _ = item.item.outro { + item.trackState = .outro + item.startTime = timestamp + } else { + self.items.removeFirst() + } + return + } else { + item.startTime = timestamp + frameIndex = lowerBound + } + case .outro: + self.items.removeFirst() + return + } + } else { + frameIndex = lowerBound + frameOffset % (upperBound - lowerBound) + } + } + + if item.frameIndex != frameIndex { + item.frameIndex = frameIndex + if let image = item.draw() { + self.imageNode.image = image + } + } + } + + func switchTo(_ item: ManagedAnimationItem, noOutro: Bool = false) { + if let state = ManagedAnimationState(item: item) { + if let last = self.items.last { + if last.item.name == item.name { + return + } + } + if let first = self.items.first { + if noOutro { + first.item.outro = nil + } + } + self.items.append(state) + self.updateAnimation() + } + } + + func trackTo(frameIndex: Int) { + if let first = self.items.first { + first.startTime = CACurrentMediaTime() + first.trackingFrameState = (first.frameIndex ?? 0, frameIndex) + self.updateAnimation() + } + } +} diff --git a/submodules/PasswordSetupUI/Sources/PasswordSetupUI.h b/submodules/PasswordSetupUI/Sources/PasswordSetupUI.h deleted file mode 100644 index 8d30612cf2..0000000000 --- a/submodules/PasswordSetupUI/Sources/PasswordSetupUI.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// PasswordSetupUI.h -// PasswordSetupUI -// -// Created by Peter on 8/12/19. -// Copyright © 2019 Telegram Messenger LLP. All rights reserved. -// - -#import - -//! Project version number for PasswordSetupUI. -FOUNDATION_EXPORT double PasswordSetupUIVersionNumber; - -//! Project version string for PasswordSetupUI. -FOUNDATION_EXPORT const unsigned char PasswordSetupUIVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift new file mode 100644 index 0000000000..8ed95ba5c8 --- /dev/null +++ b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift @@ -0,0 +1,1130 @@ +import Foundation +import UIKit +import AppBundle +import AsyncDisplayKit +import Display +import SolidRoundedButtonNode +import SwiftSignalKit +import OverlayStatusController +import AccountContext +import TelegramPresentationData +import PresentationDataUtils +import TelegramCore + +public enum TwoFactorDataInputMode { + case password + case emailAddress(password: String) + case emailConfirmation(password: String?, emailPattern: String) + case passwordHint(password: String) +} + +private let animationIdle = ManagedAnimationItem(name: "TwoFactorSetupMonkeyIdle", + intro: nil, + loop: ManagedAnimationTrack(frameRange: 0 ..< 1), + outro: nil +) + +private let animationTracking = ManagedAnimationItem(name: "TwoFactorSetupMonkeyTracking", + intro: nil, + loop: ManagedAnimationTrack(frameRange: 0 ..< Int.max), + outro: nil +) + +private let animationHide = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", + intro: ManagedAnimationTrack(frameRange: 0 ..< 41), + loop: ManagedAnimationTrack(frameRange: 40 ..< 41), + outro: ManagedAnimationTrack(frameRange: 60 ..< 99) +) + +private let animationHideNoOutro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", + intro: ManagedAnimationTrack(frameRange: 0 ..< 41), + loop: ManagedAnimationTrack(frameRange: 40 ..< 41), + outro: nil +) + +private let animationHideNoIntro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", + intro: nil, + loop: ManagedAnimationTrack(frameRange: 40 ..< 41), + outro: ManagedAnimationTrack(frameRange: 60 ..< 99) +) + +private let animationHideOutro = ManagedAnimationItem(name: "TwoFactorSetupMonkeyClose", + intro: nil, + loop: nil, + outro: ManagedAnimationTrack(frameRange: 60 ..< 99) +) + +private let animationPeek = ManagedAnimationItem(name: "TwoFactorSetupMonkeyPeek", + intro: ManagedAnimationTrack(frameRange: 0 ..< 14), + loop: ManagedAnimationTrack(frameRange: 13 ..< 14), + outro: ManagedAnimationTrack(frameRange: 14 ..< 34) +) + +private let animationMail = ManagedAnimationItem(name: "TwoFactorSetupMail", + intro: ManagedAnimationTrack(frameRange: 0 ..< Int.max), + loop: ManagedAnimationTrack(frameRange: Int.max - 1 ..< Int.max), + outro: nil +) + +private let animationHint = ManagedAnimationItem(name: "TwoFactorSetupHint", + intro: ManagedAnimationTrack(frameRange: 0 ..< Int.max), + loop: ManagedAnimationTrack(frameRange: Int.max - 1 ..< Int.max), + outro: nil +) + +public final class TwoFactorDataInputScreen: ViewController { + private let context: AccountContext + private var presentationData: PresentationData + private let mode: TwoFactorDataInputMode + + public init(context: AccountContext, mode: TwoFactorDataInputMode) { + self.context = context + self.mode = mode + + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + + let defaultTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme) + let navigationBarTheme = NavigationBarTheme(buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor) + + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Wallet_Navigation_Back, close: self.presentationData.strings.Wallet_Navigation_Close))) + + self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style + self.navigationPresentation = .modalInLargeLayout + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + self.navigationBar?.intrinsicCanTransitionInline = false + + self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Wallet_Navigation_Back, style: .plain, target: nil, action: nil) + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func backPressed() { + self.dismiss() + } + + override public func loadDisplayNode() { + self.displayNode = TwoFactorDataInputScreenNode(presentationData: self.presentationData, mode: self.mode, action: { [weak self] in + guard let strongSelf = self else { + return + } + switch strongSelf.mode { + case .password: + let values = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText + if values.count != 2 { + return + } + if values[0] != values[1] { + strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.TwoStepAuth_SetupPasswordConfirmFailed, actions: [ + TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {}) + ]), in: .window(.root)) + return + } + if values[0].isEmpty { + return + } + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + var controllers = navigationController.viewControllers.filter { controller in + if controller is TwoFactorAuthSplashScreen { + return false + } + if controller is TwoFactorDataInputScreen { + return false + } + return true + } + controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .passwordHint(password: values[0]))) + navigationController.setViewControllers(controllers, animated: true) + case let .emailAddress(password): + guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else { + return + } + let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil)) + strongSelf.present(statusController, in: .window(.root)) + + let _ = (updateTwoStepVerificationEmail(network: strongSelf.context.account.network, currentPassword: password, updatedEmail: text) + |> deliverOnMainQueue).start(next: { [weak statusController] result in + statusController?.dismiss() + + guard let strongSelf = self else { + return + } + + switch result { + case .none: + break + case let .password(password, pendingEmail): + if let pendingEmail = pendingEmail { + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + var controllers = navigationController.viewControllers.filter { controller in + if controller is TwoFactorAuthSplashScreen { + return false + } + if controller is TwoFactorDataInputScreen { + return false + } + return true + } + controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailConfirmation(password: password, emailPattern: text))) + navigationController.setViewControllers(controllers, animated: true) + } else { + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + var controllers = navigationController.viewControllers.filter { controller in + if controller is TwoFactorAuthSplashScreen { + return false + } + if controller is TwoFactorDataInputScreen { + return false + } + return true + } + controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done)) + navigationController.setViewControllers(controllers, animated: true) + } + } + }, error: { [weak statusController] error in + statusController?.dismiss() + + guard let strongSelf = self else { + return + } + + let presentationData = strongSelf.presentationData + let alertText: String + switch error { + case .generic: + alertText = presentationData.strings.Login_UnknownError + case .invalidEmail: + alertText = presentationData.strings.TwoStepAuth_EmailInvalid + } + strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: alertText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + }) + case .emailConfirmation: + guard let text = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !text.isEmpty else { + return + } + let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil)) + strongSelf.present(statusController, in: .window(.root)) + + let _ = (confirmTwoStepRecoveryEmail(network: strongSelf.context.account.network, code: text) + |> deliverOnMainQueue).start(error: { [weak statusController] error in + statusController?.dismiss() + + guard let strongSelf = self else { + return + } + + let presentationData = strongSelf.presentationData + let text: String + switch error { + case .invalidEmail: + text = presentationData.strings.TwoStepAuth_EmailInvalid + case .invalidCode: + text = presentationData.strings.Login_InvalidCodeError + case .expired: + text = presentationData.strings.TwoStepAuth_EmailCodeExpired + case .flood: + text = presentationData.strings.TwoStepAuth_FloodError + case .generic: + text = presentationData.strings.Login_UnknownError + } + strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + }, completed: { [weak statusController] in + statusController?.dismiss() + + guard let strongSelf = self else { + return + } + + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + var controllers = navigationController.viewControllers.filter { controller in + if controller is TwoFactorAuthSplashScreen { + return false + } + if controller is TwoFactorDataInputScreen { + return false + } + return true + } + controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done)) + navigationController.setViewControllers(controllers, animated: true) + }) + case let .passwordHint(password): + guard let value = (strongSelf.displayNode as! TwoFactorDataInputScreenNode).inputText.first, !value.isEmpty else { + return + } + + strongSelf.setPassword(password: password, hint: value) + } + }, skipAction: { [weak self] in + guard let strongSelf = self else { + return + } + switch strongSelf.mode { + case .emailAddress: + strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationTitle, text: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationText, actions: [ + TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationSkip, action: { + guard let strongSelf = self else { + return + } + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + var controllers = navigationController.viewControllers.filter { controller in + if controller is TwoFactorAuthSplashScreen { + return false + } + if controller is TwoFactorDataInputScreen { + return false + } + return true + } + controllers.append(TwoFactorAuthSplashScreen(context: strongSelf.context, mode: .done)) + navigationController.setViewControllers(controllers, animated: true) + }), + TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}) + ]), in: .window(.root)) + case let .passwordHint(password): + strongSelf.setPassword(password: password, hint: "") + default: + break + } + }, changeEmailAction: { [weak self] in + guard let strongSelf = self else { + return + } + switch strongSelf.mode { + case let .emailConfirmation(password, _): + if let password = password { + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + var controllers = navigationController.viewControllers.filter { controller in + if controller is TwoFactorAuthSplashScreen { + return false + } + if controller is TwoFactorDataInputScreen { + return false + } + return true + } + controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password))) + navigationController.setViewControllers(controllers, animated: true) + } else { + } + default: + break + } + }, resendCodeAction: { [weak self] in + guard let strongSelf = self else { + return + } + + let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil)) + strongSelf.present(statusController, in: .window(.root)) + + let _ = (resendTwoStepRecoveryEmail(network: strongSelf.context.account.network) + |> deliverOnMainQueue).start(error: { [weak statusController] error in + statusController?.dismiss() + + guard let strongSelf = self else { + return + } + + let text: String + switch error { + case .flood: + text = strongSelf.presentationData.strings.TwoStepAuth_FloodError + case .generic: + text = strongSelf.presentationData.strings.Login_UnknownError + } + strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + }, completed: { [weak statusController] in + statusController?.dismiss() + }) + }) + + self.displayNodeDidLoad() + } + + private func setPassword(password: String, hint: String) { + let statusController = OverlayStatusController(theme: self.presentationData.theme, type: .loading(cancelled: nil)) + self.present(statusController, in: .window(.root)) + + let _ = (updateTwoStepVerificationPassword(network: self.context.account.network, currentPassword: nil, updatedPassword: .password(password: password, hint: hint, email: nil)) + |> deliverOnMainQueue).start(next: { [weak self, weak statusController] _ in + statusController?.dismiss() + + guard let strongSelf = self else { + return + } + + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + var controllers = navigationController.viewControllers.filter { controller in + if controller is TwoFactorAuthSplashScreen { + return false + } + if controller is TwoFactorDataInputScreen { + return false + } + return true + } + controllers.append(TwoFactorDataInputScreen(context: strongSelf.context, mode: .emailAddress(password: password))) + navigationController.setViewControllers(controllers, animated: true) + }, error: { [weak self, weak statusController] _ in + statusController?.dismiss() + + guard let strongSelf = self else { + return + } + }) + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + (self.displayNode as! TwoFactorDataInputScreenNode).containerLayoutUpdated(layout: layout, navigationHeight: self.navigationHeight, transition: transition) + } +} + +private enum TwoFactorDataInputTextNodeType { + case password(confirmation: Bool) + case email + case code + case hint +} + +private func generateClearImage(color: UIColor) -> UIImage? { + return generateImage(CGSize(width: 16.0, height: 16.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(color.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) + context.setBlendMode(.copy) + context.setStrokeColor(UIColor.clear.cgColor) + context.setLineCap(.round) + context.setLineWidth(1.66) + context.move(to: CGPoint(x: 5.5, y: 5.5)) + context.addLine(to: CGPoint(x: 10.5, y: 10.5)) + context.strokePath() + context.move(to: CGPoint(x: size.width - 5.5, y: 5.5)) + context.addLine(to: CGPoint(x: size.width - 10.5, y: 10.5)) + context.strokePath() + }) +} + +private func generateTextHiddenImage(color: UIColor, on: Bool) -> UIImage? { + return generateImage(CGSize(width: 20.0, height: 18.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + guard let image = generateTintedImage(image: UIImage(bundleImageName: "PasswordSetup/TextHidden"), color: color) else { + return + } + context.draw(image.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - size.width) / 2.0), y: floor((size.height - size.height) / 2.0)), size: size)) + if !on { + context.setLineCap(.round) + + context.setBlendMode(.copy) + context.setStrokeColor(UIColor.clear.cgColor) + context.setLineWidth(4.0) + context.move(to: CGPoint(x: 2.0, y: 3.0)) + context.addLine(to: CGPoint(x: 18.0, y: 17.0)) + context.strokePath() + + context.setBlendMode(.normal) + context.setStrokeColor(color.cgColor) + context.setLineWidth(1.5) + context.move(to: CGPoint(x: 2.0, y: 3.0)) + context.addLine(to: CGPoint(x: 18.0, y: 17.0)) + context.strokePath() + } + }) +} + +private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelegate { + private let theme: PresentationTheme + let mode: TwoFactorDataInputTextNodeType + private let focused: (TwoFactorDataInputTextNode) -> Void + private let next: (TwoFactorDataInputTextNode) -> Void + private let updated: (TwoFactorDataInputTextNode) -> Void + private let toggleTextHidden: (TwoFactorDataInputTextNode) -> Void + + private let backgroundNode: ASImageNode + private let inputNode: TextFieldNode + private let hideButtonNode: HighlightableButtonNode + private let clearButtonNode: HighlightableButtonNode + + var text: String { + get { + return self.inputNode.textField.text ?? "" + } set(value) { + self.inputNode.textField.text = value + self.textFieldChanged(self.inputNode.textField) + } + } + + init(theme: PresentationTheme, mode: TwoFactorDataInputTextNodeType, placeholder: String, focused: @escaping (TwoFactorDataInputTextNode) -> Void, next: @escaping (TwoFactorDataInputTextNode) -> Void, updated: @escaping (TwoFactorDataInputTextNode) -> Void, toggleTextHidden: @escaping (TwoFactorDataInputTextNode) -> Void) { + self.theme = theme + self.mode = mode + self.focused = focused + self.next = next + self.updated = updated + self.toggleTextHidden = toggleTextHidden + + self.backgroundNode = ASImageNode() + self.backgroundNode.displaysAsynchronously = false + self.backgroundNode.displayWithoutProcessing = true + self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: theme.actionSheet.inputBackgroundColor) + + self.inputNode = TextFieldNode() + self.inputNode.textField.font = Font.regular(17.0) + self.inputNode.textField.textColor = theme.actionSheet.inputTextColor + self.inputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: theme.actionSheet.inputPlaceholderColor) + + self.hideButtonNode = HighlightableButtonNode() + + switch mode { + case let .password(confirmation): + self.inputNode.textField.keyboardType = .default + self.inputNode.textField.isSecureTextEntry = true + if confirmation { + self.inputNode.textField.returnKeyType = .done + } else { + self.inputNode.textField.returnKeyType = .next + } + self.hideButtonNode.isHidden = confirmation + case .email: + self.inputNode.textField.keyboardType = .emailAddress + self.inputNode.textField.returnKeyType = .done + self.hideButtonNode.isHidden = true + case .code: + self.inputNode.textField.keyboardType = .numberPad + self.inputNode.textField.returnKeyType = .done + self.hideButtonNode.isHidden = true + case .hint: + self.inputNode.textField.keyboardType = .asciiCapable + self.inputNode.textField.returnKeyType = .done + self.hideButtonNode.isHidden = true + } + + self.inputNode.textField.autocorrectionType = .no + self.inputNode.textField.autocapitalizationType = .none + self.inputNode.textField.spellCheckingType = .no + if #available(iOS 11.0, *) { + self.inputNode.textField.smartQuotesType = .no + self.inputNode.textField.smartDashesType = .no + self.inputNode.textField.smartInsertDeleteType = .no + } + self.inputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance + + self.hideButtonNode.setImage(generateTextHiddenImage(color: theme.actionSheet.inputClearButtonColor, on: false), for: []) + + self.clearButtonNode = HighlightableButtonNode() + self.clearButtonNode.setImage(generateClearImage(color: theme.actionSheet.inputClearButtonColor), for: []) + self.clearButtonNode.isHidden = true + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.inputNode) + self.addSubnode(self.hideButtonNode) + + self.inputNode.textField.delegate = self + self.inputNode.textField.addTarget(self, action: #selector(self.textFieldChanged(_:)), for: .editingChanged) + + self.hideButtonNode.addTarget(self, action: #selector(self.hidePressed), forControlEvents: .touchUpInside) + } + + func textFieldDidBeginEditing(_ textField: UITextField) { + let text = self.text + let isEmpty = text.isEmpty + self.focused(self) + } + + func textFieldDidEndEditing(_ textField: UITextField) { + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.next(self) + return false + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + return true + } + + @objc private func textFieldChanged(_ textField: UITextField) { + switch self.mode { + case .password: + break + default: + self.clearButtonNode.isHidden = self.text.isEmpty + } + self.updated(self) + } + + @objc private func hidePressed() { + switch self.mode { + case .password: + self.toggleTextHidden(self) + default: + break + } + } + + func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { + let leftInset: CGFloat = 16.0 + let rightInset: CGFloat = 38.0 + + transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrame(node: self.inputNode, frame: CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: size.width - leftInset - rightInset, height: size.height))) + transition.updateFrame(node: self.hideButtonNode, frame: CGRect(origin: CGPoint(x: size.width - rightInset - 4.0, y: 0.0), size: CGSize(width: rightInset + 4.0, height: size.height))) + transition.updateFrame(node: self.clearButtonNode, frame: CGRect(origin: CGPoint(x: size.width - rightInset - 4.0, y: 0.0), size: CGSize(width: rightInset + 4.0, height: size.height))) + } + + func focus() { + self.inputNode.textField.becomeFirstResponder() + } + + func updateTextHidden(_ value: Bool) { + self.hideButtonNode.setImage(generateTextHiddenImage(color: self.theme.actionSheet.inputClearButtonColor, on: !value), for: []) + self.inputNode.textField.isSecureTextEntry = value + } +} + +private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { + private var presentationData: PresentationData + private let mode: TwoFactorDataInputMode + private let action: () -> Void + private let skipAction: () -> Void + private let changeEmailAction: () -> Void + private let resendCodeAction: () -> Void + + private let navigationBackgroundNode: ASDisplayNode + private let navigationSeparatorNode: ASDisplayNode + private let scrollNode: ASScrollNode + private let animationNode: ManagedAnimationNode + private let titleNode: ImmediateTextNode + private let textNode: ImmediateTextNode + private let skipActionTitleNode: ImmediateTextNode + private let skipActionButtonNode: HighlightTrackingButtonNode + private let changeEmailActionTitleNode: ImmediateTextNode + private let changeEmailActionButtonNode: HighlightTrackingButtonNode + private let resendCodeActionTitleNode: ImmediateTextNode + private let resendCodeActionButtonNode: HighlightTrackingButtonNode + private let inputNodes: [TwoFactorDataInputTextNode] + private let buttonNode: SolidRoundedButtonNode + + private var navigationHeight: CGFloat? + + var inputText: [String] { + return self.inputNodes.map { $0.text } + } + + init(presentationData: PresentationData, mode: TwoFactorDataInputMode, action: @escaping () -> Void, skipAction: @escaping () -> Void, changeEmailAction: @escaping () -> Void, resendCodeAction: @escaping () -> Void) { + self.presentationData = presentationData + self.mode = mode + self.action = action + self.skipAction = skipAction + self.changeEmailAction = changeEmailAction + self.resendCodeAction = resendCodeAction + + self.navigationBackgroundNode = ASDisplayNode() + self.navigationBackgroundNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.backgroundColor + self.navigationBackgroundNode.alpha = 0.0 + self.navigationSeparatorNode = ASDisplayNode() + self.navigationSeparatorNode.backgroundColor = self.presentationData.theme.rootController.navigationBar.separatorColor + + self.scrollNode = ASScrollNode() + self.scrollNode.canCancelAllTouchesInViews = true + + self.animationNode = ManagedAnimationNode(size: CGSize(width: 136.0, height: 136.0)) + + let title: String + let text: NSAttributedString + let buttonText: String + let skipActionText: String + let changeEmailActionText: String + let resendCodeActionText: String + + var inputNodes: [TwoFactorDataInputTextNode] = [] + var next: ((TwoFactorDataInputTextNode) -> Void)? + var focused: ((TwoFactorDataInputTextNode) -> Void)? + var updated: ((TwoFactorDataInputTextNode) -> Void)? + var toggleTextHidden: ((TwoFactorDataInputTextNode) -> Void)? + + switch mode { + case .password: + self.animationNode.switchTo(animationIdle) + + title = presentationData.strings.TwoFactorSetup_Password_Title + text = NSAttributedString(string: "", font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + buttonText = presentationData.strings.TwoFactorSetup_Password_Action + skipActionText = "" + changeEmailActionText = "" + resendCodeActionText = "" + inputNodes = [ + TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: false), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderPassword, focused: { node in + focused?(node) + }, next: { node in + next?(node) + }, updated: { node in + updated?(node) + }, toggleTextHidden: { node in + toggleTextHidden?(node) + }), + TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .password(confirmation: true), placeholder: presentationData.strings.TwoFactorSetup_Password_PlaceholderConfirmPassword, focused: { node in + focused?(node) + }, next: { node in + next?(node) + }, updated: { node in + updated?(node) + }, toggleTextHidden: { node in + toggleTextHidden?(node) + }) + ] + case .emailAddress: + self.animationNode.switchTo(animationTracking) + + title = presentationData.strings.TwoFactorSetup_Email_Title + text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Email_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + buttonText = presentationData.strings.TwoFactorSetup_Email_Action + skipActionText = presentationData.strings.TwoFactorSetup_Email_SkipAction + changeEmailActionText = "" + resendCodeActionText = "" + inputNodes = [ + TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .email, placeholder: presentationData.strings.TwoFactorSetup_Email_Placeholder, focused: { node in + focused?(node) + }, next: { node in + next?(node) + }, updated: { node in + updated?(node) + }, toggleTextHidden: { node in + toggleTextHidden?(node) + }), + ] + case let .emailConfirmation(_, emailPattern): + self.animationNode.switchTo(animationMail) + + title = presentationData.strings.TwoFactorSetup_EmailVerification_Title + let (rawText, ranges) = presentationData.strings.TwoFactorSetup_EmailVerification_Text(emailPattern) + + let string = NSMutableAttributedString() + string.append(NSAttributedString(string: rawText, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor)) + for (_, range) in ranges { + string.addAttribute(.font, value: Font.semibold(16.0), range: range) + } + + text = string + + buttonText = presentationData.strings.TwoFactorSetup_EmailVerification_Action + skipActionText = "" + changeEmailActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ChangeAction + resendCodeActionText = presentationData.strings.TwoFactorSetup_EmailVerification_ResendAction + inputNodes = [ + TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .code, placeholder: presentationData.strings.TwoFactorSetup_EmailVerification_Placeholder, focused: { node in + focused?(node) + }, next: { node in + next?(node) + }, updated: { node in + updated?(node) + }, toggleTextHidden: { node in + toggleTextHidden?(node) + }), + ] + case .passwordHint: + self.animationNode.switchTo(animationHint) + + title = presentationData.strings.TwoFactorSetup_Hint_Title + + text = NSAttributedString(string: presentationData.strings.TwoFactorSetup_Hint_Text, font: Font.regular(16.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + + buttonText = presentationData.strings.TwoFactorSetup_Hint_Action + skipActionText = presentationData.strings.TwoFactorSetup_Hint_SkipAction + changeEmailActionText = "" + resendCodeActionText = "" + inputNodes = [ + TwoFactorDataInputTextNode(theme: presentationData.theme, mode: .hint, placeholder: presentationData.strings.TwoFactorSetup_Hint_Placeholder, focused: { node in + focused?(node) + }, next: { node in + next?(node) + }, updated: { node in + updated?(node) + }, toggleTextHidden: { node in + toggleTextHidden?(node) + }), + ] + } + + self.titleNode = ImmediateTextNode() + self.titleNode.displaysAsynchronously = false + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(28.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) + self.titleNode.maximumNumberOfLines = 0 + self.titleNode.textAlignment = .center + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.attributedText = text + self.textNode.maximumNumberOfLines = 0 + self.textNode.lineSpacing = 0.1 + self.textNode.textAlignment = .center + + self.skipActionTitleNode = ImmediateTextNode() + self.skipActionTitleNode.isUserInteractionEnabled = false + self.skipActionTitleNode.displaysAsynchronously = false + self.skipActionTitleNode.attributedText = NSAttributedString(string: skipActionText, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemAccentColor) + self.skipActionButtonNode = HighlightTrackingButtonNode() + self.skipActionTitleNode.isHidden = skipActionText.isEmpty + self.skipActionButtonNode.isHidden = skipActionText.isEmpty + + self.changeEmailActionTitleNode = ImmediateTextNode() + self.changeEmailActionTitleNode.isUserInteractionEnabled = false + self.changeEmailActionTitleNode.displaysAsynchronously = false + self.changeEmailActionTitleNode.attributedText = NSAttributedString(string: changeEmailActionText, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemAccentColor) + self.changeEmailActionButtonNode = HighlightTrackingButtonNode() + self.changeEmailActionButtonNode.isHidden = changeEmailActionText.isEmpty + self.changeEmailActionButtonNode.isHidden = changeEmailActionText.isEmpty + + self.resendCodeActionTitleNode = ImmediateTextNode() + self.resendCodeActionTitleNode.isUserInteractionEnabled = false + self.resendCodeActionTitleNode.displaysAsynchronously = false + self.resendCodeActionTitleNode.attributedText = NSAttributedString(string: resendCodeActionText, font: Font.regular(16.0), textColor: self.presentationData.theme.list.itemAccentColor) + self.resendCodeActionButtonNode = HighlightTrackingButtonNode() + self.resendCodeActionTitleNode.isHidden = resendCodeActionText.isEmpty + self.resendCodeActionButtonNode.isHidden = resendCodeActionText.isEmpty + + self.inputNodes = inputNodes + + self.buttonNode = SolidRoundedButtonNode(title: buttonText, theme: SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: self.presentationData.theme.list.itemCheckColors.foregroundColor), height: 50.0, cornerRadius: 10.0, gloss: false) + + super.init() + + self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor + + self.addSubnode(self.scrollNode) + + self.scrollNode.addSubnode(self.animationNode) + self.scrollNode.addSubnode(self.titleNode) + self.scrollNode.addSubnode(self.textNode) + self.scrollNode.addSubnode(self.skipActionTitleNode) + self.scrollNode.addSubnode(self.skipActionButtonNode) + self.scrollNode.addSubnode(self.changeEmailActionTitleNode) + self.scrollNode.addSubnode(self.changeEmailActionButtonNode) + self.scrollNode.addSubnode(self.resendCodeActionTitleNode) + self.scrollNode.addSubnode(self.resendCodeActionButtonNode) + self.scrollNode.addSubnode(self.buttonNode) + + for (inputNode) in self.inputNodes { + self.scrollNode.addSubnode(inputNode) + } + + self.navigationBackgroundNode.addSubnode(self.navigationSeparatorNode) + self.addSubnode(self.navigationBackgroundNode) + + self.buttonNode.pressed = { + action() + } + + self.skipActionButtonNode.highligthedChanged = { [weak self] highlighted in + guard let strongSelf = self else { + return + } + if highlighted { + strongSelf.skipActionTitleNode.layer.removeAnimation(forKey: "opacity") + strongSelf.skipActionTitleNode.alpha = 0.4 + } else { + strongSelf.skipActionTitleNode.alpha = 1.0 + strongSelf.skipActionTitleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + self.skipActionButtonNode.addTarget(self, action: #selector(self.skipActionPressed), forControlEvents: .touchUpInside) + + self.changeEmailActionButtonNode.highligthedChanged = { [weak self] highlighted in + guard let strongSelf = self else { + return + } + if highlighted { + strongSelf.changeEmailActionTitleNode.layer.removeAnimation(forKey: "opacity") + strongSelf.changeEmailActionTitleNode.alpha = 0.4 + } else { + strongSelf.changeEmailActionTitleNode.alpha = 1.0 + strongSelf.changeEmailActionTitleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + self.changeEmailActionButtonNode.addTarget(self, action: #selector(self.changeEmailActionPressed), forControlEvents: .touchUpInside) + + self.resendCodeActionButtonNode.highligthedChanged = { [weak self] highlighted in + guard let strongSelf = self else { + return + } + if highlighted { + strongSelf.resendCodeActionTitleNode.layer.removeAnimation(forKey: "opacity") + strongSelf.resendCodeActionTitleNode.alpha = 0.4 + } else { + strongSelf.resendCodeActionTitleNode.alpha = 1.0 + strongSelf.resendCodeActionTitleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + self.resendCodeActionButtonNode.addTarget(self, action: #selector(self.resendCodeActionPressed), forControlEvents: .touchUpInside) + + next = { [weak self] node in + guard let strongSelf = self else { + return + } + + } + focused = { [weak self] node in + DispatchQueue.main.async { + guard let strongSelf = self else { + return + } + } + } + var textHidden = true + let updateAnimations: () -> Void = { [weak self] in + guard let strongSelf = self else { + return + } + let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty }) + switch strongSelf.mode { + case .password: + if !hasText { + if strongSelf.animationNode.currentItemName == animationPeek.name { + strongSelf.animationNode.switchTo(animationHideOutro) + strongSelf.animationNode.switchTo(animationIdle) + } else { + strongSelf.animationNode.switchTo(animationIdle) + } + } else if textHidden { + if strongSelf.animationNode.currentItemName == animationPeek.name { + strongSelf.animationNode.switchTo(animationHideNoIntro) + } else { + strongSelf.animationNode.switchTo(animationHide) + } + } else { + if strongSelf.animationNode.currentItemName != animationPeek.name { + if strongSelf.animationNode.currentItemName == animationHide.name { + strongSelf.animationNode.switchTo(animationPeek, noOutro: true) + } else if strongSelf.animationNode.currentItemName == animationIdle.name { + strongSelf.animationNode.switchTo(animationHideNoOutro) + strongSelf.animationNode.switchTo(animationPeek) + } else { + strongSelf.animationNode.switchTo(animationPeek, noOutro: strongSelf.animationNode.currentItemName == animationHide.name) + } + } + } + case .emailAddress: + let textLength = strongSelf.inputNodes[0].text.count + let maxWidth = strongSelf.inputNodes[0].bounds.width + if textLength == 0 || maxWidth.isZero { + strongSelf.animationNode.trackTo(frameIndex: 0) + } else { + let textNode = ImmediateTextNode() + textNode.attributedText = NSAttributedString(string: strongSelf.inputNodes[0].text, font: Font.regular(17.0), textColor: .black) + let textSize = textNode.updateLayout(CGSize(width: 1000.0, height: 100.0)) + + let maxTextLength = 20 + let lowerBound = 14 + let upperBound = 160 + var trackingOffset = textSize.width / maxWidth + trackingOffset = max(0.0, min(1.0, trackingOffset)) + let frameIndex = lowerBound + Int(trackingOffset * CGFloat(upperBound - lowerBound)) + strongSelf.animationNode.trackTo(frameIndex: frameIndex) + } + default: + break + } + } + updated = { [weak self] _ in + guard let strongSelf = self else { + return + } + switch strongSelf.mode { + case .emailAddress: + let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty }) + strongSelf.buttonNode.isHidden = !hasText + strongSelf.skipActionTitleNode.isHidden = hasText + strongSelf.skipActionButtonNode.isHidden = hasText + case .emailConfirmation: + let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty }) + strongSelf.buttonNode.isHidden = !hasText + strongSelf.changeEmailActionTitleNode.isHidden = hasText + strongSelf.changeEmailActionButtonNode.isHidden = hasText + strongSelf.resendCodeActionTitleNode.isHidden = hasText + strongSelf.resendCodeActionButtonNode.isHidden = hasText + case .passwordHint: + let hasText = strongSelf.inputNodes.contains(where: { !$0.text.isEmpty }) + strongSelf.buttonNode.isHidden = !hasText + strongSelf.skipActionTitleNode.isHidden = hasText + strongSelf.skipActionButtonNode.isHidden = hasText + case .password: + break + } + updateAnimations() + } + toggleTextHidden = { [weak self] _ in + guard let strongSelf = self else { + return + } + switch strongSelf.mode { + case .password: + textHidden = !textHidden + for node in strongSelf.inputNodes { + node.updateTextHidden(textHidden) + } + default: + break + } + updateAnimations() + } + self.inputNodes.first.flatMap { updated?($0) } + } + + @objc private func skipActionPressed() { + self.skipAction() + } + + @objc private func changeEmailActionPressed() { + self.changeEmailAction() + } + + @objc private func resendCodeActionPressed() { + self.resendCodeAction() + } + + override func didLoad() { + super.didLoad() + + self.scrollNode.view.keyboardDismissMode = .none + self.scrollNode.view.delaysContentTouches = false + self.scrollNode.view.canCancelContentTouches = true + //self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true + self.scrollNode.view.alwaysBounceVertical = false + self.scrollNode.view.showsVerticalScrollIndicator = false + self.scrollNode.view.showsHorizontalScrollIndicator = false + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.scrollNode.view.contentInsetAdjustmentBehavior = .never + } + self.scrollNode.view.delegate = self + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + } + + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) { + self.navigationHeight = navigationHeight + + let contentAreaSize = layout.size + let availableAreaSize = CGSize(width: layout.size.width, height: layout.size.height - layout.insets(options: [.input]).bottom) + + let sideInset: CGFloat = 32.0 + let buttonSideInset: CGFloat = 48.0 + let iconSpacing: CGFloat = 2.0 + let titleSpacing: CGFloat = 19.0 + let titleInputSpacing: CGFloat = 26.0 + let textSpacing: CGFloat = 30.0 + let buttonHeight: CGFloat = 50.0 + let buttonSpacing: CGFloat = 20.0 + let rowSpacing: CGFloat = 20.0 + + transition.updateFrame(node: self.navigationBackgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: contentAreaSize.width, height: navigationHeight))) + transition.updateFrame(node: self.navigationSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationHeight), size: CGSize(width: contentAreaSize.width, height: UIScreenPixel))) + + transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: contentAreaSize)) + + let iconSize: CGSize = self.animationNode.intrinsicSize + + let titleSize = self.titleNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height)) + let textSize = self.textNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height)) + let skipActionSize = self.skipActionTitleNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height)) + let changeEmailActionSize = self.changeEmailActionTitleNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height)) + let resendCodeActionSize = self.resendCodeActionTitleNode.updateLayout(CGSize(width: contentAreaSize.width - sideInset * 2.0, height: contentAreaSize.height)) + + var calculatedContentHeight = iconSize.height + iconSpacing + titleSize.height + if textSize.width.isZero { + calculatedContentHeight += titleInputSpacing + } else { + calculatedContentHeight += titleSpacing + textSize.height + textSpacing + } + for i in 0 ..< self.inputNodes.count { + if i != 0 { + calculatedContentHeight += rowSpacing + } + calculatedContentHeight += 50.0 + } + calculatedContentHeight += buttonHeight + buttonSpacing + + var contentHeight: CGFloat = 0.0 + + let insets = layout.insets(options: [.input]) + let areaHeight = layout.size.height - insets.top - insets.bottom + let contentVerticalOrigin = max(layout.statusBarHeight ?? 0.0, floor((areaHeight - calculatedContentHeight) / 2.0)) + + let iconFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize) + transition.updateFrame(node: self.animationNode, frame: iconFrame) + let titleFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize) + transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame) + let textFrame: CGRect + if textSize.width.isZero { + textFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - textSize.width) / 2.0), y: titleFrame.maxY), size: textSize) + } else { + textFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize) + } + transition.updateFrameAdditive(node: self.textNode, frame: textFrame) + + contentHeight = textFrame.maxY + if textSize.width.isZero { + contentHeight += titleInputSpacing + } else { + contentHeight += textSpacing + } + + let rowWidth = contentAreaSize.width - buttonSideInset * 2.0 + + for i in 0 ..< self.inputNodes.count { + let inputNode = self.inputNodes[i] + if i != 0 { + contentHeight += rowSpacing + } + let inputNodeSize = CGSize(width: rowWidth, height: 50.0) + transition.updateFrame(node: inputNode, frame: CGRect(origin: CGPoint(x: buttonSideInset, y: contentHeight), size: inputNodeSize)) + inputNode.updateLayout(size: inputNodeSize, transition: transition) + contentHeight += inputNodeSize.height + } + + let minimalBottomInset: CGFloat = 74.0 + let buttonBottomInset = layout.intrinsicInsets.bottom + minimalBottomInset + let bottomInset = layout.intrinsicInsets.bottom + buttonSpacing + + let buttonWidth = contentAreaSize.width - buttonSideInset * 2.0 + + let maxButtonY = min(areaHeight - buttonSpacing, layout.size.height - buttonBottomInset) - buttonHeight + + let buttonFrame = CGRect(origin: CGPoint(x: floor((contentAreaSize.width - buttonWidth) / 2.0), y: max(contentHeight + buttonSpacing, maxButtonY)), size: CGSize(width: buttonWidth, height: buttonHeight)) + transition.updateFrame(node: self.buttonNode, frame: buttonFrame) + self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition) + transition.updateFrame(node: self.skipActionButtonNode, frame: buttonFrame) + transition.updateFrame(node: self.skipActionTitleNode, frame: CGRect(origin: CGPoint(x: buttonFrame.minX + floor((buttonFrame.width - skipActionSize.width) / 2.0), y: buttonFrame.minY + floor((buttonFrame.height - skipActionSize.height) / 2.0)), size: skipActionSize)) + + transition.updateFrame(node: self.changeEmailActionButtonNode, frame: CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.minY), size: CGSize(width: floor(buttonFrame.width / 2.0), height: buttonFrame.height))) + transition.updateFrame(node: self.resendCodeActionButtonNode, frame: CGRect(origin: CGPoint(x: buttonFrame.maxX - floor(buttonFrame.width / 2.0), y: buttonFrame.minY), size: CGSize(width: floor(buttonFrame.width / 2.0), height: buttonFrame.height))) + + transition.updateFrame(node: self.changeEmailActionTitleNode, frame: CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.minY + floor((buttonFrame.height - changeEmailActionSize.height) / 2.0)), size: changeEmailActionSize)) + transition.updateFrame(node: self.resendCodeActionTitleNode, frame: CGRect(origin: CGPoint(x: buttonFrame.maxX - resendCodeActionSize.width, y: buttonFrame.minY + floor((buttonFrame.height - resendCodeActionSize.height) / 2.0)), size: resendCodeActionSize)) + + transition.animateView { + self.scrollNode.view.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.insets(options: [.input]).bottom, right: 0.0) + self.scrollNode.view.contentSize = CGSize(width: contentAreaSize.width, height: max(availableAreaSize.height, buttonFrame.maxY + bottomInset)) + } + } +} + diff --git a/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift b/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift new file mode 100644 index 0000000000..bcffb2adaf --- /dev/null +++ b/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift @@ -0,0 +1,207 @@ +import Foundation +import UIKit +import AppBundle +import AsyncDisplayKit +import Display +import SolidRoundedButtonNode +import SwiftSignalKit +import OverlayStatusController +import AnimatedStickerNode +import AccountContext +import TelegramPresentationData +import PresentationDataUtils + +public enum TwoFactorAuthSplashMode { + case intro + case done +} + +public final class TwoFactorAuthSplashScreen: ViewController { + private let context: AccountContext + private var presentationData: PresentationData + private var mode: TwoFactorAuthSplashMode + + public init(context: AccountContext, mode: TwoFactorAuthSplashMode) { + self.context = context + self.mode = mode + + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + + let defaultTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme) + let navigationBarTheme = NavigationBarTheme(buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor) + + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Wallet_Intro_NotNow, close: self.presentationData.strings.Wallet_Navigation_Close))) + + self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style + self.navigationPresentation = .modalInLargeLayout + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + self.navigationBar?.intrinsicCanTransitionInline = false + + self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Wallet_Navigation_Back, style: .plain, target: nil, action: nil) + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + } + + override public func loadDisplayNode() { + self.displayNode = TwoFactorAuthSplashScreenNode(context: self.context, presentationData: self.presentationData, mode: self.mode, action: { [weak self] in + guard let strongSelf = self else { + return + } + switch strongSelf.mode { + case .intro: + strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .password)) + case .done: + guard let navigationController = strongSelf.navigationController as? NavigationController else { + return + } + navigationController.filterController(strongSelf, animated: true) + } + }) + + self.displayNodeDidLoad() + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + (self.displayNode as! TwoFactorAuthSplashScreenNode).containerLayoutUpdated(layout: layout, navigationHeight: self.navigationHeight, transition: transition) + } +} + +private final class TwoFactorAuthSplashScreenNode: ViewControllerTracingNode { + private var presentationData: PresentationData + private let mode: TwoFactorAuthSplashMode + + private var animationSize: CGSize = CGSize() + private var animationOffset: CGPoint = CGPoint() + private let animationNode: AnimatedStickerNode + private let titleNode: ImmediateTextNode + private let textNode: ImmediateTextNode + let buttonNode: SolidRoundedButtonNode + + var inProgress: Bool = false { + didSet { + self.buttonNode.isUserInteractionEnabled = !self.inProgress + self.buttonNode.alpha = self.inProgress ? 0.6 : 1.0 + } + } + + init(context: AccountContext, presentationData: PresentationData, mode: TwoFactorAuthSplashMode, action: @escaping () -> Void) { + self.presentationData = presentationData + self.mode = mode + + self.animationNode = AnimatedStickerNode() + + let title: String + let text: NSAttributedString + let buttonText: String + + let textFont = Font.regular(16.0) + let textColor = self.presentationData.theme.list.itemPrimaryTextColor + + switch mode { + case .intro: + title = self.presentationData.strings.TwoFactorSetup_Intro_Title + text = NSAttributedString(string: self.presentationData.strings.TwoFactorSetup_Intro_Text, font: textFont, textColor: textColor) + buttonText = self.presentationData.strings.TwoFactorSetup_Intro_Action + + if let path = getAppBundle().path(forResource: "TwoFactorSetupIntro", ofType: "tgs") { + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, playbackMode: .once, mode: .direct) + self.animationSize = CGSize(width: 124.0, height: 124.0) + self.animationNode.visibility = true + } + case .done: + title = self.presentationData.strings.TwoFactorSetup_Done_Title + text = NSAttributedString(string: self.presentationData.strings.TwoFactorSetup_Done_Text, font: textFont, textColor: textColor) + buttonText = self.presentationData.strings.TwoFactorSetup_Done_Action + + if let path = getAppBundle().path(forResource: "TwoFactorSetupDone", ofType: "tgs") { + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, mode: .direct) + self.animationSize = CGSize(width: 124.0, height: 124.0) + self.animationNode.visibility = true + } + } + + self.titleNode = ImmediateTextNode() + self.titleNode.displaysAsynchronously = false + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(32.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor) + self.titleNode.maximumNumberOfLines = 0 + self.titleNode.textAlignment = .center + + self.textNode = ImmediateTextNode() + self.textNode.displaysAsynchronously = false + self.textNode.attributedText = text + self.textNode.maximumNumberOfLines = 0 + self.textNode.lineSpacing = 0.1 + self.textNode.textAlignment = .center + + self.buttonNode = SolidRoundedButtonNode(title: buttonText, theme: SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: self.presentationData.theme.list.itemCheckColors.foregroundColor), height: 50.0, cornerRadius: 10.0, gloss: false) + self.buttonNode.isHidden = buttonText.isEmpty + + super.init() + + self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor + + self.addSubnode(self.animationNode) + self.addSubnode(self.titleNode) + self.addSubnode(self.textNode) + self.addSubnode(self.buttonNode) + + self.buttonNode.pressed = { + action() + } + } + + override func didLoad() { + super.didLoad() + } + + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) { + let sideInset: CGFloat = 32.0 + let buttonSideInset: CGFloat = 48.0 + let iconSpacing: CGFloat = 8.0 + let titleSpacing: CGFloat = 19.0 + let buttonHeight: CGFloat = 50.0 + + let iconSize: CGSize = self.animationSize + var iconOffset = CGPoint() + switch self.mode { + case .done: + iconOffset.x = 10.0 + default: + break + } + + let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height)) + let textSize = self.textNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height)) + + let contentHeight = iconSize.height + iconSpacing + titleSize.height + titleSpacing + textSize.height + var contentVerticalOrigin = floor((layout.size.height - contentHeight - iconSize.height / 2.0) / 2.0) + + let minimalBottomInset: CGFloat = 60.0 + let bottomInset = layout.intrinsicInsets.bottom + minimalBottomInset + + let buttonWidth = layout.size.width - buttonSideInset * 2.0 + + let buttonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonWidth) / 2.0), y: layout.size.height - bottomInset - buttonHeight), size: CGSize(width: buttonWidth, height: buttonHeight)) + transition.updateFrame(node: self.buttonNode, frame: buttonFrame) + self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition) + + var maxContentVerticalOrigin = buttonFrame.minY - 12.0 - contentHeight + + contentVerticalOrigin = min(contentVerticalOrigin, maxContentVerticalOrigin) + + let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0) + self.animationOffset.x, y: contentVerticalOrigin + self.animationOffset.y), size: iconSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y) + self.animationNode.updateLayout(size: iconFrame.size) + transition.updateFrameAdditive(node: self.animationNode, frame: iconFrame) + let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize) + transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame) + let textFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize) + transition.updateFrameAdditive(node: self.textNode, frame: textFrame) + } +} diff --git a/submodules/SettingsUI/BUCK b/submodules/SettingsUI/BUCK index b11d491874..d3517e5939 100644 --- a/submodules/SettingsUI/BUCK +++ b/submodules/SettingsUI/BUCK @@ -80,9 +80,9 @@ static_library( "//submodules/ContextUI:ContextUI", "//submodules/WalletUI:WalletUI", "//submodules/Markdown:Markdown", - "//submodules/PhoneNumberFormat:PhoneNumberFormat", "//submodules/UndoUI:UndoUI", "//submodules/DeleteChatPeerActionSheetItem:DeleteChatPeerActionSheetItem", + "//submodules/PhoneNumberFormat:PhoneNumberFormat", ], frameworks = [ "$SDKROOT/System/Library/Frameworks/Foundation.framework", diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 3fb813e6a3..e1440701ed 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -14,6 +14,7 @@ import AccountContext import TelegramNotices import LocalAuth import AppBundle +import PasswordSetupUI private final class PrivacyAndSecurityControllerArguments { let account: Account @@ -640,7 +641,14 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting case .set: break case let .notSet(pendingEmail): - intro = pendingEmail == nil + if pendingEmail == nil { + let controller = TwoFactorAuthSplashScreen(context: context, mode: .intro) + pushControllerImpl?(controller, true) + } else { + + } + //intro = pendingEmail == nil + return } } if intro { diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index 7343029175..ff2e48763c 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -339,9 +339,9 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr inputBackgroundColor: UIColor(rgb: 0xe9e9e9), inputHollowBackgroundColor: .white, inputBorderColor: UIColor(rgb: 0xe4e4e6), - inputPlaceholderColor: UIColor(rgb: 0x818086), + inputPlaceholderColor: UIColor(rgb: 0x8E8D92), inputTextColor: .black, - inputClearButtonColor: UIColor(rgb: 0x7b7b81), + inputClearButtonColor: UIColor(rgb: 0xBCBCC0), checkContentColor: .white ) diff --git a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift index 22ef7a1eb7..3d58b8f41e 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationStrings.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationStrings.swift @@ -444,4255 +444,4294 @@ public final class PresentationStrings: Equatable { public var Passport_Identity_DateOfBirth: String { return self._s[234]! } public var Month_ShortOctober: String { return self._s[235]! } public var SettingsSearch_Synonyms_Privacy_Data_ContactsSync: String { return self._s[236]! } - public var Notification_CallCanceledShort: String { return self._s[237]! } - public var Passport_Phone_Help: String { return self._s[238]! } - public var Passport_Language_az: String { return self._s[240]! } - public var CreatePoll_TextPlaceholder: String { return self._s[242]! } - public var VoiceOver_Chat_AnonymousPoll: String { return self._s[243]! } - public var Passport_Identity_DocumentNumber: String { return self._s[244]! } - public var PhotoEditor_CurvesRed: String { return self._s[245]! } - public var PhoneNumberHelp_Alert: String { return self._s[247]! } - public var SocksProxySetup_Port: String { return self._s[248]! } - public var Checkout_PayNone: String { return self._s[249]! } - public var AutoDownloadSettings_WiFi: String { return self._s[250]! } - public var GroupInfo_GroupType: String { return self._s[251]! } - public var StickerSettings_ContextHide: String { return self._s[252]! } - public var Passport_Address_OneOfTypeTemporaryRegistration: String { return self._s[253]! } - public var Group_Setup_HistoryTitle: String { return self._s[255]! } - public var Passport_Identity_FilesUploadNew: String { return self._s[256]! } - public var PasscodeSettings_AutoLock: String { return self._s[257]! } - public var Passport_Title: String { return self._s[258]! } - public var VoiceOver_Chat_ContactPhoneNumber: String { return self._s[259]! } - public var Channel_AdminLogFilter_EventsNewSubscribers: String { return self._s[260]! } - public var GroupPermission_NoSendGifs: String { return self._s[261]! } - public var PrivacySettings_PasscodeOn: String { return self._s[262]! } + public var TwoFactorSetup_Done_Text: String { return self._s[237]! } + public var Notification_CallCanceledShort: String { return self._s[238]! } + public var Passport_Phone_Help: String { return self._s[239]! } + public var Passport_Language_az: String { return self._s[241]! } + public var CreatePoll_TextPlaceholder: String { return self._s[243]! } + public var VoiceOver_Chat_AnonymousPoll: String { return self._s[244]! } + public var Passport_Identity_DocumentNumber: String { return self._s[245]! } + public var PhotoEditor_CurvesRed: String { return self._s[246]! } + public var PhoneNumberHelp_Alert: String { return self._s[248]! } + public var SocksProxySetup_Port: String { return self._s[249]! } + public var Checkout_PayNone: String { return self._s[250]! } + public var AutoDownloadSettings_WiFi: String { return self._s[251]! } + public var GroupInfo_GroupType: String { return self._s[252]! } + public var StickerSettings_ContextHide: String { return self._s[253]! } + public var Passport_Address_OneOfTypeTemporaryRegistration: String { return self._s[254]! } + public var Group_Setup_HistoryTitle: String { return self._s[256]! } + public var Passport_Identity_FilesUploadNew: String { return self._s[257]! } + public var PasscodeSettings_AutoLock: String { return self._s[258]! } + public var Passport_Title: String { return self._s[259]! } + public var VoiceOver_Chat_ContactPhoneNumber: String { return self._s[260]! } + public var Channel_AdminLogFilter_EventsNewSubscribers: String { return self._s[261]! } + public var GroupPermission_NoSendGifs: String { return self._s[262]! } + public var PrivacySettings_PasscodeOn: String { return self._s[263]! } public func Conversation_ScheduleMessage_SendTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[263]!, self._r[263]!, [_0]) + return formatWithArgumentRanges(self._s[264]!, self._r[264]!, [_0]) } - public var State_WaitingForNetwork: String { return self._s[265]! } + public var State_WaitingForNetwork: String { return self._s[266]! } public func Notification_Invited(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[266]!, self._r[266]!, [_0, _1]) + return formatWithArgumentRanges(self._s[267]!, self._r[267]!, [_0, _1]) } - public var Calls_NotNow: String { return self._s[268]! } + public var Calls_NotNow: String { return self._s[269]! } public func Channel_DiscussionGroup_HeaderSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[269]!, self._r[269]!, [_0]) + return formatWithArgumentRanges(self._s[270]!, self._r[270]!, [_0]) } - public var UserInfo_SendMessage: String { return self._s[270]! } - public var TwoStepAuth_PasswordSet: String { return self._s[271]! } - public var Passport_DeleteDocument: String { return self._s[272]! } - public var SocksProxySetup_AddProxyTitle: String { return self._s[273]! } + public var UserInfo_SendMessage: String { return self._s[271]! } + public var TwoStepAuth_PasswordSet: String { return self._s[272]! } + public var Passport_DeleteDocument: String { return self._s[273]! } + public var SocksProxySetup_AddProxyTitle: String { return self._s[274]! } public func PUSH_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[274]!, self._r[274]!, [_1]) + return formatWithArgumentRanges(self._s[275]!, self._r[275]!, [_1]) } - public var GroupRemoved_Remove: String { return self._s[275]! } - public var Passport_FieldIdentity: String { return self._s[276]! } - public var Group_Setup_TypePrivateHelp: String { return self._s[277]! } - public var Conversation_Processing: String { return self._s[280]! } - public var Wallet_Settings_BackupWallet: String { return self._s[282]! } - public var ChatSettings_AutoPlayAnimations: String { return self._s[283]! } - public var AuthSessions_LogOutApplicationsHelp: String { return self._s[286]! } - public var Month_GenFebruary: String { return self._s[287]! } - public var Wallet_Send_NetworkErrorTitle: String { return self._s[288]! } + public var GroupRemoved_Remove: String { return self._s[276]! } + public var Passport_FieldIdentity: String { return self._s[277]! } + public var Group_Setup_TypePrivateHelp: String { return self._s[278]! } + public var Conversation_Processing: String { return self._s[281]! } + public var Wallet_Settings_BackupWallet: String { return self._s[283]! } + public var ChatSettings_AutoPlayAnimations: String { return self._s[284]! } + public var AuthSessions_LogOutApplicationsHelp: String { return self._s[287]! } + public var Month_GenFebruary: String { return self._s[288]! } + public var Wallet_Send_NetworkErrorTitle: String { return self._s[289]! } public func Login_InvalidPhoneEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[290]!, self._r[290]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[291]!, self._r[291]!, [_1, _2, _3, _4, _5]) } - public var Passport_Identity_TypeIdentityCard: String { return self._s[291]! } - public var Wallet_Month_ShortJune: String { return self._s[293]! } - public var AutoDownloadSettings_DataUsageMedium: String { return self._s[294]! } - public var GroupInfo_AddParticipant: String { return self._s[295]! } - public var KeyCommand_SendMessage: String { return self._s[296]! } - public var VoiceOver_Chat_YourContact: String { return self._s[298]! } - public var Map_LiveLocationShowAll: String { return self._s[299]! } - public var WallpaperSearch_ColorOrange: String { return self._s[301]! } - public var Appearance_AppIconDefaultX: String { return self._s[302]! } - public var Checkout_Receipt_Title: String { return self._s[303]! } - public var Group_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[304]! } - public var WallpaperPreview_PreviewTopText: String { return self._s[305]! } - public var Message_Contact: String { return self._s[306]! } - public var Call_StatusIncoming: String { return self._s[307]! } - public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[308]! } + public var Passport_Identity_TypeIdentityCard: String { return self._s[292]! } + public var Wallet_Month_ShortJune: String { return self._s[294]! } + public var AutoDownloadSettings_DataUsageMedium: String { return self._s[295]! } + public var GroupInfo_AddParticipant: String { return self._s[296]! } + public var KeyCommand_SendMessage: String { return self._s[297]! } + public var VoiceOver_Chat_YourContact: String { return self._s[299]! } + public var Map_LiveLocationShowAll: String { return self._s[300]! } + public var WallpaperSearch_ColorOrange: String { return self._s[302]! } + public var Appearance_AppIconDefaultX: String { return self._s[303]! } + public var Checkout_Receipt_Title: String { return self._s[304]! } + public var Group_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[305]! } + public var WallpaperPreview_PreviewTopText: String { return self._s[306]! } + public var Message_Contact: String { return self._s[307]! } + public var Call_StatusIncoming: String { return self._s[308]! } + public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[309]! } public func Channel_AdminLog_MessageKickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[309]!, self._r[309]!, [_1]) + return formatWithArgumentRanges(self._s[310]!, self._r[310]!, [_1]) } public func PUSH_ENCRYPTED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[311]!, self._r[311]!, [_1]) + return formatWithArgumentRanges(self._s[312]!, self._r[312]!, [_1]) } - public var VoiceOver_Media_PlaybackRate: String { return self._s[312]! } - public var Passport_FieldIdentityDetailsHelp: String { return self._s[313]! } - public var Conversation_ViewChannel: String { return self._s[314]! } + public var VoiceOver_Media_PlaybackRate: String { return self._s[313]! } + public var Passport_FieldIdentityDetailsHelp: String { return self._s[314]! } + public var Conversation_ViewChannel: String { return self._s[315]! } public func Time_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[315]!, self._r[315]!, [_0]) + return formatWithArgumentRanges(self._s[316]!, self._r[316]!, [_0]) } - public var Passport_Language_nl: String { return self._s[317]! } - public var Camera_Retake: String { return self._s[318]! } + public var Passport_Language_nl: String { return self._s[318]! } + public var Camera_Retake: String { return self._s[319]! } public func UserInfo_BlockActionTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[319]!, self._r[319]!, [_0]) + return formatWithArgumentRanges(self._s[320]!, self._r[320]!, [_0]) } - public var AuthSessions_LogOutApplications: String { return self._s[320]! } - public var ApplyLanguage_ApplySuccess: String { return self._s[321]! } - public var Tour_Title6: String { return self._s[322]! } - public var Map_ChooseAPlace: String { return self._s[323]! } - public var CallSettings_Never: String { return self._s[325]! } + public var AuthSessions_LogOutApplications: String { return self._s[321]! } + public var ApplyLanguage_ApplySuccess: String { return self._s[322]! } + public var Tour_Title6: String { return self._s[323]! } + public var Map_ChooseAPlace: String { return self._s[324]! } + public var CallSettings_Never: String { return self._s[326]! } public func Notification_ChangedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[326]!, self._r[326]!, [_0]) + return formatWithArgumentRanges(self._s[327]!, self._r[327]!, [_0]) } - public var ChannelRemoved_RemoveInfo: String { return self._s[327]! } + public var ChannelRemoved_RemoveInfo: String { return self._s[328]! } public func AutoDownloadSettings_PreloadVideoInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[328]!, self._r[328]!, [_0]) + return formatWithArgumentRanges(self._s[329]!, self._r[329]!, [_0]) } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsExceptions: String { return self._s[329]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsExceptions: String { return self._s[330]! } public func Conversation_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[330]!, self._r[330]!, [_0]) + return formatWithArgumentRanges(self._s[331]!, self._r[331]!, [_0]) } - public var GroupInfo_InviteLink_Title: String { return self._s[331]! } + public var GroupInfo_InviteLink_Title: String { return self._s[332]! } public func Channel_AdminLog_MessageUnkickedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[332]!, self._r[332]!, [_1, _2]) + return formatWithArgumentRanges(self._s[333]!, self._r[333]!, [_1, _2]) } - public var KeyCommand_ScrollUp: String { return self._s[333]! } - public var ContactInfo_URLLabelHomepage: String { return self._s[334]! } - public var Channel_OwnershipTransfer_ChangeOwner: String { return self._s[335]! } + public var KeyCommand_ScrollUp: String { return self._s[334]! } + public var ContactInfo_URLLabelHomepage: String { return self._s[335]! } + public var Channel_OwnershipTransfer_ChangeOwner: String { return self._s[336]! } public func Channel_AdminLog_DisabledSlowmode(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[336]!, self._r[336]!, [_0]) - } - public func Conversation_EncryptedPlaceholderTitleOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[337]!, self._r[337]!, [_0]) } - public var CallFeedback_ReasonDistortedSpeech: String { return self._s[338]! } - public var Watch_LastSeen_WithinAWeek: String { return self._s[339]! } - public var ContactList_Context_SendMessage: String { return self._s[341]! } - public var Weekday_Tuesday: String { return self._s[342]! } - public var Wallet_Created_Title: String { return self._s[344]! } - public var ScheduledMessages_Delete: String { return self._s[345]! } - public var UserInfo_StartSecretChat: String { return self._s[346]! } - public var Passport_Identity_FilesTitle: String { return self._s[347]! } - public var Permissions_NotificationsAllow_v0: String { return self._s[348]! } - public var DialogList_DeleteConversationConfirmation: String { return self._s[350]! } - public var ChatList_UndoArchiveRevealedTitle: String { return self._s[351]! } - public var AuthSessions_Sessions: String { return self._s[352]! } + public var TwoFactorSetup_Done_Title: String { return self._s[338]! } + public func Conversation_EncryptedPlaceholderTitleOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[339]!, self._r[339]!, [_0]) + } + public var CallFeedback_ReasonDistortedSpeech: String { return self._s[340]! } + public var Watch_LastSeen_WithinAWeek: String { return self._s[341]! } + public var ContactList_Context_SendMessage: String { return self._s[343]! } + public var Weekday_Tuesday: String { return self._s[344]! } + public var Wallet_Created_Title: String { return self._s[346]! } + public var ScheduledMessages_Delete: String { return self._s[347]! } + public var UserInfo_StartSecretChat: String { return self._s[348]! } + public var Passport_Identity_FilesTitle: String { return self._s[349]! } + public var Permissions_NotificationsAllow_v0: String { return self._s[350]! } + public var DialogList_DeleteConversationConfirmation: String { return self._s[352]! } + public var ChatList_UndoArchiveRevealedTitle: String { return self._s[353]! } + public var AuthSessions_Sessions: String { return self._s[354]! } public func Settings_KeepPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[354]!, self._r[354]!, [_0]) + return formatWithArgumentRanges(self._s[356]!, self._r[356]!, [_0]) } - public var TwoStepAuth_RecoveryEmailChangeDescription: String { return self._s[355]! } - public var Call_StatusWaiting: String { return self._s[356]! } - public var CreateGroup_SoftUserLimitAlert: String { return self._s[357]! } - public var FastTwoStepSetup_HintHelp: String { return self._s[358]! } - public var WallpaperPreview_CustomColorBottomText: String { return self._s[359]! } - public var EditTheme_Expand_Preview_OutgoingText: String { return self._s[360]! } - public var LogoutOptions_AddAccountText: String { return self._s[361]! } - public var PasscodeSettings_6DigitCode: String { return self._s[362]! } - public var Settings_LogoutConfirmationText: String { return self._s[363]! } - public var Passport_Identity_TypePassport: String { return self._s[365]! } + public var TwoStepAuth_RecoveryEmailChangeDescription: String { return self._s[357]! } + public var Call_StatusWaiting: String { return self._s[358]! } + public var CreateGroup_SoftUserLimitAlert: String { return self._s[359]! } + public var FastTwoStepSetup_HintHelp: String { return self._s[360]! } + public var WallpaperPreview_CustomColorBottomText: String { return self._s[361]! } + public var EditTheme_Expand_Preview_OutgoingText: String { return self._s[362]! } + public var LogoutOptions_AddAccountText: String { return self._s[363]! } + public var PasscodeSettings_6DigitCode: String { return self._s[364]! } + public var Settings_LogoutConfirmationText: String { return self._s[365]! } + public var Passport_Identity_TypePassport: String { return self._s[367]! } public func PUSH_MESSAGE_VIDEOS(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[368]!, self._r[368]!, [_1, _2]) + return formatWithArgumentRanges(self._s[370]!, self._r[370]!, [_1, _2]) } - public var SocksProxySetup_SaveProxy: String { return self._s[369]! } - public var AccessDenied_SaveMedia: String { return self._s[370]! } - public var Checkout_ErrorInvoiceAlreadyPaid: String { return self._s[372]! } - public var Settings_Title: String { return self._s[374]! } - public var VoiceOver_Chat_RecordModeVideoMessageInfo: String { return self._s[375]! } - public var Contacts_InviteSearchLabel: String { return self._s[377]! } - public var ConvertToSupergroup_Title: String { return self._s[378]! } + public var SocksProxySetup_SaveProxy: String { return self._s[371]! } + public var AccessDenied_SaveMedia: String { return self._s[372]! } + public var Checkout_ErrorInvoiceAlreadyPaid: String { return self._s[374]! } + public var Settings_Title: String { return self._s[376]! } + public var VoiceOver_Chat_RecordModeVideoMessageInfo: String { return self._s[377]! } + public var Contacts_InviteSearchLabel: String { return self._s[379]! } + public var ConvertToSupergroup_Title: String { return self._s[380]! } public func Channel_AdminLog_CaptionEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[379]!, self._r[379]!, [_0]) + return formatWithArgumentRanges(self._s[381]!, self._r[381]!, [_0]) } - public var InfoPlist_NSSiriUsageDescription: String { return self._s[380]! } + public var TwoFactorSetup_Hint_Text: String { return self._s[382]! } + public var InfoPlist_NSSiriUsageDescription: String { return self._s[383]! } public func PUSH_MESSAGE_CHANNEL_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[381]!, self._r[381]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[384]!, self._r[384]!, [_1, _2, _3]) } - public var ChatSettings_AutomaticPhotoDownload: String { return self._s[382]! } - public var UserInfo_BotHelp: String { return self._s[383]! } - public var PrivacySettings_LastSeenEverybody: String { return self._s[384]! } - public var Checkout_Name: String { return self._s[385]! } - public var AutoDownloadSettings_DataUsage: String { return self._s[386]! } - public var Channel_BanUser_BlockFor: String { return self._s[387]! } - public var Checkout_ShippingAddress: String { return self._s[388]! } - public var AutoDownloadSettings_MaxVideoSize: String { return self._s[389]! } - public var Privacy_PaymentsClearInfoDoneHelp: String { return self._s[390]! } - public var Privacy_Forwards: String { return self._s[391]! } - public var Channel_BanUser_PermissionSendPolls: String { return self._s[392]! } - public var Appearance_ThemeCarouselNewNight: String { return self._s[393]! } + public var ChatSettings_AutomaticPhotoDownload: String { return self._s[385]! } + public var UserInfo_BotHelp: String { return self._s[386]! } + public var PrivacySettings_LastSeenEverybody: String { return self._s[387]! } + public var Checkout_Name: String { return self._s[388]! } + public var AutoDownloadSettings_DataUsage: String { return self._s[389]! } + public var Channel_BanUser_BlockFor: String { return self._s[390]! } + public var Checkout_ShippingAddress: String { return self._s[391]! } + public var AutoDownloadSettings_MaxVideoSize: String { return self._s[392]! } + public var Privacy_PaymentsClearInfoDoneHelp: String { return self._s[393]! } + public var Privacy_Forwards: String { return self._s[394]! } + public var Channel_BanUser_PermissionSendPolls: String { return self._s[395]! } + public var Appearance_ThemeCarouselNewNight: String { return self._s[396]! } public func SecretVideo_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[396]!, self._r[396]!, [_0]) + return formatWithArgumentRanges(self._s[399]!, self._r[399]!, [_0]) } - public var Contacts_SortedByName: String { return self._s[397]! } - public var Group_OwnershipTransfer_Title: String { return self._s[398]! } - public var VoiceOver_Chat_OpenHint: String { return self._s[399]! } - public var Group_LeaveGroup: String { return self._s[400]! } - public var Settings_UsernameEmpty: String { return self._s[401]! } + public var Contacts_SortedByName: String { return self._s[400]! } + public var Group_OwnershipTransfer_Title: String { return self._s[401]! } + public var VoiceOver_Chat_OpenHint: String { return self._s[402]! } + public var Group_LeaveGroup: String { return self._s[403]! } + public var Settings_UsernameEmpty: String { return self._s[404]! } public func Notification_PinnedPollMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[402]!, self._r[402]!, [_0]) + return formatWithArgumentRanges(self._s[405]!, self._r[405]!, [_0]) } public func TwoStepAuth_ConfirmEmailDescription(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[403]!, self._r[403]!, [_1]) + return formatWithArgumentRanges(self._s[406]!, self._r[406]!, [_1]) } public func Channel_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[404]!, self._r[404]!, [_1, _2]) + return formatWithArgumentRanges(self._s[407]!, self._r[407]!, [_1, _2]) } - public var Message_ImageExpired: String { return self._s[405]! } - public var TwoStepAuth_RecoveryFailed: String { return self._s[407]! } - public var EditTheme_Edit_Preview_OutgoingText: String { return self._s[408]! } - public var UserInfo_AddToExisting: String { return self._s[409]! } - public var TwoStepAuth_EnabledSuccess: String { return self._s[410]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_SetColor: String { return self._s[411]! } + public var Message_ImageExpired: String { return self._s[408]! } + public var TwoStepAuth_RecoveryFailed: String { return self._s[410]! } + public var EditTheme_Edit_Preview_OutgoingText: String { return self._s[411]! } + public var UserInfo_AddToExisting: String { return self._s[412]! } + public var TwoStepAuth_EnabledSuccess: String { return self._s[413]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_SetColor: String { return self._s[414]! } public func PUSH_CHANNEL_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[412]!, self._r[412]!, [_1]) + return formatWithArgumentRanges(self._s[415]!, self._r[415]!, [_1]) } - public var Notifications_GroupNotificationsAlert: String { return self._s[413]! } - public var Passport_Language_km: String { return self._s[414]! } - public var SocksProxySetup_AdNoticeHelp: String { return self._s[416]! } - public var VoiceOver_Media_PlaybackPlay: String { return self._s[417]! } - public var Notification_CallMissedShort: String { return self._s[418]! } - public var Wallet_Info_YourBalance: String { return self._s[419]! } - public var ReportPeer_ReasonOther_Send: String { return self._s[420]! } - public var Watch_Compose_Send: String { return self._s[421]! } - public var Passport_Identity_TypeInternalPassportUploadScan: String { return self._s[424]! } - public var Conversation_HoldForVideo: String { return self._s[425]! } - public var Wallet_TransactionInfo_CommentHeader: String { return self._s[426]! } - public var CheckoutInfo_ErrorCityInvalid: String { return self._s[428]! } - public var Appearance_AutoNightThemeDisabled: String { return self._s[430]! } - public var Channel_LinkItem: String { return self._s[431]! } + public var Notifications_GroupNotificationsAlert: String { return self._s[416]! } + public var Passport_Language_km: String { return self._s[417]! } + public var SocksProxySetup_AdNoticeHelp: String { return self._s[419]! } + public var VoiceOver_Media_PlaybackPlay: String { return self._s[420]! } + public var Notification_CallMissedShort: String { return self._s[421]! } + public var Wallet_Info_YourBalance: String { return self._s[422]! } + public var ReportPeer_ReasonOther_Send: String { return self._s[423]! } + public var Watch_Compose_Send: String { return self._s[424]! } + public var Passport_Identity_TypeInternalPassportUploadScan: String { return self._s[427]! } + public var TwoFactorSetup_Email_Action: String { return self._s[428]! } + public var Conversation_HoldForVideo: String { return self._s[429]! } + public var Wallet_TransactionInfo_CommentHeader: String { return self._s[430]! } + public var CheckoutInfo_ErrorCityInvalid: String { return self._s[432]! } + public var Appearance_AutoNightThemeDisabled: String { return self._s[434]! } + public var Channel_LinkItem: String { return self._s[435]! } public func PrivacySettings_LastSeenContactsMinusPlus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[432]!, self._r[432]!, [_0, _1]) + return formatWithArgumentRanges(self._s[436]!, self._r[436]!, [_0, _1]) } public func Passport_Identity_NativeNameTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[435]!, self._r[435]!, [_0]) + return formatWithArgumentRanges(self._s[439]!, self._r[439]!, [_0]) } - public var VoiceOver_Recording_StopAndPreview: String { return self._s[436]! } - public var Passport_Language_dv: String { return self._s[437]! } - public var Undo_LeftChannel: String { return self._s[438]! } - public var Notifications_ExceptionsMuted: String { return self._s[439]! } - public var ChatList_UnhideAction: String { return self._s[440]! } - public var Conversation_ContextMenuShare: String { return self._s[441]! } - public var Conversation_ContextMenuStickerPackInfo: String { return self._s[442]! } - public var ShareFileTip_Title: String { return self._s[443]! } - public var NotificationsSound_Chord: String { return self._s[444]! } - public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[445]! } + public var VoiceOver_Recording_StopAndPreview: String { return self._s[440]! } + public var Passport_Language_dv: String { return self._s[441]! } + public var Undo_LeftChannel: String { return self._s[442]! } + public var Notifications_ExceptionsMuted: String { return self._s[443]! } + public var ChatList_UnhideAction: String { return self._s[444]! } + public var Conversation_ContextMenuShare: String { return self._s[445]! } + public var Conversation_ContextMenuStickerPackInfo: String { return self._s[446]! } + public var ShareFileTip_Title: String { return self._s[447]! } + public var NotificationsSound_Chord: String { return self._s[448]! } + public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[449]! } public func PUSH_CHAT_RETURNED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[446]!, self._r[446]!, [_1, _2]) + return formatWithArgumentRanges(self._s[450]!, self._r[450]!, [_1, _2]) } - public var Passport_Address_EditTemporaryRegistration: String { return self._s[447]! } + public var Passport_Address_EditTemporaryRegistration: String { return self._s[451]! } public func Notification_Joined(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[448]!, self._r[448]!, [_0]) + return formatWithArgumentRanges(self._s[452]!, self._r[452]!, [_0]) } public func Wallet_Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[449]!, self._r[449]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[453]!, self._r[453]!, [_1, _2, _3]) } - public var Wallpaper_ErrorNotFound: String { return self._s[450]! } - public var Notification_CallOutgoingShort: String { return self._s[452]! } - public var Wallet_WordImport_IncorrectText: String { return self._s[453]! } + public var Wallpaper_ErrorNotFound: String { return self._s[454]! } + public var Notification_CallOutgoingShort: String { return self._s[456]! } + public var Wallet_WordImport_IncorrectText: String { return self._s[457]! } public func Watch_Time_ShortFullAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[454]!, self._r[454]!, [_1, _2]) + return formatWithArgumentRanges(self._s[458]!, self._r[458]!, [_1, _2]) } - public var Passport_Address_TypeUtilityBill: String { return self._s[455]! } - public var Privacy_Forwards_LinkIfAllowed: String { return self._s[456]! } - public var ReportPeer_Report: String { return self._s[457]! } - public var SettingsSearch_Synonyms_Proxy_Title: String { return self._s[458]! } - public var GroupInfo_DeactivatedStatus: String { return self._s[459]! } + public var Passport_Address_TypeUtilityBill: String { return self._s[459]! } + public var Privacy_Forwards_LinkIfAllowed: String { return self._s[460]! } + public var ReportPeer_Report: String { return self._s[461]! } + public var SettingsSearch_Synonyms_Proxy_Title: String { return self._s[462]! } + public var GroupInfo_DeactivatedStatus: String { return self._s[463]! } public func VoiceOver_Chat_MusicTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[460]!, self._r[460]!, [_1, _2]) + return formatWithArgumentRanges(self._s[464]!, self._r[464]!, [_1, _2]) } - public var StickerPack_Send: String { return self._s[461]! } - public var Login_CodeSentInternal: String { return self._s[462]! } - public var Wallet_Month_GenJanuary: String { return self._s[463]! } - public var GroupInfo_InviteLink_LinkSection: String { return self._s[464]! } + public var StickerPack_Send: String { return self._s[465]! } + public var Login_CodeSentInternal: String { return self._s[466]! } + public var Wallet_Month_GenJanuary: String { return self._s[467]! } + public var GroupInfo_InviteLink_LinkSection: String { return self._s[468]! } public func Channel_AdminLog_MessageDeleted(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[465]!, self._r[465]!, [_0]) + return formatWithArgumentRanges(self._s[469]!, self._r[469]!, [_0]) } public func Conversation_EncryptionWaiting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[467]!, self._r[467]!, [_0]) + return formatWithArgumentRanges(self._s[471]!, self._r[471]!, [_0]) } - public var Channel_BanUser_PermissionSendStickersAndGifs: String { return self._s[468]! } + public var Channel_BanUser_PermissionSendStickersAndGifs: String { return self._s[472]! } public func PUSH_PINNED_GAME(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[469]!, self._r[469]!, [_1]) + return formatWithArgumentRanges(self._s[473]!, self._r[473]!, [_1]) } - public var ReportPeer_ReasonViolence: String { return self._s[471]! } - public var Map_Locating: String { return self._s[472]! } + public var ReportPeer_ReasonViolence: String { return self._s[475]! } + public var Map_Locating: String { return self._s[476]! } public func VoiceOver_Chat_VideoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[473]!, self._r[473]!, [_0]) + return formatWithArgumentRanges(self._s[477]!, self._r[477]!, [_0]) } public func PUSH_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[474]!, self._r[474]!, [_1]) + return formatWithArgumentRanges(self._s[478]!, self._r[478]!, [_1]) } - public var AutoDownloadSettings_GroupChats: String { return self._s[476]! } - public var CheckoutInfo_SaveInfo: String { return self._s[477]! } - public var SharedMedia_EmptyLinksText: String { return self._s[479]! } - public var Passport_Address_CityPlaceholder: String { return self._s[480]! } - public var CheckoutInfo_ErrorStateInvalid: String { return self._s[481]! } - public var Privacy_ProfilePhoto_CustomHelp: String { return self._s[482]! } - public var Channel_AdminLog_CanAddAdmins: String { return self._s[484]! } + public var AutoDownloadSettings_GroupChats: String { return self._s[480]! } + public var CheckoutInfo_SaveInfo: String { return self._s[481]! } + public var SharedMedia_EmptyLinksText: String { return self._s[483]! } + public var Passport_Address_CityPlaceholder: String { return self._s[484]! } + public var CheckoutInfo_ErrorStateInvalid: String { return self._s[485]! } + public var Privacy_ProfilePhoto_CustomHelp: String { return self._s[486]! } + public var Channel_AdminLog_CanAddAdmins: String { return self._s[488]! } public func PUSH_CHANNEL_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[485]!, self._r[485]!, [_1]) + return formatWithArgumentRanges(self._s[489]!, self._r[489]!, [_1]) } public func Time_MonthOfYear_m8(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[486]!, self._r[486]!, [_0]) + return formatWithArgumentRanges(self._s[490]!, self._r[490]!, [_0]) } - public var InfoPlist_NSLocationWhenInUseUsageDescription: String { return self._s[487]! } - public var GroupInfo_InviteLink_RevokeAlert_Success: String { return self._s[488]! } - public var ChangePhoneNumberCode_Code: String { return self._s[489]! } - public var Appearance_CreateTheme: String { return self._s[490]! } + public var InfoPlist_NSLocationWhenInUseUsageDescription: String { return self._s[491]! } + public var GroupInfo_InviteLink_RevokeAlert_Success: String { return self._s[492]! } + public var ChangePhoneNumberCode_Code: String { return self._s[493]! } + public var Appearance_CreateTheme: String { return self._s[494]! } public func UserInfo_NotificationsDefaultSound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[491]!, self._r[491]!, [_0]) + return formatWithArgumentRanges(self._s[495]!, self._r[495]!, [_0]) } - public var TwoStepAuth_SetupEmail: String { return self._s[492]! } - public var HashtagSearch_AllChats: String { return self._s[493]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingCellular: String { return self._s[495]! } + public var TwoStepAuth_SetupEmail: String { return self._s[496]! } + public var HashtagSearch_AllChats: String { return self._s[497]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingCellular: String { return self._s[499]! } public func ChatList_DeleteForEveryone(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[496]!, self._r[496]!, [_0]) + return formatWithArgumentRanges(self._s[500]!, self._r[500]!, [_0]) } - public var PhotoEditor_QualityHigh: String { return self._s[498]! } + public var PhotoEditor_QualityHigh: String { return self._s[502]! } public func Passport_Phone_UseTelegramNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[499]!, self._r[499]!, [_0]) + return formatWithArgumentRanges(self._s[503]!, self._r[503]!, [_0]) } - public var ApplyLanguage_ApplyLanguageAction: String { return self._s[500]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsPreview: String { return self._s[501]! } - public var Message_LiveLocation: String { return self._s[502]! } - public var Cache_LowDiskSpaceText: String { return self._s[503]! } - public var Wallet_Receive_ShareAddress: String { return self._s[504]! } - public var EditTheme_ErrorLinkTaken: String { return self._s[505]! } - public var Conversation_SendMessage: String { return self._s[506]! } - public var AuthSessions_EmptyTitle: String { return self._s[507]! } - public var Privacy_PhoneNumber: String { return self._s[508]! } - public var PeopleNearby_CreateGroup: String { return self._s[509]! } - public var CallSettings_UseLessData: String { return self._s[510]! } - public var NetworkUsageSettings_MediaDocumentDataSection: String { return self._s[511]! } - public var Stickers_AddToFavorites: String { return self._s[512]! } - public var Wallet_WordImport_Title: String { return self._s[513]! } - public var PhotoEditor_QualityLow: String { return self._s[514]! } - public var Watch_UserInfo_Unblock: String { return self._s[515]! } - public var Settings_Logout: String { return self._s[516]! } + public var ApplyLanguage_ApplyLanguageAction: String { return self._s[504]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsPreview: String { return self._s[505]! } + public var Message_LiveLocation: String { return self._s[506]! } + public var Cache_LowDiskSpaceText: String { return self._s[507]! } + public var Wallet_Receive_ShareAddress: String { return self._s[508]! } + public var EditTheme_ErrorLinkTaken: String { return self._s[509]! } + public var Conversation_SendMessage: String { return self._s[510]! } + public var AuthSessions_EmptyTitle: String { return self._s[511]! } + public var Privacy_PhoneNumber: String { return self._s[512]! } + public var PeopleNearby_CreateGroup: String { return self._s[513]! } + public var CallSettings_UseLessData: String { return self._s[514]! } + public var NetworkUsageSettings_MediaDocumentDataSection: String { return self._s[515]! } + public var Stickers_AddToFavorites: String { return self._s[516]! } + public var Wallet_WordImport_Title: String { return self._s[517]! } + public var PhotoEditor_QualityLow: String { return self._s[518]! } + public var Watch_UserInfo_Unblock: String { return self._s[519]! } + public var Settings_Logout: String { return self._s[520]! } public func PUSH_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[517]!, self._r[517]!, [_1]) + return formatWithArgumentRanges(self._s[521]!, self._r[521]!, [_1]) } - public var ContactInfo_PhoneLabelWork: String { return self._s[518]! } - public var ChannelInfo_Stats: String { return self._s[519]! } - public var TextFormat_Link: String { return self._s[520]! } + public var ContactInfo_PhoneLabelWork: String { return self._s[522]! } + public var ChannelInfo_Stats: String { return self._s[523]! } + public var TextFormat_Link: String { return self._s[524]! } public func Date_ChatDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[521]!, self._r[521]!, [_1, _2]) + return formatWithArgumentRanges(self._s[525]!, self._r[525]!, [_1, _2]) } - public var Wallet_TransactionInfo_Title: String { return self._s[522]! } + public var Wallet_TransactionInfo_Title: String { return self._s[526]! } public func Message_ForwardedMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[523]!, self._r[523]!, [_0]) + return formatWithArgumentRanges(self._s[527]!, self._r[527]!, [_0]) } - public var Watch_Notification_Joined: String { return self._s[524]! } - public var Group_Setup_TypePublicHelp: String { return self._s[525]! } - public var Passport_Scans_UploadNew: String { return self._s[526]! } - public var Checkout_LiabilityAlertTitle: String { return self._s[527]! } - public var DialogList_Title: String { return self._s[530]! } - public var NotificationSettings_ContactJoined: String { return self._s[531]! } - public var GroupInfo_LabelAdmin: String { return self._s[532]! } - public var KeyCommand_ChatInfo: String { return self._s[533]! } - public var Conversation_EditingCaptionPanelTitle: String { return self._s[534]! } - public var Call_ReportIncludeLog: String { return self._s[535]! } + public var Watch_Notification_Joined: String { return self._s[528]! } + public var Group_Setup_TypePublicHelp: String { return self._s[529]! } + public var Passport_Scans_UploadNew: String { return self._s[530]! } + public var Checkout_LiabilityAlertTitle: String { return self._s[531]! } + public var DialogList_Title: String { return self._s[534]! } + public var NotificationSettings_ContactJoined: String { return self._s[535]! } + public var GroupInfo_LabelAdmin: String { return self._s[536]! } + public var KeyCommand_ChatInfo: String { return self._s[537]! } + public var Conversation_EditingCaptionPanelTitle: String { return self._s[538]! } + public var Call_ReportIncludeLog: String { return self._s[539]! } public func Notifications_ExceptionsChangeSound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[538]!, self._r[538]!, [_0]) + return formatWithArgumentRanges(self._s[542]!, self._r[542]!, [_0]) } - public var LocalGroup_IrrelevantWarning: String { return self._s[539]! } - public var ChatAdmins_AllMembersAreAdmins: String { return self._s[540]! } - public var Conversation_DefaultRestrictedInline: String { return self._s[541]! } - public var Message_Sticker: String { return self._s[542]! } - public var LastSeen_JustNow: String { return self._s[544]! } - public var Passport_Email_EmailPlaceholder: String { return self._s[546]! } - public var SettingsSearch_Synonyms_AppLanguage: String { return self._s[547]! } - public var Channel_AdminLogFilter_EventsEditedMessages: String { return self._s[548]! } - public var Channel_EditAdmin_PermissionsHeader: String { return self._s[549]! } - public var TwoStepAuth_Email: String { return self._s[550]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsSound: String { return self._s[551]! } - public var PhotoEditor_BlurToolOff: String { return self._s[552]! } - public var Message_PinnedStickerMessage: String { return self._s[553]! } - public var ContactInfo_PhoneLabelPager: String { return self._s[554]! } - public var SettingsSearch_Synonyms_Appearance_TextSize: String { return self._s[555]! } - public var Passport_DiscardMessageTitle: String { return self._s[556]! } - public var Privacy_PaymentsTitle: String { return self._s[557]! } - public var EditTheme_Edit_Preview_IncomingReplyName: String { return self._s[558]! } - public var Channel_DiscussionGroup_Header: String { return self._s[560]! } - public var VoiceOver_Chat_OptionSelected: String { return self._s[561]! } - public var Appearance_ColorTheme: String { return self._s[562]! } - public var UserInfo_ShareContact: String { return self._s[563]! } - public var Passport_Address_TypePassportRegistration: String { return self._s[564]! } - public var Common_More: String { return self._s[565]! } - public var Watch_Message_Call: String { return self._s[566]! } - public var Profile_EncryptionKey: String { return self._s[569]! } - public var Privacy_TopPeers: String { return self._s[570]! } - public var Conversation_StopPollConfirmation: String { return self._s[571]! } - public var Wallet_Words_NotDoneText: String { return self._s[573]! } - public var Privacy_TopPeersWarning: String { return self._s[575]! } - public var SettingsSearch_Synonyms_Data_DownloadInBackground: String { return self._s[576]! } - public var SettingsSearch_Synonyms_Data_Storage_KeepMedia: String { return self._s[577]! } - public var Wallet_RestoreFailed_EnterWords: String { return self._s[580]! } - public var DialogList_SearchSectionMessages: String { return self._s[581]! } - public var Notifications_ChannelNotifications: String { return self._s[582]! } - public var CheckoutInfo_ShippingInfoAddress1Placeholder: String { return self._s[583]! } - public var Passport_Language_sk: String { return self._s[584]! } - public var Notification_MessageLifetime1h: String { return self._s[585]! } - public var Wallpaper_ResetWallpapersInfo: String { return self._s[586]! } - public var Call_ReportSkip: String { return self._s[588]! } - public var Cache_ServiceFiles: String { return self._s[589]! } - public var Group_ErrorAddTooMuchAdmins: String { return self._s[590]! } - public var VoiceOver_Chat_YourFile: String { return self._s[591]! } - public var Map_Hybrid: String { return self._s[592]! } - public var Contacts_SearchUsersAndGroupsLabel: String { return self._s[594]! } - public var ChatSettings_AutoDownloadVideos: String { return self._s[596]! } - public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[597]! } - public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[598]! } - public var SocksProxySetup_ProxyTelegram: String { return self._s[601]! } + public var LocalGroup_IrrelevantWarning: String { return self._s[543]! } + public var ChatAdmins_AllMembersAreAdmins: String { return self._s[544]! } + public var Conversation_DefaultRestrictedInline: String { return self._s[545]! } + public var Message_Sticker: String { return self._s[546]! } + public var LastSeen_JustNow: String { return self._s[548]! } + public var Passport_Email_EmailPlaceholder: String { return self._s[550]! } + public var SettingsSearch_Synonyms_AppLanguage: String { return self._s[551]! } + public var Channel_AdminLogFilter_EventsEditedMessages: String { return self._s[552]! } + public var Channel_EditAdmin_PermissionsHeader: String { return self._s[553]! } + public var TwoStepAuth_Email: String { return self._s[554]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsSound: String { return self._s[555]! } + public var PhotoEditor_BlurToolOff: String { return self._s[556]! } + public var Message_PinnedStickerMessage: String { return self._s[557]! } + public var ContactInfo_PhoneLabelPager: String { return self._s[558]! } + public var SettingsSearch_Synonyms_Appearance_TextSize: String { return self._s[559]! } + public var Passport_DiscardMessageTitle: String { return self._s[560]! } + public var Privacy_PaymentsTitle: String { return self._s[561]! } + public var EditTheme_Edit_Preview_IncomingReplyName: String { return self._s[562]! } + public var Channel_DiscussionGroup_Header: String { return self._s[564]! } + public var VoiceOver_Chat_OptionSelected: String { return self._s[565]! } + public var Appearance_ColorTheme: String { return self._s[566]! } + public var UserInfo_ShareContact: String { return self._s[567]! } + public var Passport_Address_TypePassportRegistration: String { return self._s[568]! } + public var Common_More: String { return self._s[569]! } + public var Watch_Message_Call: String { return self._s[570]! } + public var Profile_EncryptionKey: String { return self._s[573]! } + public var Privacy_TopPeers: String { return self._s[574]! } + public var Conversation_StopPollConfirmation: String { return self._s[575]! } + public var Wallet_Words_NotDoneText: String { return self._s[577]! } + public var Privacy_TopPeersWarning: String { return self._s[579]! } + public var SettingsSearch_Synonyms_Data_DownloadInBackground: String { return self._s[580]! } + public var SettingsSearch_Synonyms_Data_Storage_KeepMedia: String { return self._s[581]! } + public var Wallet_RestoreFailed_EnterWords: String { return self._s[584]! } + public var DialogList_SearchSectionMessages: String { return self._s[585]! } + public var Notifications_ChannelNotifications: String { return self._s[586]! } + public var CheckoutInfo_ShippingInfoAddress1Placeholder: String { return self._s[587]! } + public var Passport_Language_sk: String { return self._s[588]! } + public var Notification_MessageLifetime1h: String { return self._s[589]! } + public var Wallpaper_ResetWallpapersInfo: String { return self._s[590]! } + public var Call_ReportSkip: String { return self._s[592]! } + public var Cache_ServiceFiles: String { return self._s[593]! } + public var Group_ErrorAddTooMuchAdmins: String { return self._s[594]! } + public var VoiceOver_Chat_YourFile: String { return self._s[595]! } + public var Map_Hybrid: String { return self._s[596]! } + public var Contacts_SearchUsersAndGroupsLabel: String { return self._s[598]! } + public var ChatSettings_AutoDownloadVideos: String { return self._s[600]! } + public var Channel_BanUser_PermissionEmbedLinks: String { return self._s[601]! } + public var InfoPlist_NSLocationAlwaysAndWhenInUseUsageDescription: String { return self._s[602]! } + public var SocksProxySetup_ProxyTelegram: String { return self._s[605]! } public func PUSH_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[602]!, self._r[602]!, [_1]) + return formatWithArgumentRanges(self._s[606]!, self._r[606]!, [_1]) } - public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[604]! } - public var ScheduledMessages_ScheduledToday: String { return self._s[605]! } + public var Channel_Username_CreatePrivateLinkHelp: String { return self._s[608]! } + public var ScheduledMessages_ScheduledToday: String { return self._s[609]! } public func PUSH_CHAT_TITLE_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[606]!, self._r[606]!, [_1, _2]) + return formatWithArgumentRanges(self._s[610]!, self._r[610]!, [_1, _2]) } - public var Conversation_LiveLocationYou: String { return self._s[607]! } - public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[608]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[609]! } - public var UserInfo_ShareBot: String { return self._s[612]! } + public var Conversation_LiveLocationYou: String { return self._s[611]! } + public var SettingsSearch_Synonyms_Privacy_Calls: String { return self._s[612]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview: String { return self._s[613]! } + public var UserInfo_ShareBot: String { return self._s[616]! } public func PUSH_AUTH_REGION(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[613]!, self._r[613]!, [_1, _2]) + return formatWithArgumentRanges(self._s[617]!, self._r[617]!, [_1, _2]) } - public var PhotoEditor_ShadowsTint: String { return self._s[614]! } - public var Message_Audio: String { return self._s[615]! } - public var Passport_Language_lt: String { return self._s[616]! } + public var Conversation_ClearCache: String { return self._s[618]! } + public var PhotoEditor_ShadowsTint: String { return self._s[619]! } + public var Message_Audio: String { return self._s[620]! } + public var Passport_Language_lt: String { return self._s[621]! } public func Message_PinnedTextMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[617]!, self._r[617]!, [_0]) + return formatWithArgumentRanges(self._s[622]!, self._r[622]!, [_0]) } - public var Permissions_SiriText_v0: String { return self._s[618]! } - public var Conversation_FileICloudDrive: String { return self._s[619]! } - public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[620]! } - public var Notifications_Badge_IncludeMutedChats: String { return self._s[621]! } + public var Permissions_SiriText_v0: String { return self._s[623]! } + public var Conversation_FileICloudDrive: String { return self._s[624]! } + public var ChatList_DeleteForEveryoneConfirmationTitle: String { return self._s[625]! } + public var Notifications_Badge_IncludeMutedChats: String { return self._s[626]! } public func Notification_NewAuthDetected(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[622]!, self._r[622]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[627]!, self._r[627]!, [_1, _2, _3, _4, _5, _6]) } - public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[623]! } + public var DialogList_ProxyConnectionIssuesTooltip: String { return self._s[628]! } public func Time_MonthOfYear_m5(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[624]!, self._r[624]!, [_0]) + return formatWithArgumentRanges(self._s[629]!, self._r[629]!, [_0]) } - public var Channel_SignMessages: String { return self._s[625]! } + public var Channel_SignMessages: String { return self._s[630]! } public func PUSH_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[626]!, self._r[626]!, [_1]) + return formatWithArgumentRanges(self._s[631]!, self._r[631]!, [_1]) } - public var Compose_ChannelTokenListPlaceholder: String { return self._s[627]! } - public var Passport_ScanPassport: String { return self._s[628]! } - public var Watch_Suggestion_Thanks: String { return self._s[629]! } - public var BlockedUsers_AddNew: String { return self._s[630]! } + public var Compose_ChannelTokenListPlaceholder: String { return self._s[632]! } + public var Passport_ScanPassport: String { return self._s[633]! } + public var Watch_Suggestion_Thanks: String { return self._s[634]! } + public var BlockedUsers_AddNew: String { return self._s[635]! } public func PUSH_CHAT_MESSAGE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[631]!, self._r[631]!, [_1, _2]) + return formatWithArgumentRanges(self._s[636]!, self._r[636]!, [_1, _2]) } - public var Watch_Message_Invoice: String { return self._s[632]! } - public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[633]! } - public var Month_GenJuly: String { return self._s[634]! } - public var SocksProxySetup_ProxySocks5: String { return self._s[635]! } - public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[637]! } - public var Notification_ChannelInviterSelf: String { return self._s[638]! } - public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[639]! } + public var Watch_Message_Invoice: String { return self._s[637]! } + public var SettingsSearch_Synonyms_Privacy_LastSeen: String { return self._s[638]! } + public var Month_GenJuly: String { return self._s[639]! } + public var SocksProxySetup_ProxySocks5: String { return self._s[640]! } + public var Notification_Exceptions_DeleteAllConfirmation: String { return self._s[642]! } + public var Notification_ChannelInviterSelf: String { return self._s[643]! } + public var CheckoutInfo_ReceiverInfoEmail: String { return self._s[644]! } public func ApplyLanguage_ChangeLanguageUnofficialText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[640]!, self._r[640]!, [_1, _2]) + return formatWithArgumentRanges(self._s[645]!, self._r[645]!, [_1, _2]) } - public var CheckoutInfo_Title: String { return self._s[641]! } - public var Watch_Stickers_RecentPlaceholder: String { return self._s[642]! } + public var CheckoutInfo_Title: String { return self._s[646]! } + public var Watch_Stickers_RecentPlaceholder: String { return self._s[647]! } public func Map_DistanceAway(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[643]!, self._r[643]!, [_0]) + return formatWithArgumentRanges(self._s[648]!, self._r[648]!, [_0]) } - public var Passport_Identity_MainPage: String { return self._s[644]! } - public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[645]! } - public var Passport_Language_de: String { return self._s[646]! } - public var Update_Title: String { return self._s[647]! } - public var ContactInfo_PhoneLabelWorkFax: String { return self._s[648]! } - public var Channel_AdminLog_BanEmbedLinks: String { return self._s[649]! } - public var Passport_Email_UseTelegramEmailHelp: String { return self._s[650]! } - public var Notifications_ChannelNotificationsPreview: String { return self._s[651]! } - public var NotificationsSound_Telegraph: String { return self._s[652]! } - public var Watch_LastSeen_ALongTimeAgo: String { return self._s[653]! } - public var ChannelMembers_WhoCanAddMembers: String { return self._s[654]! } + public var Passport_Identity_MainPage: String { return self._s[649]! } + public var TwoStepAuth_ConfirmEmailResendCode: String { return self._s[650]! } + public var Passport_Language_de: String { return self._s[651]! } + public var Update_Title: String { return self._s[652]! } + public var ContactInfo_PhoneLabelWorkFax: String { return self._s[653]! } + public var Channel_AdminLog_BanEmbedLinks: String { return self._s[654]! } + public var Passport_Email_UseTelegramEmailHelp: String { return self._s[655]! } + public var Notifications_ChannelNotificationsPreview: String { return self._s[656]! } + public var NotificationsSound_Telegraph: String { return self._s[657]! } + public var Watch_LastSeen_ALongTimeAgo: String { return self._s[658]! } + public var ChannelMembers_WhoCanAddMembers: String { return self._s[659]! } public func AutoDownloadSettings_UpTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[655]!, self._r[655]!, [_0]) + return formatWithArgumentRanges(self._s[660]!, self._r[660]!, [_0]) } - public var Stickers_SuggestAll: String { return self._s[656]! } - public var Conversation_ForwardTitle: String { return self._s[657]! } - public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[658]! } + public var ClearCache_Description: String { return self._s[661]! } + public var Stickers_SuggestAll: String { return self._s[662]! } + public var Conversation_ForwardTitle: String { return self._s[663]! } + public var Appearance_ThemePreview_ChatList_7_Name: String { return self._s[664]! } public func Notification_JoinedChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[659]!, self._r[659]!, [_0]) + return formatWithArgumentRanges(self._s[665]!, self._r[665]!, [_0]) } - public var Calls_NewCall: String { return self._s[660]! } - public var Call_StatusEnded: String { return self._s[661]! } - public var AutoDownloadSettings_DataUsageLow: String { return self._s[662]! } - public var Settings_ProxyConnected: String { return self._s[663]! } - public var Channel_AdminLogFilter_EventsPinned: String { return self._s[664]! } - public var PhotoEditor_QualityVeryLow: String { return self._s[665]! } - public var Channel_AdminLogFilter_EventsDeletedMessages: String { return self._s[666]! } - public var Passport_PasswordPlaceholder: String { return self._s[667]! } - public var Message_PinnedInvoice: String { return self._s[668]! } - public var Passport_Identity_IssueDate: String { return self._s[669]! } - public var Passport_Language_pl: String { return self._s[670]! } + public var Calls_NewCall: String { return self._s[666]! } + public var Call_StatusEnded: String { return self._s[667]! } + public var AutoDownloadSettings_DataUsageLow: String { return self._s[668]! } + public var Settings_ProxyConnected: String { return self._s[669]! } + public var Channel_AdminLogFilter_EventsPinned: String { return self._s[670]! } + public var PhotoEditor_QualityVeryLow: String { return self._s[671]! } + public var Channel_AdminLogFilter_EventsDeletedMessages: String { return self._s[672]! } + public var Passport_PasswordPlaceholder: String { return self._s[673]! } + public var Message_PinnedInvoice: String { return self._s[674]! } + public var Passport_Identity_IssueDate: String { return self._s[675]! } + public var Passport_Language_pl: String { return self._s[676]! } public func ChannelInfo_ChannelForbidden(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[671]!, self._r[671]!, [_0]) + return formatWithArgumentRanges(self._s[677]!, self._r[677]!, [_0]) } - public var SocksProxySetup_PasteFromClipboard: String { return self._s[672]! } - public var Call_StatusConnecting: String { return self._s[673]! } + public var SocksProxySetup_PasteFromClipboard: String { return self._s[678]! } + public var Call_StatusConnecting: String { return self._s[679]! } public func Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[674]!, self._r[674]!, [_0]) + return formatWithArgumentRanges(self._s[680]!, self._r[680]!, [_0]) } - public var ChatSettings_ConnectionType_UseProxy: String { return self._s[676]! } - public var Common_Edit: String { return self._s[677]! } - public var PrivacySettings_LastSeenNobody: String { return self._s[678]! } + public var ChatSettings_ConnectionType_UseProxy: String { return self._s[682]! } + public var Common_Edit: String { return self._s[683]! } + public var PrivacySettings_LastSeenNobody: String { return self._s[684]! } public func Notification_LeftChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[679]!, self._r[679]!, [_0]) + return formatWithArgumentRanges(self._s[685]!, self._r[685]!, [_0]) } - public var GroupInfo_ChatAdmins: String { return self._s[680]! } - public var PrivateDataSettings_Title: String { return self._s[681]! } - public var Login_CancelPhoneVerificationStop: String { return self._s[682]! } - public var ChatList_Read: String { return self._s[683]! } - public var Wallet_WordImport_Text: String { return self._s[684]! } - public var Undo_ChatClearedForBothSides: String { return self._s[685]! } - public var GroupPermission_SectionTitle: String { return self._s[686]! } + public var GroupInfo_ChatAdmins: String { return self._s[686]! } + public var PrivateDataSettings_Title: String { return self._s[687]! } + public var Login_CancelPhoneVerificationStop: String { return self._s[688]! } + public var ChatList_Read: String { return self._s[689]! } + public var Wallet_WordImport_Text: String { return self._s[690]! } + public var Undo_ChatClearedForBothSides: String { return self._s[691]! } + public var GroupPermission_SectionTitle: String { return self._s[692]! } + public var TwoFactorSetup_Intro_Title: String { return self._s[694]! } public func PUSH_CHAT_LEFT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[688]!, self._r[688]!, [_1, _2]) + return formatWithArgumentRanges(self._s[695]!, self._r[695]!, [_1, _2]) } - public var Checkout_ErrorPaymentFailed: String { return self._s[689]! } - public var Update_UpdateApp: String { return self._s[690]! } - public var Group_Username_RevokeExistingUsernamesInfo: String { return self._s[691]! } - public var Settings_Appearance: String { return self._s[692]! } - public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[696]! } - public var Watch_Location_Access: String { return self._s[697]! } - public var ShareMenu_CopyShareLink: String { return self._s[699]! } - public var TwoStepAuth_SetupHintTitle: String { return self._s[700]! } - public var Conversation_Theme: String { return self._s[702]! } + public var Checkout_ErrorPaymentFailed: String { return self._s[696]! } + public var Update_UpdateApp: String { return self._s[697]! } + public var Group_Username_RevokeExistingUsernamesInfo: String { return self._s[698]! } + public var Settings_Appearance: String { return self._s[699]! } + public var SettingsSearch_Synonyms_Stickers_SuggestStickers: String { return self._s[703]! } + public var Watch_Location_Access: String { return self._s[704]! } + public var ShareMenu_CopyShareLink: String { return self._s[706]! } + public var TwoStepAuth_SetupHintTitle: String { return self._s[707]! } + public var Conversation_Theme: String { return self._s[709]! } public func DialogList_SingleRecordingVideoMessageSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[703]!, self._r[703]!, [_0]) + return formatWithArgumentRanges(self._s[710]!, self._r[710]!, [_0]) } - public var Notifications_ClassicTones: String { return self._s[704]! } - public var Weekday_ShortWednesday: String { return self._s[705]! } - public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[706]! } - public var Undo_LeftGroup: String { return self._s[709]! } - public var Wallet_RestoreFailed_Text: String { return self._s[710]! } - public var Conversation_LinkDialogCopy: String { return self._s[711]! } - public var Wallet_TransactionInfo_NoAddress: String { return self._s[713]! } - public var Wallet_Navigation_Back: String { return self._s[714]! } - public var KeyCommand_FocusOnInputField: String { return self._s[715]! } - public var Contacts_SelectAll: String { return self._s[716]! } - public var Preview_SaveToCameraRoll: String { return self._s[717]! } - public var PrivacySettings_PasscodeOff: String { return self._s[718]! } - public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[719]! } - public var Wallpaper_Title: String { return self._s[720]! } - public var Conversation_FilePhotoOrVideo: String { return self._s[721]! } - public var AccessDenied_Camera: String { return self._s[722]! } - public var Watch_Compose_CurrentLocation: String { return self._s[723]! } - public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[725]! } + public var Notifications_ClassicTones: String { return self._s[711]! } + public var Weekday_ShortWednesday: String { return self._s[712]! } + public var WallpaperPreview_SwipeColorsBottomText: String { return self._s[713]! } + public var Undo_LeftGroup: String { return self._s[716]! } + public var Wallet_RestoreFailed_Text: String { return self._s[717]! } + public var Conversation_LinkDialogCopy: String { return self._s[718]! } + public var Wallet_TransactionInfo_NoAddress: String { return self._s[720]! } + public var Wallet_Navigation_Back: String { return self._s[721]! } + public var KeyCommand_FocusOnInputField: String { return self._s[722]! } + public var Contacts_SelectAll: String { return self._s[723]! } + public var Preview_SaveToCameraRoll: String { return self._s[724]! } + public var PrivacySettings_PasscodeOff: String { return self._s[725]! } + public var Appearance_ThemePreview_ChatList_6_Name: String { return self._s[726]! } + public var Wallpaper_Title: String { return self._s[727]! } + public var Conversation_FilePhotoOrVideo: String { return self._s[728]! } + public var AccessDenied_Camera: String { return self._s[729]! } + public var Watch_Compose_CurrentLocation: String { return self._s[730]! } + public var Channel_DiscussionGroup_MakeHistoryPublicProceed: String { return self._s[732]! } public func SecretImage_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[726]!, self._r[726]!, [_0]) + return formatWithArgumentRanges(self._s[733]!, self._r[733]!, [_0]) } - public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[727]! } - public var Passport_Language_ro: String { return self._s[728]! } - public var EditTheme_UploadNewTheme: String { return self._s[729]! } - public var CheckoutInfo_SaveInfoHelp: String { return self._s[730]! } - public var Wallet_Intro_Terms: String { return self._s[731]! } + public var GroupInfo_InvitationLinkDoesNotExist: String { return self._s[734]! } + public var Passport_Language_ro: String { return self._s[735]! } + public var EditTheme_UploadNewTheme: String { return self._s[736]! } + public var CheckoutInfo_SaveInfoHelp: String { return self._s[737]! } + public var Wallet_Intro_Terms: String { return self._s[738]! } public func Notification_SecretChatMessageScreenshot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[732]!, self._r[732]!, [_0]) - } - public var Login_CancelPhoneVerification: String { return self._s[733]! } - public var State_ConnectingToProxy: String { return self._s[734]! } - public var Calls_RatingTitle: String { return self._s[735]! } - public var Generic_ErrorMoreInfo: String { return self._s[736]! } - public var Appearance_PreviewReplyText: String { return self._s[737]! } - public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[738]! } - public func Wallet_Send_Balance(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[739]!, self._r[739]!, [_0]) } - public var SharedMedia_CategoryLinks: String { return self._s[740]! } - public var Calls_Missed: String { return self._s[741]! } - public var Cache_Photos: String { return self._s[745]! } - public var GroupPermission_NoAddMembers: String { return self._s[746]! } - public var ScheduledMessages_Title: String { return self._s[747]! } - public func Channel_AdminLog_MessageUnpinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[748]!, self._r[748]!, [_0]) + public var Login_CancelPhoneVerification: String { return self._s[740]! } + public var State_ConnectingToProxy: String { return self._s[741]! } + public var Calls_RatingTitle: String { return self._s[742]! } + public var Generic_ErrorMoreInfo: String { return self._s[743]! } + public var Appearance_PreviewReplyText: String { return self._s[744]! } + public var CheckoutInfo_ShippingInfoPostcodePlaceholder: String { return self._s[745]! } + public func Wallet_Send_Balance(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[746]!, self._r[746]!, [_0]) } - public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[749]! } - public var Settings_ProxyDisabled: String { return self._s[750]! } + public var SharedMedia_CategoryLinks: String { return self._s[747]! } + public var Calls_Missed: String { return self._s[748]! } + public var Cache_Photos: String { return self._s[752]! } + public var GroupPermission_NoAddMembers: String { return self._s[753]! } + public var ScheduledMessages_Title: String { return self._s[754]! } + public func Channel_AdminLog_MessageUnpinned(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[755]!, self._r[755]!, [_0]) + } + public var Conversation_ShareBotLocationConfirmationTitle: String { return self._s[756]! } + public var Settings_ProxyDisabled: String { return self._s[757]! } public func Settings_ApplyProxyAlertCredentials(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[751]!, self._r[751]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[758]!, self._r[758]!, [_1, _2, _3, _4]) } public func Conversation_RestrictedMediaTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[752]!, self._r[752]!, [_0]) + return formatWithArgumentRanges(self._s[759]!, self._r[759]!, [_0]) } - public var ChatList_Context_RemoveFromRecents: String { return self._s[754]! } - public var Appearance_Title: String { return self._s[755]! } + public var ChatList_Context_RemoveFromRecents: String { return self._s[761]! } + public var Appearance_Title: String { return self._s[762]! } public func Time_MonthOfYear_m2(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[757]!, self._r[757]!, [_0]) + return formatWithArgumentRanges(self._s[764]!, self._r[764]!, [_0]) } - public var Conversation_WalletRequiredText: String { return self._s[758]! } - public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[759]! } - public var Channel_EditMessageErrorGeneric: String { return self._s[760]! } - public var Privacy_Calls_IntegrationHelp: String { return self._s[761]! } - public var Preview_DeletePhoto: String { return self._s[762]! } - public var Appearance_AppIconFilledX: String { return self._s[763]! } - public var PrivacySettings_PrivacyTitle: String { return self._s[764]! } + public var Conversation_WalletRequiredText: String { return self._s[765]! } + public var StickerPacksSettings_ShowStickersButtonHelp: String { return self._s[766]! } + public var Channel_EditMessageErrorGeneric: String { return self._s[767]! } + public var Privacy_Calls_IntegrationHelp: String { return self._s[768]! } + public var Preview_DeletePhoto: String { return self._s[769]! } + public var Appearance_AppIconFilledX: String { return self._s[770]! } + public var PrivacySettings_PrivacyTitle: String { return self._s[771]! } public func Conversation_BotInteractiveUrlAlert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[765]!, self._r[765]!, [_0]) + return formatWithArgumentRanges(self._s[772]!, self._r[772]!, [_0]) } - public var Coub_TapForSound: String { return self._s[767]! } - public var Map_LocatingError: String { return self._s[768]! } - public var TwoStepAuth_EmailChangeSuccess: String { return self._s[770]! } - public var Conversation_SendMessage_SendSilently: String { return self._s[771]! } - public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[772]! } + public var Coub_TapForSound: String { return self._s[774]! } + public var Map_LocatingError: String { return self._s[775]! } + public var TwoStepAuth_EmailChangeSuccess: String { return self._s[777]! } + public var Conversation_SendMessage_SendSilently: String { return self._s[778]! } + public var VoiceOver_MessageContextOpenMessageMenu: String { return self._s[779]! } public func Wallet_Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[773]!, self._r[773]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[780]!, self._r[780]!, [_1, _2, _3]) } - public var Passport_ForgottenPassword: String { return self._s[774]! } - public var GroupInfo_InviteLink_RevokeLink: String { return self._s[775]! } - public var StickerPacksSettings_ArchivedPacks: String { return self._s[776]! } - public var Login_TermsOfServiceSignupDecline: String { return self._s[778]! } - public var Channel_Moderator_AccessLevelRevoke: String { return self._s[779]! } - public var Message_Location: String { return self._s[780]! } - public var Passport_Identity_NamePlaceholder: String { return self._s[781]! } - public var Channel_Management_Title: String { return self._s[782]! } - public var DialogList_SearchSectionDialogs: String { return self._s[784]! } - public var Compose_NewChannel_Members: String { return self._s[785]! } + public var Passport_ForgottenPassword: String { return self._s[781]! } + public var GroupInfo_InviteLink_RevokeLink: String { return self._s[782]! } + public var StickerPacksSettings_ArchivedPacks: String { return self._s[783]! } + public var Login_TermsOfServiceSignupDecline: String { return self._s[785]! } + public var Channel_Moderator_AccessLevelRevoke: String { return self._s[786]! } + public var Message_Location: String { return self._s[787]! } + public var Passport_Identity_NamePlaceholder: String { return self._s[788]! } + public var Channel_Management_Title: String { return self._s[789]! } + public var DialogList_SearchSectionDialogs: String { return self._s[791]! } + public var Compose_NewChannel_Members: String { return self._s[792]! } public func DialogList_SingleUploadingFileSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[786]!, self._r[786]!, [_0]) + return formatWithArgumentRanges(self._s[793]!, self._r[793]!, [_0]) } - public var GroupInfo_Location: String { return self._s[787]! } - public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[788]! } - public var AutoNightTheme_ScheduledFrom: String { return self._s[789]! } - public var PhotoEditor_WarmthTool: String { return self._s[790]! } - public var Passport_Language_tr: String { return self._s[791]! } + public var GroupInfo_Location: String { return self._s[794]! } + public var Appearance_ThemePreview_ChatList_5_Name: String { return self._s[795]! } + public var AutoNightTheme_ScheduledFrom: String { return self._s[796]! } + public var PhotoEditor_WarmthTool: String { return self._s[797]! } + public var Passport_Language_tr: String { return self._s[798]! } public func PUSH_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[792]!, self._r[792]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[799]!, self._r[799]!, [_1, _2, _3]) } - public var Login_ResetAccountProtected_Reset: String { return self._s[794]! } - public var Watch_PhotoView_Title: String { return self._s[795]! } - public var Passport_Phone_Delete: String { return self._s[796]! } - public var Undo_ChatDeletedForBothSides: String { return self._s[797]! } - public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[798]! } - public var GroupInfo_Permissions: String { return self._s[799]! } - public var PasscodeSettings_TurnPasscodeOff: String { return self._s[800]! } - public var Profile_ShareContactButton: String { return self._s[801]! } - public var ChatSettings_Other: String { return self._s[802]! } - public var UserInfo_NotificationsDisabled: String { return self._s[803]! } - public var CheckoutInfo_ShippingInfoCity: String { return self._s[804]! } - public var LastSeen_WithinAMonth: String { return self._s[805]! } - public var VoiceOver_Chat_PlayHint: String { return self._s[806]! } - public var Conversation_ReportGroupLocation: String { return self._s[807]! } - public var Conversation_EncryptionCanceled: String { return self._s[808]! } - public var MediaPicker_GroupDescription: String { return self._s[809]! } - public var WebSearch_Images: String { return self._s[810]! } + public var Login_ResetAccountProtected_Reset: String { return self._s[801]! } + public var Watch_PhotoView_Title: String { return self._s[802]! } + public var Passport_Phone_Delete: String { return self._s[803]! } + public var Undo_ChatDeletedForBothSides: String { return self._s[804]! } + public var Conversation_EditingMessageMediaEditCurrentPhoto: String { return self._s[805]! } + public var GroupInfo_Permissions: String { return self._s[806]! } + public var PasscodeSettings_TurnPasscodeOff: String { return self._s[807]! } + public var Profile_ShareContactButton: String { return self._s[808]! } + public var ChatSettings_Other: String { return self._s[809]! } + public var UserInfo_NotificationsDisabled: String { return self._s[810]! } + public var CheckoutInfo_ShippingInfoCity: String { return self._s[811]! } + public var LastSeen_WithinAMonth: String { return self._s[812]! } + public var VoiceOver_Chat_PlayHint: String { return self._s[813]! } + public var Conversation_ReportGroupLocation: String { return self._s[814]! } + public var Conversation_EncryptionCanceled: String { return self._s[815]! } + public var MediaPicker_GroupDescription: String { return self._s[816]! } + public var WebSearch_Images: String { return self._s[817]! } public func Channel_Management_PromotedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[811]!, self._r[811]!, [_0]) + return formatWithArgumentRanges(self._s[818]!, self._r[818]!, [_0]) } - public var Message_Photo: String { return self._s[812]! } - public var PasscodeSettings_HelpBottom: String { return self._s[813]! } - public var AutoDownloadSettings_VideosTitle: String { return self._s[814]! } - public var VoiceOver_Media_PlaybackRateChange: String { return self._s[815]! } - public var Passport_Identity_AddDriversLicense: String { return self._s[816]! } - public var TwoStepAuth_EnterPasswordPassword: String { return self._s[817]! } - public var NotificationsSound_Calypso: String { return self._s[818]! } - public var Map_Map: String { return self._s[819]! } - public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[821]! } - public var ChatSettings_TextSizeUnits: String { return self._s[822]! } + public var Message_Photo: String { return self._s[819]! } + public var PasscodeSettings_HelpBottom: String { return self._s[820]! } + public var AutoDownloadSettings_VideosTitle: String { return self._s[821]! } + public var VoiceOver_Media_PlaybackRateChange: String { return self._s[822]! } + public var Passport_Identity_AddDriversLicense: String { return self._s[823]! } + public var TwoStepAuth_EnterPasswordPassword: String { return self._s[824]! } + public var NotificationsSound_Calypso: String { return self._s[825]! } + public var Map_Map: String { return self._s[826]! } + public var CheckoutInfo_ReceiverInfoTitle: String { return self._s[828]! } + public var ChatSettings_TextSizeUnits: String { return self._s[829]! } public func VoiceOver_Chat_FileFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[823]!, self._r[823]!, [_0]) + return formatWithArgumentRanges(self._s[830]!, self._r[830]!, [_0]) } - public var Common_of: String { return self._s[824]! } - public var Conversation_ForwardContacts: String { return self._s[827]! } + public var Common_of: String { return self._s[831]! } + public var Conversation_ForwardContacts: String { return self._s[834]! } public func Call_AnsweringWithAccount(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[829]!, self._r[829]!, [_0]) - } - public var Passport_Language_hy: String { return self._s[830]! } - public var Notifications_MessageNotificationsHelp: String { return self._s[831]! } - public var AutoDownloadSettings_Reset: String { return self._s[832]! } - public var Wallet_TransactionInfo_AddressCopied: String { return self._s[833]! } - public var Paint_ClearConfirm: String { return self._s[834]! } - public var Camera_VideoMode: String { return self._s[835]! } - public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[836]!, self._r[836]!, [_0]) } - public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[837]! } - public var Conversation_ViewBackground: String { return self._s[838]! } + public var Passport_Language_hy: String { return self._s[837]! } + public var Notifications_MessageNotificationsHelp: String { return self._s[838]! } + public var AutoDownloadSettings_Reset: String { return self._s[839]! } + public var Wallet_TransactionInfo_AddressCopied: String { return self._s[840]! } + public var Paint_ClearConfirm: String { return self._s[841]! } + public var Camera_VideoMode: String { return self._s[842]! } + public func Conversation_RestrictedStickersTimed(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[843]!, self._r[843]!, [_0]) + } + public var Privacy_Calls_AlwaysAllow_Placeholder: String { return self._s[844]! } + public var Conversation_ViewBackground: String { return self._s[845]! } public func Wallet_Info_TransactionDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[839]!, self._r[839]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[846]!, self._r[846]!, [_1, _2, _3]) } - public var Passport_Language_el: String { return self._s[840]! } - public var PhotoEditor_Original: String { return self._s[841]! } - public var Settings_FAQ_Button: String { return self._s[843]! } - public var Channel_Setup_PublicNoLink: String { return self._s[845]! } - public var Conversation_UnsupportedMedia: String { return self._s[846]! } - public var Conversation_SlideToCancel: String { return self._s[847]! } - public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[848]! } - public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[849]! } - public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[850]! } - public var Conversation_ReportSpamChannelConfirmation: String { return self._s[851]! } - public var AutoNightTheme_NotAvailable: String { return self._s[852]! } - public var Conversation_Owner: String { return self._s[853]! } - public var Common_Create: String { return self._s[854]! } - public var Settings_ApplyProxyAlertEnable: String { return self._s[855]! } - public var ContactList_Context_Call: String { return self._s[856]! } - public var Localization_ChooseLanguage: String { return self._s[858]! } - public var ChatList_Context_AddToContacts: String { return self._s[860]! } - public var Settings_Proxy: String { return self._s[862]! } - public var Privacy_TopPeersHelp: String { return self._s[863]! } - public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[864]! } - public var Chat_UnsendMyMessages: String { return self._s[865]! } + public var Passport_Language_el: String { return self._s[847]! } + public var PhotoEditor_Original: String { return self._s[848]! } + public var Settings_FAQ_Button: String { return self._s[850]! } + public var Channel_Setup_PublicNoLink: String { return self._s[852]! } + public var Conversation_UnsupportedMedia: String { return self._s[853]! } + public var Conversation_SlideToCancel: String { return self._s[854]! } + public var Appearance_ThemePreview_ChatList_4_Name: String { return self._s[855]! } + public var Passport_Identity_OneOfTypeInternalPassport: String { return self._s[856]! } + public var CheckoutInfo_ShippingInfoPostcode: String { return self._s[857]! } + public var Conversation_ReportSpamChannelConfirmation: String { return self._s[858]! } + public var AutoNightTheme_NotAvailable: String { return self._s[859]! } + public var Conversation_Owner: String { return self._s[860]! } + public var Common_Create: String { return self._s[861]! } + public var Settings_ApplyProxyAlertEnable: String { return self._s[862]! } + public var ContactList_Context_Call: String { return self._s[863]! } + public var Localization_ChooseLanguage: String { return self._s[865]! } + public var ChatList_Context_AddToContacts: String { return self._s[867]! } + public var Settings_Proxy: String { return self._s[869]! } + public var Privacy_TopPeersHelp: String { return self._s[870]! } + public var CheckoutInfo_ShippingInfoCountryPlaceholder: String { return self._s[871]! } + public var Chat_UnsendMyMessages: String { return self._s[872]! } public func VoiceOver_Chat_Duration(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[866]!, self._r[866]!, [_0]) - } - public var TwoStepAuth_ConfirmationAbort: String { return self._s[867]! } - public func Contacts_AccessDeniedHelpPortrait(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[869]!, self._r[869]!, [_0]) - } - public var Contacts_SortedByPresence: String { return self._s[870]! } - public var Passport_Identity_SurnamePlaceholder: String { return self._s[871]! } - public var Cache_Title: String { return self._s[872]! } - public func Login_PhoneBannedEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[873]!, self._r[873]!, [_0]) } - public var TwoStepAuth_EmailCodeExpired: String { return self._s[874]! } - public var Channel_Moderator_Title: String { return self._s[875]! } - public var InstantPage_AutoNightTheme: String { return self._s[877]! } + public var TwoStepAuth_ConfirmationAbort: String { return self._s[874]! } + public func Contacts_AccessDeniedHelpPortrait(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[876]!, self._r[876]!, [_0]) + } + public var Contacts_SortedByPresence: String { return self._s[877]! } + public var Passport_Identity_SurnamePlaceholder: String { return self._s[878]! } + public var Cache_Title: String { return self._s[879]! } + public func Login_PhoneBannedEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[880]!, self._r[880]!, [_0]) + } + public var TwoStepAuth_EmailCodeExpired: String { return self._s[881]! } + public var Channel_Moderator_Title: String { return self._s[882]! } + public var InstantPage_AutoNightTheme: String { return self._s[884]! } public func PUSH_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[880]!, self._r[880]!, [_1]) + return formatWithArgumentRanges(self._s[887]!, self._r[887]!, [_1]) } - public var Passport_Scans_Upload: String { return self._s[881]! } - public var Undo_Undo: String { return self._s[883]! } - public var Contacts_AccessDeniedHelpON: String { return self._s[884]! } - public var TwoStepAuth_RemovePassword: String { return self._s[885]! } - public var Common_Delete: String { return self._s[886]! } - public var Contacts_AddPeopleNearby: String { return self._s[888]! } - public var Conversation_ContextMenuDelete: String { return self._s[889]! } - public var SocksProxySetup_Credentials: String { return self._s[890]! } - public var Appearance_EditTheme: String { return self._s[892]! } - public var PasscodeSettings_AutoLock_Disabled: String { return self._s[893]! } - public var Wallet_Send_NetworkErrorText: String { return self._s[894]! } - public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[897]! } - public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[898]! } - public var Passport_Language_id: String { return self._s[900]! } - public var WallpaperSearch_ColorTeal: String { return self._s[901]! } - public var ChannelIntro_Title: String { return self._s[902]! } + public var Passport_Scans_Upload: String { return self._s[888]! } + public var Undo_Undo: String { return self._s[890]! } + public var Contacts_AccessDeniedHelpON: String { return self._s[891]! } + public var TwoStepAuth_RemovePassword: String { return self._s[892]! } + public var Common_Delete: String { return self._s[893]! } + public var Contacts_AddPeopleNearby: String { return self._s[895]! } + public var Conversation_ContextMenuDelete: String { return self._s[896]! } + public var SocksProxySetup_Credentials: String { return self._s[897]! } + public var Appearance_EditTheme: String { return self._s[899]! } + public var PasscodeSettings_AutoLock_Disabled: String { return self._s[900]! } + public var Wallet_Send_NetworkErrorText: String { return self._s[901]! } + public var Passport_Address_OneOfTypeRentalAgreement: String { return self._s[904]! } + public var Conversation_ShareBotContactConfirmationTitle: String { return self._s[905]! } + public var Passport_Language_id: String { return self._s[907]! } + public var WallpaperSearch_ColorTeal: String { return self._s[908]! } + public var ChannelIntro_Title: String { return self._s[909]! } public func Channel_AdminLog_MessageToggleSignaturesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[903]!, self._r[903]!, [_0]) + return formatWithArgumentRanges(self._s[910]!, self._r[910]!, [_0]) } - public var VoiceOver_Chat_OpenLinkHint: String { return self._s[905]! } - public var VoiceOver_Chat_Reply: String { return self._s[906]! } - public var ScheduledMessages_BotActionUnavailable: String { return self._s[907]! } - public var Channel_Info_Description: String { return self._s[908]! } - public var Stickers_FavoriteStickers: String { return self._s[909]! } - public var Channel_BanUser_PermissionAddMembers: String { return self._s[910]! } - public var Notifications_DisplayNamesOnLockScreen: String { return self._s[911]! } - public var ChatSearch_ResultsTooltip: String { return self._s[912]! } - public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[913]! } - public var Calls_NoMissedCallsPlacehoder: String { return self._s[914]! } - public var Group_PublicLink_Placeholder: String { return self._s[915]! } - public var Notifications_ExceptionsDefaultSound: String { return self._s[916]! } + public var VoiceOver_Chat_OpenLinkHint: String { return self._s[912]! } + public var VoiceOver_Chat_Reply: String { return self._s[913]! } + public var ScheduledMessages_BotActionUnavailable: String { return self._s[914]! } + public var Channel_Info_Description: String { return self._s[915]! } + public var Stickers_FavoriteStickers: String { return self._s[916]! } + public var Channel_BanUser_PermissionAddMembers: String { return self._s[917]! } + public var Notifications_DisplayNamesOnLockScreen: String { return self._s[918]! } + public var ChatSearch_ResultsTooltip: String { return self._s[919]! } + public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[920]! } + public var Calls_NoMissedCallsPlacehoder: String { return self._s[921]! } + public var Group_PublicLink_Placeholder: String { return self._s[922]! } + public var Notifications_ExceptionsDefaultSound: String { return self._s[923]! } public func PUSH_CHANNEL_MESSAGE_POLL(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[917]!, self._r[917]!, [_1]) + return formatWithArgumentRanges(self._s[924]!, self._r[924]!, [_1]) } - public var TextFormat_Underline: String { return self._s[918]! } + public var TextFormat_Underline: String { return self._s[925]! } public func DialogList_SearchSubtitleFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[919]!, self._r[919]!, [_1, _2]) + return formatWithArgumentRanges(self._s[926]!, self._r[926]!, [_1, _2]) } public func Channel_AdminLog_MessageRemovedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[920]!, self._r[920]!, [_0]) + return formatWithArgumentRanges(self._s[927]!, self._r[927]!, [_0]) } - public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[921]! } + public var Appearance_ThemePreview_ChatList_3_Name: String { return self._s[928]! } public func Channel_OwnershipTransfer_TransferCompleted(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[922]!, self._r[922]!, [_1, _2]) - } - public var Wallet_Intro_ImportExisting: String { return self._s[923]! } - public var GroupPermission_Delete: String { return self._s[924]! } - public var Passport_Language_uk: String { return self._s[925]! } - public var StickerPack_HideStickers: String { return self._s[927]! } - public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[928]! } - public func PUSH_CHAT_MESSAGE_PHOTO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[929]!, self._r[929]!, [_1, _2]) } - public var Activity_UploadingVideoMessage: String { return self._s[930]! } + public var Wallet_Intro_ImportExisting: String { return self._s[930]! } + public var GroupPermission_Delete: String { return self._s[931]! } + public var Passport_Language_uk: String { return self._s[932]! } + public var StickerPack_HideStickers: String { return self._s[934]! } + public var ChangePhoneNumberNumber_NumberPlaceholder: String { return self._s[935]! } + public func PUSH_CHAT_MESSAGE_PHOTO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[936]!, self._r[936]!, [_1, _2]) + } + public var Activity_UploadingVideoMessage: String { return self._s[937]! } public func GroupPermission_ApplyAlertText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[931]!, self._r[931]!, [_0]) + return formatWithArgumentRanges(self._s[938]!, self._r[938]!, [_0]) } - public var Channel_TitleInfo: String { return self._s[932]! } - public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[933]! } - public var Settings_CallSettings: String { return self._s[934]! } - public var Camera_SquareMode: String { return self._s[935]! } - public var Conversation_SendMessage_ScheduleMessage: String { return self._s[936]! } - public var GroupInfo_SharedMediaNone: String { return self._s[937]! } + public var Channel_TitleInfo: String { return self._s[939]! } + public var StickerPacksSettings_ArchivedPacks_Info: String { return self._s[940]! } + public var Settings_CallSettings: String { return self._s[941]! } + public var Camera_SquareMode: String { return self._s[942]! } + public var Conversation_SendMessage_ScheduleMessage: String { return self._s[943]! } + public var GroupInfo_SharedMediaNone: String { return self._s[944]! } public func PUSH_MESSAGE_VIDEO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[938]!, self._r[938]!, [_1]) + return formatWithArgumentRanges(self._s[945]!, self._r[945]!, [_1]) } - public var Bot_GenericBotStatus: String { return self._s[939]! } - public var Application_Update: String { return self._s[941]! } - public var Month_ShortJanuary: String { return self._s[942]! } - public var Contacts_PermissionsKeepDisabled: String { return self._s[943]! } - public var Channel_AdminLog_BanReadMessages: String { return self._s[944]! } - public var Settings_AppLanguage_Unofficial: String { return self._s[945]! } - public var Passport_Address_Street2Placeholder: String { return self._s[946]! } + public var Bot_GenericBotStatus: String { return self._s[946]! } + public var Application_Update: String { return self._s[948]! } + public var Month_ShortJanuary: String { return self._s[949]! } + public var Contacts_PermissionsKeepDisabled: String { return self._s[950]! } + public var Channel_AdminLog_BanReadMessages: String { return self._s[951]! } + public var Settings_AppLanguage_Unofficial: String { return self._s[952]! } + public var Passport_Address_Street2Placeholder: String { return self._s[953]! } public func Map_LiveLocationShortHour(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[947]!, self._r[947]!, [_0]) + return formatWithArgumentRanges(self._s[954]!, self._r[954]!, [_0]) } - public var NetworkUsageSettings_Cellular: String { return self._s[948]! } - public var Appearance_PreviewOutgoingText: String { return self._s[949]! } - public var Notifications_PermissionsAllowInSettings: String { return self._s[950]! } - public var AutoDownloadSettings_OnForAll: String { return self._s[952]! } - public var Map_Directions: String { return self._s[953]! } - public var Passport_FieldIdentityTranslationHelp: String { return self._s[955]! } - public var Appearance_ThemeDay: String { return self._s[956]! } - public var LogoutOptions_LogOut: String { return self._s[957]! } - public var Group_PublicLink_Title: String { return self._s[959]! } - public var Channel_AddBotErrorNoRights: String { return self._s[960]! } - public var Passport_Identity_AddPassport: String { return self._s[961]! } - public var LocalGroup_ButtonTitle: String { return self._s[962]! } - public var Call_Message: String { return self._s[963]! } - public var PhotoEditor_ExposureTool: String { return self._s[964]! } - public var Wallet_Receive_CommentInfo: String { return self._s[966]! } - public var Passport_FieldOneOf_Delimeter: String { return self._s[967]! } - public var Channel_AdminLog_CanBanUsers: String { return self._s[969]! } - public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[970]! } - public var Appearance_Preview: String { return self._s[971]! } - public var Compose_ChannelMembers: String { return self._s[972]! } - public var Conversation_DeleteManyMessages: String { return self._s[973]! } - public var ReportPeer_ReasonOther_Title: String { return self._s[974]! } - public var Checkout_ErrorProviderAccountTimeout: String { return self._s[975]! } - public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[976]! } - public var Channel_Stickers_CreateYourOwn: String { return self._s[979]! } - public var Conversation_UpdateTelegram: String { return self._s[980]! } - public var EditTheme_Create_TopInfo: String { return self._s[981]! } + public var NetworkUsageSettings_Cellular: String { return self._s[955]! } + public var Appearance_PreviewOutgoingText: String { return self._s[956]! } + public var Notifications_PermissionsAllowInSettings: String { return self._s[957]! } + public var AutoDownloadSettings_OnForAll: String { return self._s[959]! } + public var Map_Directions: String { return self._s[960]! } + public var Passport_FieldIdentityTranslationHelp: String { return self._s[962]! } + public var Appearance_ThemeDay: String { return self._s[963]! } + public var LogoutOptions_LogOut: String { return self._s[964]! } + public var Group_PublicLink_Title: String { return self._s[966]! } + public var Channel_AddBotErrorNoRights: String { return self._s[967]! } + public var Passport_Identity_AddPassport: String { return self._s[968]! } + public var LocalGroup_ButtonTitle: String { return self._s[969]! } + public var Call_Message: String { return self._s[970]! } + public var PhotoEditor_ExposureTool: String { return self._s[971]! } + public var Wallet_Receive_CommentInfo: String { return self._s[973]! } + public var Passport_FieldOneOf_Delimeter: String { return self._s[974]! } + public var Channel_AdminLog_CanBanUsers: String { return self._s[976]! } + public var Appearance_ThemePreview_ChatList_2_Name: String { return self._s[977]! } + public var Appearance_Preview: String { return self._s[978]! } + public var Compose_ChannelMembers: String { return self._s[979]! } + public var Conversation_DeleteManyMessages: String { return self._s[980]! } + public var ReportPeer_ReasonOther_Title: String { return self._s[981]! } + public var Checkout_ErrorProviderAccountTimeout: String { return self._s[982]! } + public var TwoStepAuth_ResetAccountConfirmation: String { return self._s[983]! } + public var Channel_Stickers_CreateYourOwn: String { return self._s[986]! } + public var Conversation_UpdateTelegram: String { return self._s[987]! } + public var EditTheme_Create_TopInfo: String { return self._s[988]! } public func Notification_PinnedPhotoMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[982]!, self._r[982]!, [_0]) + return formatWithArgumentRanges(self._s[989]!, self._r[989]!, [_0]) } - public var Wallet_WordCheck_Continue: String { return self._s[983]! } + public var Wallet_WordCheck_Continue: String { return self._s[990]! } + public var TwoFactorSetup_Hint_Action: String { return self._s[991]! } public func PUSH_PINNED_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[984]!, self._r[984]!, [_1]) + return formatWithArgumentRanges(self._s[992]!, self._r[992]!, [_1]) } - public var GroupInfo_Administrators_Title: String { return self._s[985]! } - public var Privacy_Forwards_PreviewMessageText: String { return self._s[986]! } + public var GroupInfo_Administrators_Title: String { return self._s[993]! } + public var Privacy_Forwards_PreviewMessageText: String { return self._s[994]! } public func PrivacySettings_LastSeenNobodyPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[987]!, self._r[987]!, [_0]) + return formatWithArgumentRanges(self._s[995]!, self._r[995]!, [_0]) } - public var Tour_Title3: String { return self._s[988]! } - public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[989]! } - public var Clipboard_SendPhoto: String { return self._s[993]! } - public var MediaPicker_Videos: String { return self._s[994]! } - public var Passport_Email_Title: String { return self._s[995]! } + public var Tour_Title3: String { return self._s[996]! } + public var Channel_EditAdmin_PermissionInviteSubscribers: String { return self._s[997]! } + public var Clipboard_SendPhoto: String { return self._s[1001]! } + public var MediaPicker_Videos: String { return self._s[1002]! } + public var Passport_Email_Title: String { return self._s[1003]! } public func PrivacySettings_LastSeenEverybodyMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[996]!, self._r[996]!, [_0]) + return formatWithArgumentRanges(self._s[1004]!, self._r[1004]!, [_0]) } - public var StickerPacksSettings_Title: String { return self._s[997]! } - public var Conversation_MessageDialogDelete: String { return self._s[998]! } - public var Privacy_Calls_CustomHelp: String { return self._s[1000]! } - public var Message_Wallpaper: String { return self._s[1001]! } - public var MemberSearch_BotSection: String { return self._s[1002]! } - public var GroupInfo_SetSound: String { return self._s[1003]! } - public var Core_ServiceUserStatus: String { return self._s[1004]! } - public var LiveLocationUpdated_JustNow: String { return self._s[1005]! } - public var Call_StatusFailed: String { return self._s[1006]! } - public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1007]! } - public var TwoStepAuth_SetPassword: String { return self._s[1008]! } - public var Permissions_PeopleNearbyText_v0: String { return self._s[1009]! } + public var StickerPacksSettings_Title: String { return self._s[1005]! } + public var Conversation_MessageDialogDelete: String { return self._s[1006]! } + public var Privacy_Calls_CustomHelp: String { return self._s[1008]! } + public var Message_Wallpaper: String { return self._s[1009]! } + public var MemberSearch_BotSection: String { return self._s[1010]! } + public var GroupInfo_SetSound: String { return self._s[1011]! } + public var Core_ServiceUserStatus: String { return self._s[1012]! } + public var LiveLocationUpdated_JustNow: String { return self._s[1013]! } + public var Call_StatusFailed: String { return self._s[1014]! } + public var TwoFactorSetup_Email_Placeholder: String { return self._s[1015]! } + public var TwoStepAuth_SetupPasswordDescription: String { return self._s[1016]! } + public var TwoStepAuth_SetPassword: String { return self._s[1017]! } + public var Permissions_PeopleNearbyText_v0: String { return self._s[1018]! } public func SocksProxySetup_ProxyStatusPing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1011]!, self._r[1011]!, [_0]) + return formatWithArgumentRanges(self._s[1020]!, self._r[1020]!, [_0]) } - public var Calls_SubmitRating: String { return self._s[1012]! } - public var Profile_Username: String { return self._s[1013]! } - public var Bot_DescriptionTitle: String { return self._s[1014]! } - public var MaskStickerSettings_Title: String { return self._s[1015]! } - public var SharedMedia_CategoryOther: String { return self._s[1016]! } - public var GroupInfo_SetGroupPhoto: String { return self._s[1017]! } - public var Common_NotNow: String { return self._s[1018]! } - public var CallFeedback_IncludeLogsInfo: String { return self._s[1019]! } - public var Conversation_ShareMyPhoneNumber: String { return self._s[1020]! } - public var Map_Location: String { return self._s[1021]! } - public var Invitation_JoinGroup: String { return self._s[1022]! } - public var AutoDownloadSettings_Title: String { return self._s[1024]! } - public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1025]! } - public var Channel_ErrorAddBlocked: String { return self._s[1026]! } - public var Conversation_UnblockUser: String { return self._s[1027]! } - public var EditTheme_Edit_TopInfo: String { return self._s[1028]! } - public var Watch_Bot_Restart: String { return self._s[1029]! } - public var TwoStepAuth_Title: String { return self._s[1030]! } - public var Channel_AdminLog_BanSendMessages: String { return self._s[1031]! } - public var Checkout_ShippingMethod: String { return self._s[1032]! } - public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1033]! } + public var Calls_SubmitRating: String { return self._s[1021]! } + public var Profile_Username: String { return self._s[1022]! } + public var Bot_DescriptionTitle: String { return self._s[1023]! } + public var MaskStickerSettings_Title: String { return self._s[1024]! } + public var SharedMedia_CategoryOther: String { return self._s[1025]! } + public var GroupInfo_SetGroupPhoto: String { return self._s[1026]! } + public var Common_NotNow: String { return self._s[1027]! } + public var CallFeedback_IncludeLogsInfo: String { return self._s[1028]! } + public var Conversation_ShareMyPhoneNumber: String { return self._s[1029]! } + public var Map_Location: String { return self._s[1030]! } + public var Invitation_JoinGroup: String { return self._s[1031]! } + public var AutoDownloadSettings_Title: String { return self._s[1033]! } + public var Conversation_DiscardVoiceMessageDescription: String { return self._s[1034]! } + public var Channel_ErrorAddBlocked: String { return self._s[1035]! } + public var Conversation_UnblockUser: String { return self._s[1036]! } + public var EditTheme_Edit_TopInfo: String { return self._s[1037]! } + public var Watch_Bot_Restart: String { return self._s[1038]! } + public var TwoStepAuth_Title: String { return self._s[1039]! } + public var Channel_AdminLog_BanSendMessages: String { return self._s[1040]! } + public var Checkout_ShippingMethod: String { return self._s[1041]! } + public var Passport_Identity_OneOfTypeIdentityCard: String { return self._s[1042]! } public func PUSH_CHAT_MESSAGE_STICKER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1034]!, self._r[1034]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1043]!, self._r[1043]!, [_1, _2, _3]) } public func Chat_UnsendMyMessagesAlertTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1036]!, self._r[1036]!, [_0]) + return formatWithArgumentRanges(self._s[1045]!, self._r[1045]!, [_0]) } public func Channel_Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1037]!, self._r[1037]!, [_0]) + return formatWithArgumentRanges(self._s[1046]!, self._r[1046]!, [_0]) } - public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1038]! } - public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1039]! } - public var AuthSessions_TerminateOtherSessions: String { return self._s[1040]! } - public var Contacts_FailedToSendInvitesMessage: String { return self._s[1041]! } - public var PrivacySettings_TwoStepAuth: String { return self._s[1042]! } - public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1043]! } - public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1044]! } - public var Conversation_EditingMessagePanelMedia: String { return self._s[1045]! } - public var Checkout_PaymentMethod_Title: String { return self._s[1046]! } - public var SocksProxySetup_Connection: String { return self._s[1047]! } - public var Group_MessagePhotoRemoved: String { return self._s[1048]! } - public var Channel_Stickers_NotFound: String { return self._s[1051]! } - public var Group_About_Help: String { return self._s[1052]! } - public var Notification_PassportValueProofOfIdentity: String { return self._s[1053]! } - public var PeopleNearby_Title: String { return self._s[1055]! } + public var Appearance_ThemePreview_ChatList_1_Name: String { return self._s[1047]! } + public var SettingsSearch_Synonyms_Data_AutoplayGifs: String { return self._s[1048]! } + public var AuthSessions_TerminateOtherSessions: String { return self._s[1049]! } + public var Contacts_FailedToSendInvitesMessage: String { return self._s[1050]! } + public var PrivacySettings_TwoStepAuth: String { return self._s[1051]! } + public var Notification_Exceptions_PreviewAlwaysOn: String { return self._s[1052]! } + public var SettingsSearch_Synonyms_Privacy_Passcode: String { return self._s[1053]! } + public var Conversation_EditingMessagePanelMedia: String { return self._s[1054]! } + public var Checkout_PaymentMethod_Title: String { return self._s[1055]! } + public var SocksProxySetup_Connection: String { return self._s[1056]! } + public var Group_MessagePhotoRemoved: String { return self._s[1057]! } + public var Channel_Stickers_NotFound: String { return self._s[1060]! } + public var Group_About_Help: String { return self._s[1061]! } + public var Notification_PassportValueProofOfIdentity: String { return self._s[1062]! } + public var PeopleNearby_Title: String { return self._s[1064]! } public func ApplyLanguage_ChangeLanguageOfficialText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1056]!, self._r[1056]!, [_1]) + return formatWithArgumentRanges(self._s[1065]!, self._r[1065]!, [_1]) } - public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1058]! } - public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1059]! } - public var SocksProxySetup_Password: String { return self._s[1060]! } - public var Notifications_PermissionsEnable: String { return self._s[1061]! } - public var TwoStepAuth_ChangeEmail: String { return self._s[1063]! } + public var CheckoutInfo_ShippingInfoStatePlaceholder: String { return self._s[1067]! } + public var Notifications_GroupNotificationsExceptionsHelp: String { return self._s[1068]! } + public var SocksProxySetup_Password: String { return self._s[1069]! } + public var Notifications_PermissionsEnable: String { return self._s[1070]! } + public var TwoStepAuth_ChangeEmail: String { return self._s[1072]! } public func Channel_AdminLog_MessageInvitedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1064]!, self._r[1064]!, [_1]) + return formatWithArgumentRanges(self._s[1073]!, self._r[1073]!, [_1]) } public func Time_MonthOfYear_m10(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1066]!, self._r[1066]!, [_0]) + return formatWithArgumentRanges(self._s[1075]!, self._r[1075]!, [_0]) } - public var Passport_Identity_TypeDriversLicense: String { return self._s[1067]! } - public var ArchivedPacksAlert_Title: String { return self._s[1068]! } - public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1069]! } + public var Passport_Identity_TypeDriversLicense: String { return self._s[1076]! } + public var ArchivedPacksAlert_Title: String { return self._s[1077]! } + public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[1078]! } public func Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1070]!, self._r[1070]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1079]!, self._r[1079]!, [_1, _2, _3]) } - public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1071]! } - public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1073]! } - public var Conversation_StatusTyping: String { return self._s[1074]! } - public var Broadcast_AdminLog_EmptyText: String { return self._s[1075]! } - public var Notification_PassportValueProofOfAddress: String { return self._s[1076]! } - public var UserInfo_CreateNewContact: String { return self._s[1077]! } - public var Passport_Identity_FrontSide: String { return self._s[1078]! } - public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1079]! } - public var Calls_CallTabTitle: String { return self._s[1080]! } - public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1081]! } + public var PrivacyLastSeenSettings_GroupsAndChannelsHelp: String { return self._s[1080]! } + public var Privacy_Calls_NeverAllow_Placeholder: String { return self._s[1082]! } + public var Conversation_StatusTyping: String { return self._s[1083]! } + public var Broadcast_AdminLog_EmptyText: String { return self._s[1084]! } + public var Notification_PassportValueProofOfAddress: String { return self._s[1085]! } + public var UserInfo_CreateNewContact: String { return self._s[1086]! } + public var Passport_Identity_FrontSide: String { return self._s[1087]! } + public var Login_PhoneNumberAlreadyAuthorizedSwitch: String { return self._s[1088]! } + public var Calls_CallTabTitle: String { return self._s[1089]! } + public var Channel_AdminLog_ChannelEmptyText: String { return self._s[1090]! } public func Login_BannedPhoneBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1083]!, self._r[1083]!, [_0]) + return formatWithArgumentRanges(self._s[1092]!, self._r[1092]!, [_0]) } - public var Watch_UserInfo_MuteTitle: String { return self._s[1084]! } - public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1085]! } - public var SharedMedia_EmptyMusicText: String { return self._s[1086]! } - public var Wallet_Completed_Text: String { return self._s[1087]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1088]! } - public var Paint_Stickers: String { return self._s[1089]! } - public var Privacy_GroupsAndChannels: String { return self._s[1090]! } - public var ChatList_Context_Delete: String { return self._s[1092]! } - public var UserInfo_AddContact: String { return self._s[1093]! } + public var Watch_UserInfo_MuteTitle: String { return self._s[1093]! } + public var Group_EditAdmin_RankAdminPlaceholder: String { return self._s[1094]! } + public var SharedMedia_EmptyMusicText: String { return self._s[1095]! } + public var Wallet_Completed_Text: String { return self._s[1096]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1minute: String { return self._s[1097]! } + public var Paint_Stickers: String { return self._s[1098]! } + public var Privacy_GroupsAndChannels: String { return self._s[1099]! } + public var ChatList_Context_Delete: String { return self._s[1101]! } + public var UserInfo_AddContact: String { return self._s[1102]! } public func Conversation_MessageViaUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1094]!, self._r[1094]!, [_0]) + return formatWithArgumentRanges(self._s[1103]!, self._r[1103]!, [_0]) } - public var PhoneNumberHelp_ChangeNumber: String { return self._s[1096]! } + public var PhoneNumberHelp_ChangeNumber: String { return self._s[1105]! } public func ChatList_ClearChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1098]!, self._r[1098]!, [_0]) + return formatWithArgumentRanges(self._s[1107]!, self._r[1107]!, [_0]) } - public var DialogList_NoMessagesTitle: String { return self._s[1099]! } - public var EditProfile_NameAndPhotoHelp: String { return self._s[1100]! } - public var BlockedUsers_BlockUser: String { return self._s[1101]! } - public var Notifications_PermissionsOpenSettings: String { return self._s[1102]! } - public var MediaPicker_UngroupDescription: String { return self._s[1103]! } - public var Watch_NoConnection: String { return self._s[1104]! } - public var Month_GenSeptember: String { return self._s[1105]! } - public var Conversation_ViewGroup: String { return self._s[1107]! } - public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1110]! } - public var Privacy_Forwards_AlwaysLink: String { return self._s[1111]! } - public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1112]! } - public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1113]! } - public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1114]! } - public var MediaPicker_CameraRoll: String { return self._s[1116]! } - public var Month_GenAugust: String { return self._s[1117]! } - public var AccessDenied_VideoMessageMicrophone: String { return self._s[1118]! } - public var SharedMedia_EmptyText: String { return self._s[1119]! } - public var Map_ShareLiveLocation: String { return self._s[1120]! } - public var Calls_All: String { return self._s[1121]! } - public var Appearance_ThemeNight: String { return self._s[1124]! } - public var Conversation_HoldForAudio: String { return self._s[1125]! } - public var SettingsSearch_Synonyms_Support: String { return self._s[1128]! } - public var GroupInfo_GroupHistoryHidden: String { return self._s[1129]! } - public var SocksProxySetup_Secret: String { return self._s[1130]! } + public var DialogList_NoMessagesTitle: String { return self._s[1108]! } + public var EditProfile_NameAndPhotoHelp: String { return self._s[1109]! } + public var BlockedUsers_BlockUser: String { return self._s[1110]! } + public var Notifications_PermissionsOpenSettings: String { return self._s[1111]! } + public var MediaPicker_UngroupDescription: String { return self._s[1112]! } + public var Watch_NoConnection: String { return self._s[1113]! } + public var Month_GenSeptember: String { return self._s[1114]! } + public var Conversation_ViewGroup: String { return self._s[1116]! } + public var Channel_AdminLogFilter_EventsLeavingSubscribers: String { return self._s[1119]! } + public var Privacy_Forwards_AlwaysLink: String { return self._s[1120]! } + public var Channel_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[1121]! } + public var Passport_FieldOneOf_FinalDelimeter: String { return self._s[1122]! } + public var Wallet_WordCheck_IncorrectHeader: String { return self._s[1123]! } + public var MediaPicker_CameraRoll: String { return self._s[1125]! } + public var Month_GenAugust: String { return self._s[1126]! } + public var AccessDenied_VideoMessageMicrophone: String { return self._s[1127]! } + public var SharedMedia_EmptyText: String { return self._s[1128]! } + public var Map_ShareLiveLocation: String { return self._s[1129]! } + public var Calls_All: String { return self._s[1130]! } + public var Appearance_ThemeNight: String { return self._s[1133]! } + public var Conversation_HoldForAudio: String { return self._s[1134]! } + public var SettingsSearch_Synonyms_Support: String { return self._s[1137]! } + public var GroupInfo_GroupHistoryHidden: String { return self._s[1138]! } + public var SocksProxySetup_Secret: String { return self._s[1139]! } public func Activity_RemindAboutChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1131]!, self._r[1131]!, [_0]) + return formatWithArgumentRanges(self._s[1140]!, self._r[1140]!, [_0]) } - public var Channel_BanList_RestrictedTitle: String { return self._s[1133]! } - public var Conversation_Location: String { return self._s[1134]! } + public var Channel_BanList_RestrictedTitle: String { return self._s[1142]! } + public var Conversation_Location: String { return self._s[1143]! } public func AutoDownloadSettings_UpToFor(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1135]!, self._r[1135]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1144]!, self._r[1144]!, [_1, _2]) } - public var ChatSettings_AutoDownloadPhotos: String { return self._s[1137]! } - public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1138]! } - public var Notifications_PermissionsText: String { return self._s[1139]! } - public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1140]! } - public var Call_Flip: String { return self._s[1141]! } - public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1143]! } - public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1144]! } - public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1145]! } - public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1147]! } - public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1149]! } - public var Channel_TooMuchBots: String { return self._s[1151]! } - public var Passport_DeletePassportConfirmation: String { return self._s[1152]! } - public var Login_InvalidCodeError: String { return self._s[1153]! } - public var StickerPacksSettings_FeaturedPacks: String { return self._s[1154]! } + public var ChatSettings_AutoDownloadPhotos: String { return self._s[1146]! } + public var SettingsSearch_Synonyms_Privacy_Title: String { return self._s[1147]! } + public var Notifications_PermissionsText: String { return self._s[1148]! } + public var SettingsSearch_Synonyms_Data_SaveIncomingPhotos: String { return self._s[1149]! } + public var Call_Flip: String { return self._s[1150]! } + public var Channel_AdminLog_CanDeleteMessagesOfOthers: String { return self._s[1152]! } + public var SocksProxySetup_ProxyStatusConnecting: String { return self._s[1153]! } + public var PrivacyPhoneNumberSettings_DiscoveryHeader: String { return self._s[1154]! } + public var Channel_EditAdmin_PermissionPinMessages: String { return self._s[1156]! } + public var TwoStepAuth_ReEnterPasswordDescription: String { return self._s[1158]! } + public var Channel_TooMuchBots: String { return self._s[1160]! } + public var Passport_DeletePassportConfirmation: String { return self._s[1161]! } + public var Login_InvalidCodeError: String { return self._s[1162]! } + public var StickerPacksSettings_FeaturedPacks: String { return self._s[1163]! } public func ChatList_DeleteSecretChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1155]!, self._r[1155]!, [_0]) + return formatWithArgumentRanges(self._s[1164]!, self._r[1164]!, [_0]) } public func GroupInfo_InvitationLinkAcceptChannel(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1156]!, self._r[1156]!, [_0]) + return formatWithArgumentRanges(self._s[1165]!, self._r[1165]!, [_0]) } - public var VoiceOver_Navigation_ProxySettings: String { return self._s[1157]! } - public var Call_CallInProgressTitle: String { return self._s[1158]! } - public var Month_ShortSeptember: String { return self._s[1159]! } - public var Watch_ChannelInfo_Title: String { return self._s[1160]! } - public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1163]! } - public var DialogList_PasscodeLockHelp: String { return self._s[1164]! } - public var Chat_MultipleTextMessagesDisabled: String { return self._s[1165]! } - public var Wallet_Receive_Title: String { return self._s[1166]! } - public var Notifications_Badge_IncludePublicGroups: String { return self._s[1167]! } - public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1168]! } - public var PhotoEditor_CropReset: String { return self._s[1169]! } - public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1171]! } - public var Channel_Management_LabelEditor: String { return self._s[1172]! } - public var Passport_Identity_LatinNameHelp: String { return self._s[1174]! } - public var PhotoEditor_HighlightsTool: String { return self._s[1175]! } - public var Wallet_Info_WalletCreated: String { return self._s[1176]! } - public var UserInfo_Title: String { return self._s[1177]! } - public var ChatList_HideAction: String { return self._s[1178]! } - public var AccessDenied_Title: String { return self._s[1179]! } - public var DialogList_SearchLabel: String { return self._s[1180]! } - public var Group_Setup_HistoryHidden: String { return self._s[1181]! } - public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1182]! } - public var State_Updating: String { return self._s[1184]! } - public var Contacts_TabTitle: String { return self._s[1185]! } - public var Notifications_Badge_CountUnreadMessages: String { return self._s[1187]! } - public var GroupInfo_GroupHistory: String { return self._s[1188]! } - public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1189]! } - public var Wallpaper_SetColor: String { return self._s[1190]! } - public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1191]! } - public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1192]! } - public var Chat_AttachmentLimitReached: String { return self._s[1193]! } - public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1194]! } - public var Contacts_NotRegisteredSection: String { return self._s[1195]! } + public var VoiceOver_Navigation_ProxySettings: String { return self._s[1166]! } + public var Call_CallInProgressTitle: String { return self._s[1167]! } + public var Month_ShortSeptember: String { return self._s[1168]! } + public var Watch_ChannelInfo_Title: String { return self._s[1169]! } + public var ChatList_DeleteSavedMessagesConfirmation: String { return self._s[1172]! } + public var DialogList_PasscodeLockHelp: String { return self._s[1173]! } + public var Chat_MultipleTextMessagesDisabled: String { return self._s[1174]! } + public var Wallet_Receive_Title: String { return self._s[1175]! } + public var Notifications_Badge_IncludePublicGroups: String { return self._s[1176]! } + public var Channel_AdminLogFilter_EventsTitle: String { return self._s[1177]! } + public var PhotoEditor_CropReset: String { return self._s[1178]! } + public var Group_Username_CreatePrivateLinkHelp: String { return self._s[1180]! } + public var Channel_Management_LabelEditor: String { return self._s[1181]! } + public var Passport_Identity_LatinNameHelp: String { return self._s[1183]! } + public var PhotoEditor_HighlightsTool: String { return self._s[1184]! } + public var Wallet_Info_WalletCreated: String { return self._s[1185]! } + public var UserInfo_Title: String { return self._s[1186]! } + public var ChatList_HideAction: String { return self._s[1187]! } + public var AccessDenied_Title: String { return self._s[1188]! } + public var DialogList_SearchLabel: String { return self._s[1189]! } + public var Group_Setup_HistoryHidden: String { return self._s[1190]! } + public var TwoStepAuth_PasswordChangeSuccess: String { return self._s[1191]! } + public var State_Updating: String { return self._s[1193]! } + public var Contacts_TabTitle: String { return self._s[1194]! } + public var Notifications_Badge_CountUnreadMessages: String { return self._s[1196]! } + public var GroupInfo_GroupHistory: String { return self._s[1197]! } + public var Conversation_UnsupportedMediaPlaceholder: String { return self._s[1198]! } + public var Wallpaper_SetColor: String { return self._s[1199]! } + public var CheckoutInfo_ShippingInfoCountry: String { return self._s[1200]! } + public var SettingsSearch_Synonyms_SavedMessages: String { return self._s[1201]! } + public var Chat_AttachmentLimitReached: String { return self._s[1202]! } + public var Passport_Identity_OneOfTypeDriversLicense: String { return self._s[1203]! } + public var Contacts_NotRegisteredSection: String { return self._s[1204]! } public func Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1196]!, self._r[1196]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1205]!, self._r[1205]!, [_1, _2, _3]) } - public var Paint_Clear: String { return self._s[1197]! } - public var StickerPacksSettings_ArchivedMasks: String { return self._s[1198]! } - public var SocksProxySetup_Connecting: String { return self._s[1199]! } - public var ExplicitContent_AlertChannel: String { return self._s[1200]! } - public var CreatePoll_AllOptionsAdded: String { return self._s[1201]! } - public var Conversation_Contact: String { return self._s[1202]! } - public var Login_CodeExpired: String { return self._s[1203]! } - public var Passport_DiscardMessageAction: String { return self._s[1204]! } - public var ChatList_Context_Unpin: String { return self._s[1205]! } - public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1206]! } + public var Paint_Clear: String { return self._s[1206]! } + public var StickerPacksSettings_ArchivedMasks: String { return self._s[1207]! } + public var SocksProxySetup_Connecting: String { return self._s[1208]! } + public var ExplicitContent_AlertChannel: String { return self._s[1209]! } + public var CreatePoll_AllOptionsAdded: String { return self._s[1210]! } + public var Conversation_Contact: String { return self._s[1211]! } + public var Login_CodeExpired: String { return self._s[1212]! } + public var Passport_DiscardMessageAction: String { return self._s[1213]! } + public var ChatList_Context_Unpin: String { return self._s[1214]! } + public var Channel_AdminLog_MessagePreviousDescription: String { return self._s[1215]! } public func VoiceOver_Chat_MusicFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1207]!, self._r[1207]!, [_0]) + return formatWithArgumentRanges(self._s[1216]!, self._r[1216]!, [_0]) } - public var Channel_AdminLog_EmptyMessageText: String { return self._s[1208]! } - public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1209]! } + public var Channel_AdminLog_EmptyMessageText: String { return self._s[1217]! } + public var SettingsSearch_Synonyms_Data_NetworkUsage: String { return self._s[1218]! } public func Group_EditAdmin_RankInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1210]!, self._r[1210]!, [_0]) + return formatWithArgumentRanges(self._s[1219]!, self._r[1219]!, [_0]) } - public var Month_ShortApril: String { return self._s[1211]! } - public var AuthSessions_CurrentSession: String { return self._s[1212]! } - public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1215]! } - public var Wallet_Navigation_Cancel: String { return self._s[1217]! } - public var WallpaperPreview_CropTopText: String { return self._s[1218]! } - public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1219]! } - public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1220]! } + public var Month_ShortApril: String { return self._s[1220]! } + public var AuthSessions_CurrentSession: String { return self._s[1221]! } + public var Chat_AttachmentMultipleFilesDisabled: String { return self._s[1224]! } + public var Wallet_Navigation_Cancel: String { return self._s[1226]! } + public var WallpaperPreview_CropTopText: String { return self._s[1227]! } + public var PrivacySettings_DeleteAccountIfAwayFor: String { return self._s[1228]! } + public var CheckoutInfo_ShippingInfoTitle: String { return self._s[1229]! } public func Conversation_ScheduleMessage_SendOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1221]!, self._r[1221]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1230]!, self._r[1230]!, [_0, _1]) } - public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1222]! } - public var Channel_Setup_TypePrivate: String { return self._s[1224]! } - public var Forward_ChannelReadOnly: String { return self._s[1227]! } - public var PhotoEditor_CurvesBlue: String { return self._s[1228]! } - public var AddContact_SharedContactException: String { return self._s[1229]! } - public var UserInfo_BotPrivacy: String { return self._s[1231]! } - public var Wallet_CreateInvoice_Title: String { return self._s[1232]! } - public var Notification_PassportValueEmail: String { return self._s[1233]! } - public var EmptyGroupInfo_Subtitle: String { return self._s[1234]! } - public var GroupPermission_NewTitle: String { return self._s[1235]! } - public var CallFeedback_ReasonDropped: String { return self._s[1236]! } - public var GroupInfo_Permissions_AddException: String { return self._s[1237]! } - public var Channel_SignMessages_Help: String { return self._s[1239]! } - public var Undo_ChatDeleted: String { return self._s[1241]! } - public var Conversation_ChatBackground: String { return self._s[1242]! } + public var Appearance_ThemePreview_Chat_2_Text: String { return self._s[1231]! } + public var Channel_Setup_TypePrivate: String { return self._s[1233]! } + public var Forward_ChannelReadOnly: String { return self._s[1236]! } + public var PhotoEditor_CurvesBlue: String { return self._s[1237]! } + public var AddContact_SharedContactException: String { return self._s[1238]! } + public var UserInfo_BotPrivacy: String { return self._s[1240]! } + public var Wallet_CreateInvoice_Title: String { return self._s[1241]! } + public var Notification_PassportValueEmail: String { return self._s[1242]! } + public var EmptyGroupInfo_Subtitle: String { return self._s[1243]! } + public var GroupPermission_NewTitle: String { return self._s[1244]! } + public var CallFeedback_ReasonDropped: String { return self._s[1245]! } + public var GroupInfo_Permissions_AddException: String { return self._s[1246]! } + public var Channel_SignMessages_Help: String { return self._s[1248]! } + public var Undo_ChatDeleted: String { return self._s[1250]! } + public var Conversation_ChatBackground: String { return self._s[1251]! } public func Wallet_WordCheck_Text(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1243]!, self._r[1243]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1252]!, self._r[1252]!, [_1, _2, _3]) } - public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1244]! } - public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1245]! } - public var Passport_Language_pt: String { return self._s[1246]! } - public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1247]! } - public var NotificationsSound_Popcorn: String { return self._s[1250]! } - public var AutoNightTheme_Disabled: String { return self._s[1251]! } - public var BlockedUsers_LeavePrefix: String { return self._s[1252]! } - public var WallpaperPreview_CustomColorTopText: String { return self._s[1253]! } - public var Contacts_PermissionsSuppressWarningText: String { return self._s[1254]! } - public var WallpaperSearch_ColorBlue: String { return self._s[1255]! } + public var ChannelMembers_WhoCanAddMembers_Admins: String { return self._s[1253]! } + public var FastTwoStepSetup_EmailPlaceholder: String { return self._s[1254]! } + public var Passport_Language_pt: String { return self._s[1255]! } + public var VoiceOver_Chat_YourVoiceMessage: String { return self._s[1256]! } + public var NotificationsSound_Popcorn: String { return self._s[1259]! } + public var AutoNightTheme_Disabled: String { return self._s[1260]! } + public var BlockedUsers_LeavePrefix: String { return self._s[1261]! } + public var WallpaperPreview_CustomColorTopText: String { return self._s[1262]! } + public var Contacts_PermissionsSuppressWarningText: String { return self._s[1263]! } + public var WallpaperSearch_ColorBlue: String { return self._s[1264]! } public func CancelResetAccount_TextSMS(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1256]!, self._r[1256]!, [_0]) + return formatWithArgumentRanges(self._s[1265]!, self._r[1265]!, [_0]) } - public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1257]! } - public var SocksProxySetup_UseForCalls: String { return self._s[1258]! } - public var Passport_DeleteDocumentConfirmation: String { return self._s[1260]! } + public var CheckoutInfo_ErrorNameInvalid: String { return self._s[1266]! } + public var SocksProxySetup_UseForCalls: String { return self._s[1267]! } + public var Passport_DeleteDocumentConfirmation: String { return self._s[1269]! } public func Conversation_Megabytes(_ _0: Float) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1261]!, self._r[1261]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1270]!, self._r[1270]!, ["\(_0)"]) } - public var SocksProxySetup_Hostname: String { return self._s[1264]! } - public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1265]! } - public var Compose_NewEncryptedChat: String { return self._s[1266]! } - public var Login_CodeFloodError: String { return self._s[1267]! } - public var Calls_TabTitle: String { return self._s[1268]! } - public var Privacy_ProfilePhoto: String { return self._s[1269]! } - public var Passport_Language_he: String { return self._s[1270]! } + public var SocksProxySetup_Hostname: String { return self._s[1273]! } + public var ChatSettings_AutoDownloadSettings_OffForAll: String { return self._s[1274]! } + public var Compose_NewEncryptedChat: String { return self._s[1275]! } + public var Login_CodeFloodError: String { return self._s[1276]! } + public var Calls_TabTitle: String { return self._s[1277]! } + public var Privacy_ProfilePhoto: String { return self._s[1278]! } + public var Passport_Language_he: String { return self._s[1279]! } public func Conversation_SetReminder_RemindToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1271]!, self._r[1271]!, [_0]) + return formatWithArgumentRanges(self._s[1280]!, self._r[1280]!, [_0]) } - public var GroupPermission_Title: String { return self._s[1272]! } + public var GroupPermission_Title: String { return self._s[1281]! } public func Channel_AdminLog_MessageGroupPreHistoryHidden(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1273]!, self._r[1273]!, [_0]) + return formatWithArgumentRanges(self._s[1282]!, self._r[1282]!, [_0]) } - public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1274]! } - public var GroupPermission_NoChangeInfo: String { return self._s[1275]! } - public var ChatList_DeleteForCurrentUser: String { return self._s[1276]! } - public var Tour_Text1: String { return self._s[1277]! } - public var Channel_EditAdmin_TransferOwnership: String { return self._s[1278]! } - public var Month_ShortFebruary: String { return self._s[1279]! } - public var TwoStepAuth_EmailSkip: String { return self._s[1280]! } + public var Wallet_TransactionInfo_SenderHeader: String { return self._s[1283]! } + public var GroupPermission_NoChangeInfo: String { return self._s[1284]! } + public var ChatList_DeleteForCurrentUser: String { return self._s[1285]! } + public var Tour_Text1: String { return self._s[1286]! } + public var Channel_EditAdmin_TransferOwnership: String { return self._s[1287]! } + public var Month_ShortFebruary: String { return self._s[1288]! } + public var TwoStepAuth_EmailSkip: String { return self._s[1289]! } public func Wallet_Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1281]!, self._r[1281]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1290]!, self._r[1290]!, [_1, _2, _3]) } - public var NotificationsSound_Glass: String { return self._s[1282]! } - public var Appearance_ThemeNightBlue: String { return self._s[1283]! } - public var CheckoutInfo_Pay: String { return self._s[1284]! } - public var Invite_LargeRecipientsCountWarning: String { return self._s[1286]! } - public var Call_CallAgain: String { return self._s[1288]! } - public var AttachmentMenu_SendAsFile: String { return self._s[1289]! } - public var AccessDenied_MicrophoneRestricted: String { return self._s[1290]! } - public var Passport_InvalidPasswordError: String { return self._s[1291]! } - public var Watch_Message_Game: String { return self._s[1292]! } - public var Stickers_Install: String { return self._s[1293]! } - public var VoiceOver_Chat_Message: String { return self._s[1294]! } - public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1295]! } - public var Passport_Identity_ResidenceCountry: String { return self._s[1297]! } - public var Notifications_GroupNotificationsHelp: String { return self._s[1298]! } - public var AuthSessions_OtherSessions: String { return self._s[1299]! } - public var Channel_Username_Help: String { return self._s[1300]! } - public var Camera_Title: String { return self._s[1301]! } - public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1303]! } - public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1304]! } - public var Channel_AdminLog_SendPolls: String { return self._s[1305]! } - public var Channel_AdminLog_TitleAllEvents: String { return self._s[1306]! } - public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1307]! } - public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1308]! } - public var ScheduledMessages_DeleteMany: String { return self._s[1309]! } - public var Conversation_RestrictedStickers: String { return self._s[1310]! } - public var Notifications_ExceptionsResetToDefaults: String { return self._s[1312]! } - public var UserInfo_TelegramCall: String { return self._s[1314]! } - public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1315]! } - public var CreatePoll_OptionsHeader: String { return self._s[1316]! } - public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1317]! } - public var ArchivedChats_IntroTitle1: String { return self._s[1318]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1319]! } - public var Passport_Identity_EditPersonalDetails: String { return self._s[1320]! } + public var NotificationsSound_Glass: String { return self._s[1291]! } + public var Appearance_ThemeNightBlue: String { return self._s[1292]! } + public var CheckoutInfo_Pay: String { return self._s[1293]! } + public var Invite_LargeRecipientsCountWarning: String { return self._s[1295]! } + public var Call_CallAgain: String { return self._s[1297]! } + public var AttachmentMenu_SendAsFile: String { return self._s[1298]! } + public var AccessDenied_MicrophoneRestricted: String { return self._s[1299]! } + public var Passport_InvalidPasswordError: String { return self._s[1300]! } + public var Watch_Message_Game: String { return self._s[1301]! } + public var Stickers_Install: String { return self._s[1302]! } + public var VoiceOver_Chat_Message: String { return self._s[1303]! } + public var PrivacyLastSeenSettings_NeverShareWith: String { return self._s[1304]! } + public var Passport_Identity_ResidenceCountry: String { return self._s[1306]! } + public var Notifications_GroupNotificationsHelp: String { return self._s[1307]! } + public var AuthSessions_OtherSessions: String { return self._s[1308]! } + public var Channel_Username_Help: String { return self._s[1309]! } + public var Camera_Title: String { return self._s[1310]! } + public var GroupInfo_SetGroupPhotoDelete: String { return self._s[1312]! } + public var Privacy_ProfilePhoto_NeverShareWith_Title: String { return self._s[1313]! } + public var Channel_AdminLog_SendPolls: String { return self._s[1314]! } + public var Channel_AdminLog_TitleAllEvents: String { return self._s[1315]! } + public var Channel_EditAdmin_PermissionInviteMembers: String { return self._s[1316]! } + public var Contacts_MemberSearchSectionTitleGroup: String { return self._s[1317]! } + public var ScheduledMessages_DeleteMany: String { return self._s[1318]! } + public var Conversation_RestrictedStickers: String { return self._s[1319]! } + public var Notifications_ExceptionsResetToDefaults: String { return self._s[1321]! } + public var UserInfo_TelegramCall: String { return self._s[1323]! } + public var TwoStepAuth_SetupResendEmailCode: String { return self._s[1324]! } + public var CreatePoll_OptionsHeader: String { return self._s[1325]! } + public var SettingsSearch_Synonyms_Data_CallsUseLessData: String { return self._s[1326]! } + public var ArchivedChats_IntroTitle1: String { return self._s[1327]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Title: String { return self._s[1328]! } + public var Passport_Identity_EditPersonalDetails: String { return self._s[1329]! } public func Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1321]!, self._r[1321]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1330]!, self._r[1330]!, [_1, _2, _3]) } - public var Wallet_Month_GenAugust: String { return self._s[1322]! } - public var Settings_SaveEditedPhotos: String { return self._s[1323]! } - public var TwoStepAuth_ConfirmationTitle: String { return self._s[1324]! } - public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1325]! } - public var Conversation_MessageDialogRetry: String { return self._s[1326]! } - public var ChatList_Context_MarkAsUnread: String { return self._s[1327]! } - public var Conversation_DiscardVoiceMessageAction: String { return self._s[1328]! } - public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1329]! } - public var Group_Setup_TypeHeader: String { return self._s[1330]! } - public var Paint_RecentStickers: String { return self._s[1331]! } - public var PhotoEditor_GrainTool: String { return self._s[1332]! } - public var CheckoutInfo_ShippingInfoState: String { return self._s[1333]! } - public var EmptyGroupInfo_Line4: String { return self._s[1334]! } - public var Watch_AuthRequired: String { return self._s[1336]! } + public var Wallet_Month_GenAugust: String { return self._s[1331]! } + public var Settings_SaveEditedPhotos: String { return self._s[1332]! } + public var TwoStepAuth_ConfirmationTitle: String { return self._s[1333]! } + public var Privacy_GroupsAndChannels_NeverAllow_Title: String { return self._s[1334]! } + public var Conversation_MessageDialogRetry: String { return self._s[1335]! } + public var ChatList_Context_MarkAsUnread: String { return self._s[1336]! } + public var Conversation_DiscardVoiceMessageAction: String { return self._s[1337]! } + public var Permissions_PeopleNearbyTitle_v0: String { return self._s[1338]! } + public var Group_Setup_TypeHeader: String { return self._s[1339]! } + public var Paint_RecentStickers: String { return self._s[1340]! } + public var PhotoEditor_GrainTool: String { return self._s[1341]! } + public var CheckoutInfo_ShippingInfoState: String { return self._s[1342]! } + public var EmptyGroupInfo_Line4: String { return self._s[1343]! } + public var Watch_AuthRequired: String { return self._s[1345]! } public func Passport_Email_UseTelegramEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1337]!, self._r[1337]!, [_0]) + return formatWithArgumentRanges(self._s[1346]!, self._r[1346]!, [_0]) } - public var Conversation_EncryptedDescriptionTitle: String { return self._s[1338]! } - public var ChannelIntro_Text: String { return self._s[1339]! } - public var DialogList_DeleteBotConfirmation: String { return self._s[1340]! } - public var GroupPermission_NoSendMedia: String { return self._s[1341]! } - public var Calls_AddTab: String { return self._s[1342]! } - public var Message_ReplyActionButtonShowReceipt: String { return self._s[1343]! } - public var Channel_AdminLog_EmptyFilterText: String { return self._s[1344]! } - public var Conversation_WalletRequiredSetup: String { return self._s[1345]! } - public var Notification_MessageLifetime1d: String { return self._s[1346]! } - public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1347]! } - public var Channel_BanUser_PermissionsHeader: String { return self._s[1348]! } - public var Passport_Identity_GenderFemale: String { return self._s[1349]! } - public var BlockedUsers_BlockTitle: String { return self._s[1350]! } + public var Conversation_EncryptedDescriptionTitle: String { return self._s[1347]! } + public var ChannelIntro_Text: String { return self._s[1348]! } + public var DialogList_DeleteBotConfirmation: String { return self._s[1349]! } + public var GroupPermission_NoSendMedia: String { return self._s[1350]! } + public var Calls_AddTab: String { return self._s[1351]! } + public var Message_ReplyActionButtonShowReceipt: String { return self._s[1352]! } + public var Channel_AdminLog_EmptyFilterText: String { return self._s[1353]! } + public var Conversation_WalletRequiredSetup: String { return self._s[1354]! } + public var Notification_MessageLifetime1d: String { return self._s[1355]! } + public var Notifications_ChannelNotificationsExceptionsHelp: String { return self._s[1356]! } + public var Channel_BanUser_PermissionsHeader: String { return self._s[1357]! } + public var Passport_Identity_GenderFemale: String { return self._s[1358]! } + public var BlockedUsers_BlockTitle: String { return self._s[1359]! } public func PUSH_CHANNEL_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1351]!, self._r[1351]!, [_1]) + return formatWithArgumentRanges(self._s[1360]!, self._r[1360]!, [_1]) } - public var Weekday_Yesterday: String { return self._s[1352]! } - public var WallpaperSearch_ColorBlack: String { return self._s[1353]! } - public var Settings_Context_Logout: String { return self._s[1354]! } - public var Wallet_Info_UnknownTransaction: String { return self._s[1355]! } - public var ChatList_ArchiveAction: String { return self._s[1356]! } - public var AutoNightTheme_Scheduled: String { return self._s[1357]! } + public var Weekday_Yesterday: String { return self._s[1361]! } + public var WallpaperSearch_ColorBlack: String { return self._s[1362]! } + public var Settings_Context_Logout: String { return self._s[1363]! } + public var Wallet_Info_UnknownTransaction: String { return self._s[1364]! } + public var ChatList_ArchiveAction: String { return self._s[1365]! } + public var AutoNightTheme_Scheduled: String { return self._s[1366]! } + public var TwoFactorSetup_Email_SkipAction: String { return self._s[1367]! } public func Login_PhoneGenericEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String, _ _6: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1358]!, self._r[1358]!, [_1, _2, _3, _4, _5, _6]) + return formatWithArgumentRanges(self._s[1368]!, self._r[1368]!, [_1, _2, _3, _4, _5, _6]) } - public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1359]! } - public var Wallet_Receive_CreateInvoice: String { return self._s[1360]! } - public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1361]! } + public var EditTheme_ThemeTemplateAlertTitle: String { return self._s[1369]! } + public var Wallet_Receive_CreateInvoice: String { return self._s[1370]! } + public var PrivacyPolicy_DeclineDeleteNow: String { return self._s[1371]! } public func PUSH_CHAT_JOINED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1362]!, self._r[1362]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1372]!, self._r[1372]!, [_1, _2]) } - public var CreatePoll_Create: String { return self._s[1363]! } - public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1364]! } + public var CreatePoll_Create: String { return self._s[1373]! } + public var Channel_Members_AddBannedErrorAdmin: String { return self._s[1374]! } public func Notification_CallFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1365]!, self._r[1365]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1375]!, self._r[1375]!, [_1, _2]) } - public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1366]! } - public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1367]! } - public var Notifications_InAppNotificationsSounds: String { return self._s[1369]! } + public var ScheduledMessages_ClearAllConfirmation: String { return self._s[1376]! } + public var Checkout_ErrorProviderAccountInvalid: String { return self._s[1377]! } + public var Notifications_InAppNotificationsSounds: String { return self._s[1379]! } public func PUSH_PINNED_GAME_SCORE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1370]!, self._r[1370]!, [_1]) + return formatWithArgumentRanges(self._s[1380]!, self._r[1380]!, [_1]) } - public var Preview_OpenInInstagram: String { return self._s[1371]! } - public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1372]! } + public var Preview_OpenInInstagram: String { return self._s[1381]! } + public var Notification_MessageLifetimeRemovedOutgoing: String { return self._s[1382]! } public func PUSH_CHAT_ADD_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1373]!, self._r[1373]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1383]!, self._r[1383]!, [_1, _2, _3]) } public func Passport_PrivacyPolicy(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1374]!, self._r[1374]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1384]!, self._r[1384]!, [_1, _2]) } - public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1375]! } - public var ArchivedChats_IntroText3: String { return self._s[1376]! } - public var ChatList_UndoArchiveHiddenText: String { return self._s[1377]! } - public var NetworkUsageSettings_TotalSection: String { return self._s[1378]! } - public var Wallet_Month_GenSeptember: String { return self._s[1379]! } - public var Channel_Setup_TypePrivateHelp: String { return self._s[1380]! } + public var Channel_AdminLog_InfoPanelAlertTitle: String { return self._s[1385]! } + public var ArchivedChats_IntroText3: String { return self._s[1386]! } + public var ChatList_UndoArchiveHiddenText: String { return self._s[1387]! } + public var NetworkUsageSettings_TotalSection: String { return self._s[1388]! } + public var Wallet_Month_GenSeptember: String { return self._s[1389]! } + public var Channel_Setup_TypePrivateHelp: String { return self._s[1390]! } public func PUSH_CHAT_MESSAGE_POLL(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1381]!, self._r[1381]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1391]!, self._r[1391]!, [_1, _2, _3]) } - public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1383]! } - public var FastTwoStepSetup_HintSection: String { return self._s[1384]! } - public var Wallpaper_PhotoLibrary: String { return self._s[1385]! } - public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1386]! } - public var Gif_NoGifsFound: String { return self._s[1387]! } - public var Watch_LastSeen_WithinAMonth: String { return self._s[1388]! } - public var VoiceOver_MessageContextDelete: String { return self._s[1389]! } - public var EditTheme_Preview: String { return self._s[1390]! } - public var GroupInfo_ActionPromote: String { return self._s[1391]! } - public var PasscodeSettings_SimplePasscode: String { return self._s[1392]! } - public var GroupInfo_Permissions_Title: String { return self._s[1393]! } - public var Permissions_ContactsText_v0: String { return self._s[1394]! } - public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1395]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1396]! } - public var PrivacySettings_DataSettingsHelp: String { return self._s[1399]! } - public var Passport_FieldEmailHelp: String { return self._s[1400]! } + public var Privacy_GroupsAndChannels_NeverAllow_Placeholder: String { return self._s[1393]! } + public var FastTwoStepSetup_HintSection: String { return self._s[1394]! } + public var Wallpaper_PhotoLibrary: String { return self._s[1395]! } + public var TwoStepAuth_SetupResendEmailCodeAlert: String { return self._s[1396]! } + public var Gif_NoGifsFound: String { return self._s[1397]! } + public var Watch_LastSeen_WithinAMonth: String { return self._s[1398]! } + public var VoiceOver_MessageContextDelete: String { return self._s[1399]! } + public var EditTheme_Preview: String { return self._s[1400]! } + public var GroupInfo_ActionPromote: String { return self._s[1401]! } + public var PasscodeSettings_SimplePasscode: String { return self._s[1402]! } + public var GroupInfo_Permissions_Title: String { return self._s[1403]! } + public var Permissions_ContactsText_v0: String { return self._s[1404]! } + public var PrivacyPhoneNumberSettings_CustomDisabledHelp: String { return self._s[1405]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedPublicGroups: String { return self._s[1406]! } + public var PrivacySettings_DataSettingsHelp: String { return self._s[1409]! } + public var Passport_FieldEmailHelp: String { return self._s[1410]! } public func Activity_RemindAboutUser(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1401]!, self._r[1401]!, [_0]) + return formatWithArgumentRanges(self._s[1411]!, self._r[1411]!, [_0]) } - public var Passport_Identity_GenderPlaceholder: String { return self._s[1402]! } - public var Weekday_ShortSaturday: String { return self._s[1403]! } - public var ContactInfo_PhoneLabelMain: String { return self._s[1404]! } - public var Watch_Conversation_UserInfo: String { return self._s[1405]! } - public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1406]! } - public var PrivacyLastSeenSettings_Title: String { return self._s[1407]! } - public var Conversation_ShareBotLocationConfirmation: String { return self._s[1408]! } - public var PhotoEditor_VignetteTool: String { return self._s[1409]! } - public var Passport_Address_Street1Placeholder: String { return self._s[1410]! } - public var Passport_Language_et: String { return self._s[1411]! } - public var AppUpgrade_Running: String { return self._s[1412]! } - public var Channel_DiscussionGroup_Info: String { return self._s[1414]! } - public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1415]! } - public var Passport_Language_bg: String { return self._s[1416]! } - public var Stickers_NoStickersFound: String { return self._s[1418]! } + public var Passport_Identity_GenderPlaceholder: String { return self._s[1412]! } + public var Weekday_ShortSaturday: String { return self._s[1413]! } + public var ContactInfo_PhoneLabelMain: String { return self._s[1414]! } + public var Watch_Conversation_UserInfo: String { return self._s[1415]! } + public var CheckoutInfo_ShippingInfoCityPlaceholder: String { return self._s[1416]! } + public var PrivacyLastSeenSettings_Title: String { return self._s[1417]! } + public var Conversation_ShareBotLocationConfirmation: String { return self._s[1418]! } + public var PhotoEditor_VignetteTool: String { return self._s[1419]! } + public var Passport_Address_Street1Placeholder: String { return self._s[1420]! } + public var Passport_Language_et: String { return self._s[1421]! } + public var AppUpgrade_Running: String { return self._s[1422]! } + public var Channel_DiscussionGroup_Info: String { return self._s[1424]! } + public var EditTheme_Create_Preview_IncomingReplyName: String { return self._s[1425]! } + public var Passport_Language_bg: String { return self._s[1426]! } + public var Stickers_NoStickersFound: String { return self._s[1428]! } public func PUSH_CHANNEL_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1420]!, self._r[1420]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1430]!, self._r[1430]!, [_1, _2]) } public func VoiceOver_Chat_ContactFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1421]!, self._r[1421]!, [_0]) - } - public var Wallet_Month_GenJuly: String { return self._s[1422]! } - public var Wallet_Receive_AddressHeader: String { return self._s[1423]! } - public var Wallet_Send_AmountText: String { return self._s[1424]! } - public var Settings_About: String { return self._s[1425]! } - public func Channel_AdminLog_MessageRestricted(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1426]!, self._r[1426]!, [_0, _1, _2]) - } - public var ChatList_Context_MarkAsRead: String { return self._s[1428]! } - public var KeyCommand_NewMessage: String { return self._s[1429]! } - public var Group_ErrorAddBlocked: String { return self._s[1430]! } - public func Message_PaymentSent(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[1431]!, self._r[1431]!, [_0]) } - public var Map_LocationTitle: String { return self._s[1432]! } - public var ReportGroupLocation_Title: String { return self._s[1433]! } - public var CallSettings_UseLessDataLongDescription: String { return self._s[1434]! } - public var Cache_ClearProgress: String { return self._s[1435]! } + public var Wallet_Month_GenJuly: String { return self._s[1432]! } + public var Wallet_Receive_AddressHeader: String { return self._s[1433]! } + public var Wallet_Send_AmountText: String { return self._s[1434]! } + public var Settings_About: String { return self._s[1435]! } + public func Channel_AdminLog_MessageRestricted(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1436]!, self._r[1436]!, [_0, _1, _2]) + } + public var ChatList_Context_MarkAsRead: String { return self._s[1438]! } + public var KeyCommand_NewMessage: String { return self._s[1439]! } + public var Group_ErrorAddBlocked: String { return self._s[1440]! } + public func Message_PaymentSent(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[1441]!, self._r[1441]!, [_0]) + } + public var Map_LocationTitle: String { return self._s[1442]! } + public var ReportGroupLocation_Title: String { return self._s[1443]! } + public var CallSettings_UseLessDataLongDescription: String { return self._s[1444]! } + public var Cache_ClearProgress: String { return self._s[1445]! } public func Channel_Management_ErrorNotMember(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1436]!, self._r[1436]!, [_0]) + return formatWithArgumentRanges(self._s[1446]!, self._r[1446]!, [_0]) } - public var GroupRemoved_AddToGroup: String { return self._s[1437]! } - public var Passport_UpdateRequiredError: String { return self._s[1438]! } - public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1439]! } + public var GroupRemoved_AddToGroup: String { return self._s[1447]! } + public var Passport_UpdateRequiredError: String { return self._s[1448]! } + public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[1449]! } public func PUSH_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1440]!, self._r[1440]!, [_1]) + return formatWithArgumentRanges(self._s[1450]!, self._r[1450]!, [_1]) } - public var Notifications_PermissionsSuppressWarningText: String { return self._s[1442]! } - public var Passport_Identity_MainPageHelp: String { return self._s[1443]! } - public var Conversation_StatusKickedFromGroup: String { return self._s[1444]! } - public var Passport_Language_ka: String { return self._s[1445]! } + public var Notifications_PermissionsSuppressWarningText: String { return self._s[1452]! } + public var Passport_Identity_MainPageHelp: String { return self._s[1453]! } + public var Conversation_StatusKickedFromGroup: String { return self._s[1454]! } + public var Passport_Language_ka: String { return self._s[1455]! } public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1446]!, self._r[1446]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1456]!, self._r[1456]!, [_1, _2, _3]) } - public var Call_Decline: String { return self._s[1447]! } - public var SocksProxySetup_ProxyEnabled: String { return self._s[1448]! } + public var Call_Decline: String { return self._s[1457]! } + public var SocksProxySetup_ProxyEnabled: String { return self._s[1458]! } + public var TwoFactorSetup_Email_SkipConfirmationText: String { return self._s[1461]! } public func AuthCode_Alert(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1451]!, self._r[1451]!, [_0]) + return formatWithArgumentRanges(self._s[1462]!, self._r[1462]!, [_0]) } - public var CallFeedback_Send: String { return self._s[1452]! } - public var EditTheme_EditTitle: String { return self._s[1453]! } + public var CallFeedback_Send: String { return self._s[1463]! } + public var EditTheme_EditTitle: String { return self._s[1464]! } public func Channel_AdminLog_MessagePromotedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1454]!, self._r[1454]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1465]!, self._r[1465]!, [_1, _2]) } - public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1455]! } + public var Passport_Phone_UseTelegramNumberHelp: String { return self._s[1466]! } public func Wallet_Updated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1457]!, self._r[1457]!, [_0]) + return formatWithArgumentRanges(self._s[1468]!, self._r[1468]!, [_0]) } - public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1458]! } - public var Passport_DeletePassport: String { return self._s[1459]! } - public var Appearance_AppIconFilled: String { return self._s[1460]! } - public var Privacy_Calls_P2PAlways: String { return self._s[1461]! } - public var Month_ShortDecember: String { return self._s[1462]! } - public var Channel_AdminLog_CanEditMessages: String { return self._s[1464]! } + public var SettingsSearch_Synonyms_Data_Title: String { return self._s[1469]! } + public var Passport_DeletePassport: String { return self._s[1470]! } + public var Appearance_AppIconFilled: String { return self._s[1471]! } + public var Privacy_Calls_P2PAlways: String { return self._s[1472]! } + public var Month_ShortDecember: String { return self._s[1473]! } + public var Channel_AdminLog_CanEditMessages: String { return self._s[1475]! } public func Contacts_AccessDeniedHelpLandscape(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1465]!, self._r[1465]!, [_0]) + return formatWithArgumentRanges(self._s[1476]!, self._r[1476]!, [_0]) } - public var Channel_Stickers_Searching: String { return self._s[1466]! } - public var Conversation_EncryptedDescription1: String { return self._s[1467]! } - public var Conversation_EncryptedDescription2: String { return self._s[1468]! } - public var PasscodeSettings_PasscodeOptions: String { return self._s[1469]! } - public var Conversation_EncryptedDescription3: String { return self._s[1471]! } - public var PhotoEditor_SharpenTool: String { return self._s[1472]! } - public var Wallet_Configuration_Title: String { return self._s[1473]! } + public var Channel_Stickers_Searching: String { return self._s[1477]! } + public var Conversation_EncryptedDescription1: String { return self._s[1478]! } + public var Conversation_EncryptedDescription2: String { return self._s[1479]! } + public var PasscodeSettings_PasscodeOptions: String { return self._s[1480]! } + public var Conversation_EncryptedDescription3: String { return self._s[1482]! } + public var PhotoEditor_SharpenTool: String { return self._s[1483]! } + public var Wallet_Configuration_Title: String { return self._s[1484]! } public func Conversation_AddNameToContacts(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1474]!, self._r[1474]!, [_0]) + return formatWithArgumentRanges(self._s[1485]!, self._r[1485]!, [_0]) } - public var Conversation_EncryptedDescription4: String { return self._s[1476]! } - public var Channel_Members_AddMembers: String { return self._s[1477]! } - public var Wallpaper_Search: String { return self._s[1478]! } - public var Weekday_Friday: String { return self._s[1479]! } - public var Privacy_ContactsSync: String { return self._s[1480]! } - public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1481]! } - public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1482]! } + public var Conversation_EncryptedDescription4: String { return self._s[1487]! } + public var Channel_Members_AddMembers: String { return self._s[1488]! } + public var Wallpaper_Search: String { return self._s[1489]! } + public var Weekday_Friday: String { return self._s[1490]! } + public var Privacy_ContactsSync: String { return self._s[1491]! } + public var SettingsSearch_Synonyms_Privacy_Data_ContactsReset: String { return self._s[1492]! } + public var ApplyLanguage_ChangeLanguageAction: String { return self._s[1493]! } public func Channel_Management_RestrictedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1483]!, self._r[1483]!, [_0]) + return formatWithArgumentRanges(self._s[1494]!, self._r[1494]!, [_0]) } - public var GroupInfo_Permissions_Removed: String { return self._s[1484]! } - public var Passport_Identity_GenderMale: String { return self._s[1485]! } + public var GroupInfo_Permissions_Removed: String { return self._s[1495]! } + public var ScheduledMessages_ScheduledOnline: String { return self._s[1496]! } + public var Passport_Identity_GenderMale: String { return self._s[1497]! } public func Call_StatusBar(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1486]!, self._r[1486]!, [_0]) + return formatWithArgumentRanges(self._s[1498]!, self._r[1498]!, [_0]) } - public var Notifications_PermissionsKeepDisabled: String { return self._s[1487]! } - public var Conversation_JumpToDate: String { return self._s[1488]! } - public var Contacts_GlobalSearch: String { return self._s[1489]! } - public var AutoDownloadSettings_ResetHelp: String { return self._s[1490]! } - public var SettingsSearch_Synonyms_FAQ: String { return self._s[1491]! } - public var Profile_MessageLifetime1d: String { return self._s[1492]! } + public var Notifications_PermissionsKeepDisabled: String { return self._s[1499]! } + public var Conversation_JumpToDate: String { return self._s[1500]! } + public var Contacts_GlobalSearch: String { return self._s[1501]! } + public var AutoDownloadSettings_ResetHelp: String { return self._s[1502]! } + public var SettingsSearch_Synonyms_FAQ: String { return self._s[1503]! } + public var Profile_MessageLifetime1d: String { return self._s[1504]! } public func MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1493]!, self._r[1493]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1505]!, self._r[1505]!, [_1, _2]) } - public var StickerPack_BuiltinPackName: String { return self._s[1496]! } + public var StickerPack_BuiltinPackName: String { return self._s[1508]! } public func PUSH_CHAT_MESSAGE_AUDIO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1497]!, self._r[1497]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1509]!, self._r[1509]!, [_1, _2]) } - public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1498]! } - public var Passport_InfoTitle: String { return self._s[1500]! } - public var Notifications_PermissionsUnreachableText: String { return self._s[1501]! } + public var VoiceOver_Chat_RecordModeVoiceMessageInfo: String { return self._s[1510]! } + public var Passport_InfoTitle: String { return self._s[1512]! } + public var Notifications_PermissionsUnreachableText: String { return self._s[1513]! } public func NetworkUsageSettings_CellularUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1505]!, self._r[1505]!, [_0]) + return formatWithArgumentRanges(self._s[1517]!, self._r[1517]!, [_0]) } public func PUSH_CHAT_MESSAGE_GEO(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1506]!, self._r[1506]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1518]!, self._r[1518]!, [_1, _2]) } - public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1507]! } - public var Profile_BotInfo: String { return self._s[1508]! } - public var Watch_Compose_CreateMessage: String { return self._s[1509]! } - public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1510]! } - public var Month_ShortNovember: String { return self._s[1511]! } - public var Conversation_ScamWarning: String { return self._s[1512]! } - public var Wallpaper_SetCustomBackground: String { return self._s[1513]! } - public var Passport_Identity_TranslationsHelp: String { return self._s[1514]! } - public var NotificationsSound_Chime: String { return self._s[1515]! } - public var Passport_Language_ko: String { return self._s[1517]! } - public var InviteText_URL: String { return self._s[1518]! } - public var TextFormat_Monospace: String { return self._s[1519]! } + public var Passport_Address_TypePassportRegistrationUploadScan: String { return self._s[1519]! } + public var Profile_BotInfo: String { return self._s[1520]! } + public var Watch_Compose_CreateMessage: String { return self._s[1521]! } + public var AutoDownloadSettings_VoiceMessagesInfo: String { return self._s[1522]! } + public var Month_ShortNovember: String { return self._s[1523]! } + public var Conversation_ScamWarning: String { return self._s[1524]! } + public var Wallpaper_SetCustomBackground: String { return self._s[1525]! } + public var Passport_Identity_TranslationsHelp: String { return self._s[1526]! } + public var NotificationsSound_Chime: String { return self._s[1527]! } + public var Passport_Language_ko: String { return self._s[1529]! } + public var InviteText_URL: String { return self._s[1530]! } + public var TextFormat_Monospace: String { return self._s[1531]! } public func Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1520]!, self._r[1520]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1532]!, self._r[1532]!, [_1, _2, _3]) } - public var EditTheme_Edit_BottomInfo: String { return self._s[1521]! } + public var EditTheme_Edit_BottomInfo: String { return self._s[1533]! } public func Login_WillSendSms(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1522]!, self._r[1522]!, [_0]) + return formatWithArgumentRanges(self._s[1534]!, self._r[1534]!, [_0]) } public func Watch_Time_ShortWeekdayAt(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1523]!, self._r[1523]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1535]!, self._r[1535]!, [_1, _2]) } - public var Wallet_Words_Title: String { return self._s[1524]! } - public var Wallet_Month_ShortMay: String { return self._s[1525]! } - public var EditTheme_CreateTitle: String { return self._s[1527]! } - public var Passport_InfoLearnMore: String { return self._s[1528]! } - public var TwoStepAuth_EmailPlaceholder: String { return self._s[1529]! } - public var Passport_Identity_AddIdentityCard: String { return self._s[1530]! } - public var Your_card_has_expired: String { return self._s[1531]! } - public var StickerPacksSettings_StickerPacksSection: String { return self._s[1532]! } - public var GroupInfo_InviteLink_Help: String { return self._s[1533]! } - public var Conversation_Report: String { return self._s[1537]! } - public var Notifications_MessageNotificationsSound: String { return self._s[1538]! } - public var Notification_MessageLifetime1m: String { return self._s[1539]! } - public var Privacy_ContactsTitle: String { return self._s[1540]! } - public var Conversation_ShareMyContactInfo: String { return self._s[1541]! } - public var Wallet_WordCheck_Title: String { return self._s[1542]! } - public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1543]! } - public var Channel_Members_Title: String { return self._s[1544]! } - public var Map_OpenInWaze: String { return self._s[1545]! } - public var Login_PhoneBannedError: String { return self._s[1546]! } + public var Wallet_Words_Title: String { return self._s[1536]! } + public var Wallet_Month_ShortMay: String { return self._s[1537]! } + public var EditTheme_CreateTitle: String { return self._s[1539]! } + public var Passport_InfoLearnMore: String { return self._s[1540]! } + public var TwoStepAuth_EmailPlaceholder: String { return self._s[1541]! } + public var Passport_Identity_AddIdentityCard: String { return self._s[1542]! } + public var Your_card_has_expired: String { return self._s[1543]! } + public var StickerPacksSettings_StickerPacksSection: String { return self._s[1544]! } + public var GroupInfo_InviteLink_Help: String { return self._s[1545]! } + public var TwoFactorSetup_EmailVerification_ResendAction: String { return self._s[1549]! } + public var Conversation_Report: String { return self._s[1550]! } + public var Notifications_MessageNotificationsSound: String { return self._s[1551]! } + public var Notification_MessageLifetime1m: String { return self._s[1552]! } + public var Privacy_ContactsTitle: String { return self._s[1553]! } + public var Conversation_ShareMyContactInfo: String { return self._s[1554]! } + public var Wallet_WordCheck_Title: String { return self._s[1555]! } + public var ChannelMembers_WhoCanAddMembersAdminsHelp: String { return self._s[1556]! } + public var Channel_Members_Title: String { return self._s[1557]! } + public var Map_OpenInWaze: String { return self._s[1558]! } + public var Login_PhoneBannedError: String { return self._s[1559]! } public func LiveLocationUpdated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1547]!, self._r[1547]!, [_0]) + return formatWithArgumentRanges(self._s[1560]!, self._r[1560]!, [_0]) } - public var Group_Management_AddModeratorHelp: String { return self._s[1548]! } - public var AutoDownloadSettings_WifiTitle: String { return self._s[1549]! } - public var Common_OK: String { return self._s[1550]! } - public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1551]! } - public var Wallet_Words_NotDoneResponse: String { return self._s[1552]! } - public var Cache_Music: String { return self._s[1553]! } - public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1554]! } - public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1555]! } - public var TwoStepAuth_HintPlaceholder: String { return self._s[1556]! } + public var Group_Management_AddModeratorHelp: String { return self._s[1561]! } + public var AutoDownloadSettings_WifiTitle: String { return self._s[1562]! } + public var Common_OK: String { return self._s[1563]! } + public var Passport_Address_TypeBankStatementUploadScan: String { return self._s[1564]! } + public var Wallet_Words_NotDoneResponse: String { return self._s[1565]! } + public var Cache_Music: String { return self._s[1566]! } + public var SettingsSearch_Synonyms_EditProfile_PhoneNumber: String { return self._s[1567]! } + public var PasscodeSettings_UnlockWithTouchId: String { return self._s[1568]! } + public var TwoStepAuth_HintPlaceholder: String { return self._s[1569]! } public func PUSH_PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1557]!, self._r[1557]!, [_1]) + return formatWithArgumentRanges(self._s[1570]!, self._r[1570]!, [_1]) } public func Passport_RequestHeader(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1558]!, self._r[1558]!, [_0]) + return formatWithArgumentRanges(self._s[1571]!, self._r[1571]!, [_0]) } + public var TwoFactorSetup_Done_Action: String { return self._s[1572]! } public func VoiceOver_Chat_ContactOrganization(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1559]!, self._r[1559]!, [_0]) + return formatWithArgumentRanges(self._s[1573]!, self._r[1573]!, [_0]) } - public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1560]! } - public var Watch_MessageView_ViewOnPhone: String { return self._s[1562]! } - public var Privacy_Calls_CustomShareHelp: String { return self._s[1563]! } - public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1565]! } - public var ChangePhoneNumberNumber_Title: String { return self._s[1566]! } - public var State_ConnectingToProxyInfo: String { return self._s[1567]! } - public var Message_VideoMessage: String { return self._s[1569]! } - public var ChannelInfo_DeleteChannel: String { return self._s[1570]! } - public var ContactInfo_PhoneLabelOther: String { return self._s[1571]! } - public var Channel_EditAdmin_CannotEdit: String { return self._s[1572]! } - public var Passport_DeleteAddressConfirmation: String { return self._s[1573]! } + public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[1574]! } + public var Watch_MessageView_ViewOnPhone: String { return self._s[1576]! } + public var Privacy_Calls_CustomShareHelp: String { return self._s[1577]! } + public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[1579]! } + public var ChangePhoneNumberNumber_Title: String { return self._s[1580]! } + public var State_ConnectingToProxyInfo: String { return self._s[1581]! } + public var Conversation_SwipeToReplyHintTitle: String { return self._s[1582]! } + public var Message_VideoMessage: String { return self._s[1584]! } + public var ChannelInfo_DeleteChannel: String { return self._s[1585]! } + public var ContactInfo_PhoneLabelOther: String { return self._s[1586]! } + public var Channel_EditAdmin_CannotEdit: String { return self._s[1587]! } + public var Passport_DeleteAddressConfirmation: String { return self._s[1588]! } public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1574]!, self._r[1574]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1589]!, self._r[1589]!, [_1, _2, _3]) } - public var WallpaperPreview_SwipeBottomText: String { return self._s[1575]! } - public var Activity_RecordingAudio: String { return self._s[1576]! } - public var SettingsSearch_Synonyms_Watch: String { return self._s[1577]! } - public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1578]! } - public var Wallet_Info_Address: String { return self._s[1579]! } + public var WallpaperPreview_SwipeBottomText: String { return self._s[1590]! } + public var Activity_RecordingAudio: String { return self._s[1591]! } + public var SettingsSearch_Synonyms_Watch: String { return self._s[1592]! } + public var PasscodeSettings_TryAgainIn1Minute: String { return self._s[1593]! } + public var Wallet_Info_Address: String { return self._s[1594]! } public func Notification_ChangedGroupName(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1581]!, self._r[1581]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1596]!, self._r[1596]!, [_0, _1]) } public func EmptyGroupInfo_Line1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1585]!, self._r[1585]!, [_0]) + return formatWithArgumentRanges(self._s[1600]!, self._r[1600]!, [_0]) } - public var Conversation_ApplyLocalization: String { return self._s[1586]! } - public var UserInfo_AddPhone: String { return self._s[1587]! } - public var Map_ShareLiveLocationHelp: String { return self._s[1588]! } + public var Conversation_ApplyLocalization: String { return self._s[1601]! } + public var TwoFactorSetup_Intro_Action: String { return self._s[1602]! } + public var UserInfo_AddPhone: String { return self._s[1603]! } + public var Map_ShareLiveLocationHelp: String { return self._s[1604]! } public func Passport_Identity_NativeNameGenericHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1589]!, self._r[1589]!, [_0]) + return formatWithArgumentRanges(self._s[1605]!, self._r[1605]!, [_0]) } - public var Passport_Scans: String { return self._s[1591]! } - public var BlockedUsers_Unblock: String { return self._s[1592]! } + public var Passport_Scans: String { return self._s[1607]! } + public var BlockedUsers_Unblock: String { return self._s[1608]! } public func PUSH_ENCRYPTION_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1593]!, self._r[1593]!, [_1]) + return formatWithArgumentRanges(self._s[1609]!, self._r[1609]!, [_1]) } - public var Channel_Management_LabelCreator: String { return self._s[1594]! } - public var Conversation_ReportSpamAndLeave: String { return self._s[1595]! } - public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1596]! } - public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1597]! } - public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1598]! } + public var Channel_Management_LabelCreator: String { return self._s[1610]! } + public var Conversation_ReportSpamAndLeave: String { return self._s[1611]! } + public var SettingsSearch_Synonyms_EditProfile_Bio: String { return self._s[1612]! } + public var ChatList_UndoArchiveMultipleTitle: String { return self._s[1613]! } + public var Passport_Identity_NativeNameGenericTitle: String { return self._s[1614]! } public func Login_EmailPhoneBody(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1599]!, self._r[1599]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[1615]!, self._r[1615]!, [_0, _1, _2]) } - public var Login_PhoneNumberHelp: String { return self._s[1600]! } - public var LastSeen_ALongTimeAgo: String { return self._s[1601]! } - public var Channel_AdminLog_CanPinMessages: String { return self._s[1602]! } - public var ChannelIntro_CreateChannel: String { return self._s[1603]! } - public var Conversation_UnreadMessages: String { return self._s[1604]! } - public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1605]! } - public var Channel_AdminLog_EmptyText: String { return self._s[1606]! } - public var Theme_Context_Apply: String { return self._s[1607]! } - public var Notification_GroupActivated: String { return self._s[1608]! } - public var NotificationSettings_ContactJoinedInfo: String { return self._s[1609]! } - public var Wallet_Intro_CreateWallet: String { return self._s[1610]! } + public var Login_PhoneNumberHelp: String { return self._s[1616]! } + public var LastSeen_ALongTimeAgo: String { return self._s[1617]! } + public var Channel_AdminLog_CanPinMessages: String { return self._s[1618]! } + public var ChannelIntro_CreateChannel: String { return self._s[1619]! } + public var Conversation_UnreadMessages: String { return self._s[1620]! } + public var SettingsSearch_Synonyms_Stickers_ArchivedPacks: String { return self._s[1621]! } + public var Channel_AdminLog_EmptyText: String { return self._s[1622]! } + public var Theme_Context_Apply: String { return self._s[1623]! } + public var Notification_GroupActivated: String { return self._s[1624]! } + public var NotificationSettings_ContactJoinedInfo: String { return self._s[1625]! } + public var Wallet_Intro_CreateWallet: String { return self._s[1626]! } public func Notification_PinnedContactMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1611]!, self._r[1611]!, [_0]) + return formatWithArgumentRanges(self._s[1627]!, self._r[1627]!, [_0]) } public func DownloadingStatus(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1612]!, self._r[1612]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1628]!, self._r[1628]!, [_0, _1]) } - public var GroupInfo_ConvertToSupergroup: String { return self._s[1614]! } + public var GroupInfo_ConvertToSupergroup: String { return self._s[1630]! } public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1615]!, self._r[1615]!, [_0]) + return formatWithArgumentRanges(self._s[1631]!, self._r[1631]!, [_0]) } - public var Undo_DeletedChannel: String { return self._s[1616]! } - public var CallFeedback_AddComment: String { return self._s[1617]! } + public var Undo_DeletedChannel: String { return self._s[1632]! } + public var CallFeedback_AddComment: String { return self._s[1633]! } public func Conversation_OpenBotLinkAllowMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1618]!, self._r[1618]!, [_0]) + return formatWithArgumentRanges(self._s[1634]!, self._r[1634]!, [_0]) } - public var Document_TargetConfirmationFormat: String { return self._s[1619]! } + public var Document_TargetConfirmationFormat: String { return self._s[1635]! } public func Call_StatusOngoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1620]!, self._r[1620]!, [_0]) + return formatWithArgumentRanges(self._s[1636]!, self._r[1636]!, [_0]) } - public var LogoutOptions_SetPasscodeTitle: String { return self._s[1621]! } + public var LogoutOptions_SetPasscodeTitle: String { return self._s[1637]! } public func PUSH_CHAT_MESSAGE_GAME_SCORE(_ _1: String, _ _2: String, _ _3: String, _ _4: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1622]!, self._r[1622]!, [_1, _2, _3, _4]) + return formatWithArgumentRanges(self._s[1638]!, self._r[1638]!, [_1, _2, _3, _4]) } - public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1623]! } - public var Theme_ErrorNotFound: String { return self._s[1624]! } - public var Contacts_SortByName: String { return self._s[1625]! } - public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1626]! } + public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[1639]! } + public var Theme_ErrorNotFound: String { return self._s[1640]! } + public var Contacts_SortByName: String { return self._s[1641]! } + public var SettingsSearch_Synonyms_Privacy_Forwards: String { return self._s[1642]! } public func CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1628]!, self._r[1628]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1644]!, self._r[1644]!, [_1, _2, _3]) } - public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1629]! } - public var ScheduledMessages_EditTime: String { return self._s[1630]! } - public var Conversation_ClearSelfHistory: String { return self._s[1631]! } - public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1632]! } - public var PasscodeSettings_DoNotMatch: String { return self._s[1633]! } - public var Stickers_SuggestNone: String { return self._s[1634]! } - public var ChatSettings_Cache: String { return self._s[1635]! } - public var Settings_SaveIncomingPhotos: String { return self._s[1636]! } - public var Media_ShareThisPhoto: String { return self._s[1637]! } - public var Chat_SlowmodeTooltipPending: String { return self._s[1638]! } - public var InfoPlist_NSContactsUsageDescription: String { return self._s[1639]! } - public var Conversation_ContextMenuCopyLink: String { return self._s[1640]! } - public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1641]! } - public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1642]! } - public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1643]! } + public var Notification_Exceptions_RemoveFromExceptions: String { return self._s[1645]! } + public var ScheduledMessages_EditTime: String { return self._s[1646]! } + public var Conversation_ClearSelfHistory: String { return self._s[1647]! } + public var Checkout_NewCard_PostcodePlaceholder: String { return self._s[1648]! } + public var PasscodeSettings_DoNotMatch: String { return self._s[1649]! } + public var Stickers_SuggestNone: String { return self._s[1650]! } + public var ChatSettings_Cache: String { return self._s[1651]! } + public var Settings_SaveIncomingPhotos: String { return self._s[1652]! } + public var Media_ShareThisPhoto: String { return self._s[1653]! } + public var Chat_SlowmodeTooltipPending: String { return self._s[1654]! } + public var InfoPlist_NSContactsUsageDescription: String { return self._s[1655]! } + public var Conversation_ContextMenuCopyLink: String { return self._s[1656]! } + public var PrivacyPolicy_AgeVerificationTitle: String { return self._s[1657]! } + public var SettingsSearch_Synonyms_Stickers_Masks: String { return self._s[1658]! } + public var TwoStepAuth_SetupPasswordEnterPasswordNew: String { return self._s[1659]! } public func Wallet_SecureStorageReset_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1644]!, self._r[1644]!, [_0]) + return formatWithArgumentRanges(self._s[1660]!, self._r[1660]!, [_0]) } - public var Permissions_CellularDataTitle_v0: String { return self._s[1645]! } - public var WallpaperSearch_ColorWhite: String { return self._s[1647]! } - public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1648]! } - public var Conversation_ErrorInaccessibleMessage: String { return self._s[1649]! } - public var Map_OpenIn: String { return self._s[1650]! } + public var Permissions_CellularDataTitle_v0: String { return self._s[1661]! } + public var WallpaperSearch_ColorWhite: String { return self._s[1663]! } + public var Channel_AdminLog_DefaultRestrictionsUpdated: String { return self._s[1664]! } + public var Conversation_ErrorInaccessibleMessage: String { return self._s[1665]! } + public var Map_OpenIn: String { return self._s[1666]! } public func PUSH_PHONE_CALL_MISSED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1653]!, self._r[1653]!, [_1]) + return formatWithArgumentRanges(self._s[1669]!, self._r[1669]!, [_1]) } public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1654]!, self._r[1654]!, [_0]) + return formatWithArgumentRanges(self._s[1670]!, self._r[1670]!, [_0]) } - public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1655]! } - public var MessagePoll_LabelClosed: String { return self._s[1656]! } - public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1658]! } - public var Wallet_Send_SendAnyway: String { return self._s[1659]! } - public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1660]! } - public var UserInfo_FirstNamePlaceholder: String { return self._s[1661]! } - public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1662]! } - public var Login_SelectCountry_Title: String { return self._s[1663]! } - public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1664]! } + public var GroupInfo_Permissions_SlowmodeHeader: String { return self._s[1671]! } + public var MessagePoll_LabelClosed: String { return self._s[1672]! } + public var GroupPermission_PermissionGloballyDisabled: String { return self._s[1674]! } + public var Wallet_Send_SendAnyway: String { return self._s[1675]! } + public var Passport_Identity_MiddleNamePlaceholder: String { return self._s[1676]! } + public var UserInfo_FirstNamePlaceholder: String { return self._s[1677]! } + public var PrivacyLastSeenSettings_WhoCanSeeMyTimestamp: String { return self._s[1678]! } + public var Login_SelectCountry_Title: String { return self._s[1679]! } + public var Channel_EditAdmin_PermissionBanUsers: String { return self._s[1680]! } public func Conversation_OpenBotLinkLogin(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1665]!, self._r[1665]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1681]!, self._r[1681]!, [_1, _2]) } - public var Channel_AdminLog_ChangeInfo: String { return self._s[1666]! } - public var Watch_Suggestion_BRB: String { return self._s[1667]! } - public var Passport_Identity_EditIdentityCard: String { return self._s[1668]! } - public var Contacts_PermissionsTitle: String { return self._s[1669]! } - public var Conversation_RestrictedInline: String { return self._s[1670]! } - public var StickerPack_ViewPack: String { return self._s[1672]! } - public var Wallet_UnknownError: String { return self._s[1673]! } + public var Channel_AdminLog_ChangeInfo: String { return self._s[1682]! } + public var Watch_Suggestion_BRB: String { return self._s[1683]! } + public var Passport_Identity_EditIdentityCard: String { return self._s[1684]! } + public var Contacts_PermissionsTitle: String { return self._s[1685]! } + public var Conversation_RestrictedInline: String { return self._s[1686]! } + public var StickerPack_ViewPack: String { return self._s[1688]! } + public var Wallet_UnknownError: String { return self._s[1689]! } public func Update_AppVersion(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1674]!, self._r[1674]!, [_0]) + return formatWithArgumentRanges(self._s[1690]!, self._r[1690]!, [_0]) } - public var Compose_NewChannel: String { return self._s[1676]! } - public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1679]! } - public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1681]! } - public var Channel_Info_Stickers: String { return self._s[1682]! } - public var AutoNightTheme_PreferredTheme: String { return self._s[1683]! } - public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1684]! } - public var Passport_DeletePersonalDetails: String { return self._s[1685]! } - public var LogoutOptions_AddAccountTitle: String { return self._s[1686]! } - public var Channel_DiscussionGroupInfo: String { return self._s[1687]! } - public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1688]! } - public var Conversation_SearchNoResults: String { return self._s[1690]! } - public var MessagePoll_LabelAnonymous: String { return self._s[1691]! } - public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1692]! } - public var Login_Code: String { return self._s[1693]! } - public var EditTheme_Create_BottomInfo: String { return self._s[1694]! } - public var Watch_Suggestion_WhatsUp: String { return self._s[1695]! } - public var Weekday_ShortThursday: String { return self._s[1696]! } - public var Resolve_ErrorNotFound: String { return self._s[1698]! } - public var LastSeen_Offline: String { return self._s[1699]! } - public var PeopleNearby_NoMembers: String { return self._s[1700]! } - public var GroupPermission_AddMembersNotAvailable: String { return self._s[1701]! } - public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1702]! } - public var GroupInfo_Title: String { return self._s[1704]! } - public var NotificationsSound_Note: String { return self._s[1705]! } - public var Conversation_EditingMessagePanelTitle: String { return self._s[1706]! } - public var Watch_Message_Poll: String { return self._s[1707]! } - public var Privacy_Calls: String { return self._s[1708]! } + public var Compose_NewChannel: String { return self._s[1692]! } + public var ChatSettings_AutoDownloadSettings_TypePhoto: String { return self._s[1695]! } + public var Conversation_ReportSpamGroupConfirmation: String { return self._s[1697]! } + public var Channel_Info_Stickers: String { return self._s[1698]! } + public var AutoNightTheme_PreferredTheme: String { return self._s[1699]! } + public var PrivacyPolicy_AgeVerificationAgree: String { return self._s[1700]! } + public var Passport_DeletePersonalDetails: String { return self._s[1701]! } + public var LogoutOptions_AddAccountTitle: String { return self._s[1702]! } + public var Channel_DiscussionGroupInfo: String { return self._s[1703]! } + public var Group_EditAdmin_RankOwnerPlaceholder: String { return self._s[1704]! } + public var Conversation_SearchNoResults: String { return self._s[1706]! } + public var MessagePoll_LabelAnonymous: String { return self._s[1707]! } + public var Channel_Members_AddAdminErrorNotAMember: String { return self._s[1708]! } + public var Login_Code: String { return self._s[1709]! } + public var EditTheme_Create_BottomInfo: String { return self._s[1710]! } + public var Watch_Suggestion_WhatsUp: String { return self._s[1711]! } + public var Weekday_ShortThursday: String { return self._s[1712]! } + public var Resolve_ErrorNotFound: String { return self._s[1714]! } + public var LastSeen_Offline: String { return self._s[1715]! } + public var PeopleNearby_NoMembers: String { return self._s[1716]! } + public var GroupPermission_AddMembersNotAvailable: String { return self._s[1717]! } + public var Privacy_Calls_AlwaysAllow_Title: String { return self._s[1718]! } + public var GroupInfo_Title: String { return self._s[1720]! } + public var NotificationsSound_Note: String { return self._s[1721]! } + public var Conversation_EditingMessagePanelTitle: String { return self._s[1722]! } + public var Watch_Message_Poll: String { return self._s[1723]! } + public var Privacy_Calls: String { return self._s[1724]! } public func Channel_AdminLog_MessageRankUsername(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1709]!, self._r[1709]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1725]!, self._r[1725]!, [_1, _2, _3]) } - public var Month_ShortAugust: String { return self._s[1710]! } - public var TwoStepAuth_SetPasswordHelp: String { return self._s[1711]! } - public var Notifications_Reset: String { return self._s[1712]! } - public var Conversation_Pin: String { return self._s[1713]! } - public var Passport_Language_lv: String { return self._s[1714]! } - public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1715]! } - public var BlockedUsers_Info: String { return self._s[1716]! } - public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1718]! } - public var Watch_Conversation_Unblock: String { return self._s[1720]! } + public var Month_ShortAugust: String { return self._s[1726]! } + public var TwoStepAuth_SetPasswordHelp: String { return self._s[1727]! } + public var Notifications_Reset: String { return self._s[1728]! } + public var Conversation_Pin: String { return self._s[1729]! } + public var Passport_Language_lv: String { return self._s[1730]! } + public var Permissions_PeopleNearbyAllowInSettings_v0: String { return self._s[1731]! } + public var BlockedUsers_Info: String { return self._s[1732]! } + public var SettingsSearch_Synonyms_Data_AutoplayVideos: String { return self._s[1734]! } + public var Watch_Conversation_Unblock: String { return self._s[1736]! } public func Time_MonthOfYear_m9(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1721]!, self._r[1721]!, [_0]) + return formatWithArgumentRanges(self._s[1737]!, self._r[1737]!, [_0]) } - public var CloudStorage_Title: String { return self._s[1722]! } - public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1723]! } + public var CloudStorage_Title: String { return self._s[1738]! } + public var GroupInfo_DeleteAndExitConfirmation: String { return self._s[1739]! } public func NetworkUsageSettings_WifiUsageSince(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1724]!, self._r[1724]!, [_0]) + return formatWithArgumentRanges(self._s[1740]!, self._r[1740]!, [_0]) } - public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1725]! } - public var Watch_Suggestion_OnMyWay: String { return self._s[1726]! } - public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1727]! } - public var Passport_Address_EditBankStatement: String { return self._s[1728]! } + public var Channel_AdminLogFilter_AdminsTitle: String { return self._s[1741]! } + public var Watch_Suggestion_OnMyWay: String { return self._s[1742]! } + public var TwoStepAuth_RecoveryEmailTitle: String { return self._s[1743]! } + public var Passport_Address_EditBankStatement: String { return self._s[1744]! } public func Channel_AdminLog_MessageChangedUnlinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1729]!, self._r[1729]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1745]!, self._r[1745]!, [_1, _2]) } - public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1730]! } - public var ShareMenu_Comment: String { return self._s[1731]! } - public var Permissions_ContactsTitle_v0: String { return self._s[1732]! } - public var Notifications_PermissionsTitle: String { return self._s[1733]! } - public var GroupPermission_NoSendLinks: String { return self._s[1734]! } - public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1735]! } - public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1736]! } - public var Settings_Support: String { return self._s[1737]! } - public var Notifications_ChannelNotificationsSound: String { return self._s[1738]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1739]! } - public var Privacy_Forwards_Preview: String { return self._s[1740]! } - public var GroupPermission_ApplyAlertAction: String { return self._s[1741]! } - public var Watch_Stickers_StickerPacks: String { return self._s[1742]! } - public var Common_Select: String { return self._s[1744]! } - public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1745]! } - public var WallpaperSearch_ColorGray: String { return self._s[1748]! } - public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1749]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1750]! } - public var Appearance_PreviewReplyAuthor: String { return self._s[1751]! } - public var TwoStepAuth_RecoveryTitle: String { return self._s[1752]! } - public var Widget_AuthRequired: String { return self._s[1753]! } - public var Camera_FlashOn: String { return self._s[1754]! } - public var Conversation_ContextMenuLookUp: String { return self._s[1755]! } - public var Channel_Stickers_NotFoundHelp: String { return self._s[1756]! } - public var Watch_Suggestion_OK: String { return self._s[1757]! } + public var ChatSettings_DownloadInBackgroundInfo: String { return self._s[1746]! } + public var ShareMenu_Comment: String { return self._s[1747]! } + public var Permissions_ContactsTitle_v0: String { return self._s[1748]! } + public var Notifications_PermissionsTitle: String { return self._s[1749]! } + public var GroupPermission_NoSendLinks: String { return self._s[1750]! } + public var Privacy_Forwards_NeverAllow_Title: String { return self._s[1751]! } + public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[1752]! } + public var Settings_Support: String { return self._s[1753]! } + public var Notifications_ChannelNotificationsSound: String { return self._s[1754]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadReset: String { return self._s[1755]! } + public var Privacy_Forwards_Preview: String { return self._s[1756]! } + public var GroupPermission_ApplyAlertAction: String { return self._s[1757]! } + public var Watch_Stickers_StickerPacks: String { return self._s[1758]! } + public var Common_Select: String { return self._s[1760]! } + public var CheckoutInfo_ErrorEmailInvalid: String { return self._s[1761]! } + public var WallpaperSearch_ColorGray: String { return self._s[1764]! } + public var TwoFactorSetup_Password_PlaceholderPassword: String { return self._s[1765]! } + public var TwoFactorSetup_Hint_SkipAction: String { return self._s[1766]! } + public var ChatAdmins_AllMembersAreAdminsOffHelp: String { return self._s[1767]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5hours: String { return self._s[1768]! } + public var Appearance_PreviewReplyAuthor: String { return self._s[1769]! } + public var TwoStepAuth_RecoveryTitle: String { return self._s[1770]! } + public var Widget_AuthRequired: String { return self._s[1771]! } + public var Camera_FlashOn: String { return self._s[1772]! } + public var Conversation_ContextMenuLookUp: String { return self._s[1773]! } + public var Channel_Stickers_NotFoundHelp: String { return self._s[1774]! } + public var Watch_Suggestion_OK: String { return self._s[1775]! } public func Username_LinkHint(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1759]!, self._r[1759]!, [_0]) + return formatWithArgumentRanges(self._s[1777]!, self._r[1777]!, [_0]) } public func Notification_PinnedLiveLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1761]!, self._r[1761]!, [_0]) + return formatWithArgumentRanges(self._s[1779]!, self._r[1779]!, [_0]) } - public var TextFormat_Strikethrough: String { return self._s[1762]! } - public var DialogList_AdLabel: String { return self._s[1763]! } - public var WatchRemote_NotificationText: String { return self._s[1764]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1765]! } - public var Conversation_ReportSpam: String { return self._s[1766]! } - public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1767]! } - public var Settings_LogoutConfirmationTitle: String { return self._s[1769]! } - public var PhoneLabel_Title: String { return self._s[1770]! } - public var Passport_Address_EditRentalAgreement: String { return self._s[1771]! } - public var Settings_ChangePhoneNumber: String { return self._s[1772]! } - public var Notifications_ExceptionsTitle: String { return self._s[1773]! } - public var Notifications_AlertTones: String { return self._s[1774]! } - public var Call_ReportIncludeLogDescription: String { return self._s[1775]! } - public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1776]! } - public var AutoDownloadSettings_PrivateChats: String { return self._s[1777]! } - public var VoiceOver_Chat_Photo: String { return self._s[1779]! } - public var TwoStepAuth_AddHintTitle: String { return self._s[1780]! } - public var ReportPeer_ReasonOther: String { return self._s[1781]! } - public var ChatList_Context_JoinChannel: String { return self._s[1782]! } - public var KeyCommand_ScrollDown: String { return self._s[1784]! } - public var Conversation_ScheduleMessage_Title: String { return self._s[1785]! } + public var TextFormat_Strikethrough: String { return self._s[1780]! } + public var DialogList_AdLabel: String { return self._s[1781]! } + public var WatchRemote_NotificationText: String { return self._s[1782]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert: String { return self._s[1783]! } + public var Conversation_ReportSpam: String { return self._s[1784]! } + public var SettingsSearch_Synonyms_Privacy_Data_TopPeers: String { return self._s[1785]! } + public var Settings_LogoutConfirmationTitle: String { return self._s[1787]! } + public var PhoneLabel_Title: String { return self._s[1788]! } + public var Passport_Address_EditRentalAgreement: String { return self._s[1789]! } + public var Settings_ChangePhoneNumber: String { return self._s[1790]! } + public var Notifications_ExceptionsTitle: String { return self._s[1791]! } + public var Notifications_AlertTones: String { return self._s[1792]! } + public var Call_ReportIncludeLogDescription: String { return self._s[1793]! } + public var SettingsSearch_Synonyms_Notifications_ResetAllNotifications: String { return self._s[1794]! } + public var AutoDownloadSettings_PrivateChats: String { return self._s[1795]! } + public var VoiceOver_Chat_Photo: String { return self._s[1797]! } + public var TwoStepAuth_AddHintTitle: String { return self._s[1798]! } + public var ReportPeer_ReasonOther: String { return self._s[1799]! } + public var ChatList_Context_JoinChannel: String { return self._s[1800]! } + public var KeyCommand_ScrollDown: String { return self._s[1802]! } + public var Conversation_ScheduleMessage_Title: String { return self._s[1803]! } public func Login_BannedPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1786]!, self._r[1786]!, [_0]) + return formatWithArgumentRanges(self._s[1804]!, self._r[1804]!, [_0]) } - public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1787]! } - public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1788]! } - public var AuthSessions_LogOut: String { return self._s[1789]! } - public var Passport_Identity_TypeInternalPassport: String { return self._s[1790]! } - public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1791]! } - public var Passport_Phone_Title: String { return self._s[1792]! } - public var ContactList_Context_StartSecretChat: String { return self._s[1793]! } - public var Settings_PhoneNumber: String { return self._s[1794]! } + public var NetworkUsageSettings_MediaVideoDataSection: String { return self._s[1805]! } + public var ChannelInfo_DeleteGroupConfirmation: String { return self._s[1806]! } + public var AuthSessions_LogOut: String { return self._s[1807]! } + public var Passport_Identity_TypeInternalPassport: String { return self._s[1808]! } + public var ChatSettings_AutoDownloadVoiceMessages: String { return self._s[1809]! } + public var Passport_Phone_Title: String { return self._s[1810]! } + public var ContactList_Context_StartSecretChat: String { return self._s[1811]! } + public var Settings_PhoneNumber: String { return self._s[1812]! } public func Conversation_ScheduleMessage_SendToday(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1795]!, self._r[1795]!, [_0]) + return formatWithArgumentRanges(self._s[1813]!, self._r[1813]!, [_0]) } - public var NotificationsSound_Alert: String { return self._s[1796]! } - public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1797]! } - public var WebSearch_SearchNoResults: String { return self._s[1798]! } - public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1800]! } - public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1801]! } - public var SettingsSearch_Synonyms_Passport: String { return self._s[1802]! } - public var PhotoEditor_CurvesTool: String { return self._s[1803]! } - public var Checkout_PaymentMethod: String { return self._s[1805]! } + public var NotificationsSound_Alert: String { return self._s[1814]! } + public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[1815]! } + public var WebSearch_SearchNoResults: String { return self._s[1816]! } + public var Privacy_ProfilePhoto_AlwaysShareWith_Title: String { return self._s[1818]! } + public var LogoutOptions_AlternativeOptionsSection: String { return self._s[1819]! } + public var SettingsSearch_Synonyms_Passport: String { return self._s[1820]! } + public var PhotoEditor_CurvesTool: String { return self._s[1821]! } + public var Checkout_PaymentMethod: String { return self._s[1823]! } public func PUSH_CHAT_ADD_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1806]!, self._r[1806]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1824]!, self._r[1824]!, [_1, _2]) } - public var Contacts_AccessDeniedError: String { return self._s[1807]! } - public var Camera_PhotoMode: String { return self._s[1810]! } - public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1811]! } - public var Passport_Address_AddUtilityBill: String { return self._s[1813]! } - public var CallSettings_OnMobile: String { return self._s[1814]! } - public var Tour_Text2: String { return self._s[1815]! } + public var Contacts_AccessDeniedError: String { return self._s[1825]! } + public var Camera_PhotoMode: String { return self._s[1828]! } + public var EditTheme_Expand_Preview_IncomingText: String { return self._s[1829]! } + public var Passport_Address_AddUtilityBill: String { return self._s[1831]! } + public var CallSettings_OnMobile: String { return self._s[1832]! } + public var Tour_Text2: String { return self._s[1833]! } public func PUSH_CHAT_MESSAGE_ROUND(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1816]!, self._r[1816]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1834]!, self._r[1834]!, [_1, _2]) } - public var DialogList_EncryptionProcessing: String { return self._s[1818]! } - public var Permissions_Skip: String { return self._s[1819]! } - public var Wallet_Words_NotDoneOk: String { return self._s[1820]! } - public var SecretImage_Title: String { return self._s[1821]! } - public var Watch_MessageView_Title: String { return self._s[1822]! } - public var Channel_DiscussionGroupAdd: String { return self._s[1823]! } - public var AttachmentMenu_Poll: String { return self._s[1824]! } + public var DialogList_EncryptionProcessing: String { return self._s[1836]! } + public var Permissions_Skip: String { return self._s[1837]! } + public var Wallet_Words_NotDoneOk: String { return self._s[1838]! } + public var SecretImage_Title: String { return self._s[1839]! } + public var Watch_MessageView_Title: String { return self._s[1840]! } + public var Channel_DiscussionGroupAdd: String { return self._s[1841]! } + public var AttachmentMenu_Poll: String { return self._s[1842]! } public func Notification_GroupInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1825]!, self._r[1825]!, [_0]) + return formatWithArgumentRanges(self._s[1843]!, self._r[1843]!, [_0]) } public func Channel_DiscussionGroup_PrivateChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1826]!, self._r[1826]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1844]!, self._r[1844]!, [_1, _2]) } - public var Notification_CallCanceled: String { return self._s[1827]! } - public var WallpaperPreview_Title: String { return self._s[1828]! } - public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1829]! } - public var Settings_ProxyConnecting: String { return self._s[1830]! } - public var Settings_CheckPhoneNumberText: String { return self._s[1832]! } - public var VoiceOver_Chat_YourVideo: String { return self._s[1833]! } - public var Wallet_Intro_Title: String { return self._s[1834]! } - public var Profile_MessageLifetime5s: String { return self._s[1835]! } - public var Username_InvalidCharacters: String { return self._s[1836]! } - public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1837]! } - public var ScheduledMessages_ClearAll: String { return self._s[1838]! } - public var WallpaperPreview_CropBottomText: String { return self._s[1839]! } - public var AutoDownloadSettings_LimitBySize: String { return self._s[1840]! } - public var Settings_AddAccount: String { return self._s[1841]! } - public var Notification_CreatedChannel: String { return self._s[1844]! } + public var Notification_CallCanceled: String { return self._s[1845]! } + public var WallpaperPreview_Title: String { return self._s[1846]! } + public var Privacy_PaymentsClear_PaymentInfo: String { return self._s[1847]! } + public var Settings_ProxyConnecting: String { return self._s[1848]! } + public var Settings_CheckPhoneNumberText: String { return self._s[1850]! } + public var VoiceOver_Chat_YourVideo: String { return self._s[1851]! } + public var Wallet_Intro_Title: String { return self._s[1852]! } + public var TwoFactorSetup_Password_Action: String { return self._s[1853]! } + public var Profile_MessageLifetime5s: String { return self._s[1854]! } + public var Username_InvalidCharacters: String { return self._s[1855]! } + public var VoiceOver_Media_PlaybackRateFast: String { return self._s[1856]! } + public var ScheduledMessages_ClearAll: String { return self._s[1857]! } + public var WallpaperPreview_CropBottomText: String { return self._s[1858]! } + public var AutoDownloadSettings_LimitBySize: String { return self._s[1859]! } + public var Settings_AddAccount: String { return self._s[1860]! } + public var Notification_CreatedChannel: String { return self._s[1863]! } public func PUSH_CHAT_DELETE_MEMBER(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1845]!, self._r[1845]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1864]!, self._r[1864]!, [_1, _2, _3]) } - public var Passcode_AppLockedAlert: String { return self._s[1847]! } - public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1848]! } - public var VoiceOver_Media_PlaybackStop: String { return self._s[1849]! } - public var Contacts_TopSection: String { return self._s[1850]! } - public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1851]! } + public var Passcode_AppLockedAlert: String { return self._s[1866]! } + public var StickerPacksSettings_AnimatedStickersInfo: String { return self._s[1867]! } + public var VoiceOver_Media_PlaybackStop: String { return self._s[1868]! } + public var Contacts_TopSection: String { return self._s[1869]! } + public var ChatList_DeleteForEveryoneConfirmationAction: String { return self._s[1870]! } public func Conversation_SetReminder_RemindOn(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1852]!, self._r[1852]!, [_0, _1]) + return formatWithArgumentRanges(self._s[1871]!, self._r[1871]!, [_0, _1]) } - public var Wallet_Info_Receive: String { return self._s[1853]! } - public var Wallet_Completed_ViewWallet: String { return self._s[1854]! } + public var Wallet_Info_Receive: String { return self._s[1872]! } + public var Wallet_Completed_ViewWallet: String { return self._s[1873]! } public func Time_MonthOfYear_m6(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1855]!, self._r[1855]!, [_0]) + return formatWithArgumentRanges(self._s[1874]!, self._r[1874]!, [_0]) } - public var ReportPeer_ReasonSpam: String { return self._s[1856]! } - public var UserInfo_TapToCall: String { return self._s[1857]! } - public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1859]! } - public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1860]! } - public var Common_Search: String { return self._s[1861]! } - public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1862]! } + public var ReportPeer_ReasonSpam: String { return self._s[1875]! } + public var UserInfo_TapToCall: String { return self._s[1876]! } + public var Conversation_ForwardAuthorHiddenTooltip: String { return self._s[1878]! } + public var AutoDownloadSettings_DataUsageCustom: String { return self._s[1879]! } + public var Common_Search: String { return self._s[1880]! } + public var ScheduledMessages_EmptyPlaceholder: String { return self._s[1881]! } public func Channel_AdminLog_MessageChangedGroupGeoLocation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1863]!, self._r[1863]!, [_0]) + return formatWithArgumentRanges(self._s[1882]!, self._r[1882]!, [_0]) } - public var Wallet_Month_ShortJuly: String { return self._s[1864]! } - public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1865]! } - public var Message_InvoiceLabel: String { return self._s[1866]! } - public var Conversation_InputTextPlaceholder: String { return self._s[1867]! } - public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1868]! } + public var Wallet_Month_ShortJuly: String { return self._s[1883]! } + public var AuthSessions_IncompleteAttemptsInfo: String { return self._s[1884]! } + public var Message_InvoiceLabel: String { return self._s[1885]! } + public var Conversation_InputTextPlaceholder: String { return self._s[1886]! } + public var NetworkUsageSettings_MediaImageDataSection: String { return self._s[1887]! } public func Passport_Address_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1869]!, self._r[1869]!, [_0]) + return formatWithArgumentRanges(self._s[1888]!, self._r[1888]!, [_0]) } - public var Conversation_Info: String { return self._s[1870]! } - public var Login_InfoDeletePhoto: String { return self._s[1871]! } - public var Passport_Language_vi: String { return self._s[1873]! } - public var UserInfo_ScamUserWarning: String { return self._s[1874]! } - public var Conversation_Search: String { return self._s[1875]! } - public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1877]! } - public var ReportPeer_ReasonPornography: String { return self._s[1878]! } - public var AutoDownloadSettings_PhotosTitle: String { return self._s[1879]! } - public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1880]! } - public var Map_LiveLocationGroupDescription: String { return self._s[1881]! } - public var Channel_Setup_TypeHeader: String { return self._s[1882]! } - public var AuthSessions_LoggedIn: String { return self._s[1883]! } - public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1884]! } - public var Login_SmsRequestState3: String { return self._s[1885]! } - public var Passport_Address_EditUtilityBill: String { return self._s[1886]! } - public var Appearance_ReduceMotionInfo: String { return self._s[1887]! } - public var Join_ChannelsTooMuch: String { return self._s[1888]! } - public var Channel_Edit_LinkItem: String { return self._s[1889]! } - public var Privacy_Calls_P2PNever: String { return self._s[1890]! } - public var Conversation_AddToReadingList: String { return self._s[1892]! } - public var Share_MultipleMessagesDisabled: String { return self._s[1893]! } - public var Message_Animation: String { return self._s[1894]! } - public var Conversation_DefaultRestrictedMedia: String { return self._s[1895]! } - public var Map_Unknown: String { return self._s[1896]! } - public var AutoDownloadSettings_LastDelimeter: String { return self._s[1897]! } + public var Conversation_Info: String { return self._s[1889]! } + public var Login_InfoDeletePhoto: String { return self._s[1890]! } + public var Passport_Language_vi: String { return self._s[1892]! } + public var UserInfo_ScamUserWarning: String { return self._s[1893]! } + public var Conversation_Search: String { return self._s[1894]! } + public var DialogList_DeleteBotConversationConfirmation: String { return self._s[1896]! } + public var ReportPeer_ReasonPornography: String { return self._s[1897]! } + public var AutoDownloadSettings_PhotosTitle: String { return self._s[1898]! } + public var Conversation_SendMessageErrorGroupRestricted: String { return self._s[1899]! } + public var Map_LiveLocationGroupDescription: String { return self._s[1900]! } + public var Channel_Setup_TypeHeader: String { return self._s[1901]! } + public var AuthSessions_LoggedIn: String { return self._s[1902]! } + public var Privacy_Forwards_AlwaysAllow_Title: String { return self._s[1903]! } + public var Login_SmsRequestState3: String { return self._s[1904]! } + public var Passport_Address_EditUtilityBill: String { return self._s[1905]! } + public var Appearance_ReduceMotionInfo: String { return self._s[1906]! } + public var Join_ChannelsTooMuch: String { return self._s[1907]! } + public var Channel_Edit_LinkItem: String { return self._s[1908]! } + public var Privacy_Calls_P2PNever: String { return self._s[1909]! } + public var Conversation_AddToReadingList: String { return self._s[1911]! } + public var Share_MultipleMessagesDisabled: String { return self._s[1912]! } + public var Message_Animation: String { return self._s[1913]! } + public var Conversation_DefaultRestrictedMedia: String { return self._s[1914]! } + public var Map_Unknown: String { return self._s[1915]! } + public var AutoDownloadSettings_LastDelimeter: String { return self._s[1916]! } public func PUSH_PINNED_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1898]!, self._r[1898]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1917]!, self._r[1917]!, [_1, _2]) } public func Passport_FieldOneOf_Or(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1899]!, self._r[1899]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1918]!, self._r[1918]!, [_1, _2]) } - public var Call_StatusRequesting: String { return self._s[1900]! } - public var Conversation_SecretChatContextBotAlert: String { return self._s[1901]! } - public var SocksProxySetup_ProxyStatusChecking: String { return self._s[1902]! } + public var Call_StatusRequesting: String { return self._s[1919]! } + public var Conversation_SecretChatContextBotAlert: String { return self._s[1920]! } + public var SocksProxySetup_ProxyStatusChecking: String { return self._s[1921]! } public func PUSH_CHAT_MESSAGE_DOC(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1903]!, self._r[1903]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1922]!, self._r[1922]!, [_1, _2]) } public func Notification_PinnedLocationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1904]!, self._r[1904]!, [_0]) + return formatWithArgumentRanges(self._s[1923]!, self._r[1923]!, [_0]) } - public var Update_Skip: String { return self._s[1905]! } - public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[1906]! } - public var Message_PinnedPollMessage: String { return self._s[1907]! } - public var BlockedUsers_Title: String { return self._s[1908]! } + public var Update_Skip: String { return self._s[1924]! } + public var Group_Username_RemoveExistingUsernamesInfo: String { return self._s[1925]! } + public var Message_PinnedPollMessage: String { return self._s[1926]! } + public var BlockedUsers_Title: String { return self._s[1927]! } public func PUSH_CHANNEL_MESSAGE_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1909]!, self._r[1909]!, [_1]) + return formatWithArgumentRanges(self._s[1928]!, self._r[1928]!, [_1]) } - public var Username_CheckingUsername: String { return self._s[1910]! } - public var NotificationsSound_Bell: String { return self._s[1911]! } - public var Conversation_SendMessageErrorFlood: String { return self._s[1912]! } - public var Weekday_Monday: String { return self._s[1913]! } - public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[1914]! } - public var ChannelMembers_ChannelAdminsTitle: String { return self._s[1915]! } - public var ChatSettings_Groups: String { return self._s[1916]! } + public var Username_CheckingUsername: String { return self._s[1929]! } + public var NotificationsSound_Bell: String { return self._s[1930]! } + public var Conversation_SendMessageErrorFlood: String { return self._s[1931]! } + public var Weekday_Monday: String { return self._s[1932]! } + public var SettingsSearch_Synonyms_Notifications_DisplayNamesOnLockScreen: String { return self._s[1933]! } + public var ChannelMembers_ChannelAdminsTitle: String { return self._s[1934]! } + public var ChatSettings_Groups: String { return self._s[1935]! } public func Conversation_SetReminder_RemindTomorrow(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1917]!, self._r[1917]!, [_0]) + return formatWithArgumentRanges(self._s[1936]!, self._r[1936]!, [_0]) } - public var Your_card_was_declined: String { return self._s[1918]! } - public var TwoStepAuth_EnterPasswordHelp: String { return self._s[1920]! } - public var Wallet_Month_ShortApril: String { return self._s[1921]! } - public var ChatList_Unmute: String { return self._s[1922]! } - public var PhotoEditor_CurvesAll: String { return self._s[1923]! } - public var Weekday_ShortTuesday: String { return self._s[1924]! } - public var DialogList_Read: String { return self._s[1925]! } - public var Appearance_AppIconClassic: String { return self._s[1926]! } - public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[1927]! } - public var Passport_Identity_Gender: String { return self._s[1928]! } + public var Your_card_was_declined: String { return self._s[1937]! } + public var TwoStepAuth_EnterPasswordHelp: String { return self._s[1939]! } + public var Wallet_Month_ShortApril: String { return self._s[1940]! } + public var ChatList_Unmute: String { return self._s[1941]! } + public var PhotoEditor_CurvesAll: String { return self._s[1942]! } + public var Weekday_ShortTuesday: String { return self._s[1943]! } + public var DialogList_Read: String { return self._s[1944]! } + public var Appearance_AppIconClassic: String { return self._s[1945]! } + public var ChannelMembers_WhoCanAddMembers_AllMembers: String { return self._s[1946]! } + public var Passport_Identity_Gender: String { return self._s[1947]! } public func Target_ShareGameConfirmationPrivate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1929]!, self._r[1929]!, [_0]) + return formatWithArgumentRanges(self._s[1948]!, self._r[1948]!, [_0]) } - public var Target_SelectGroup: String { return self._s[1930]! } + public var Target_SelectGroup: String { return self._s[1949]! } public func DialogList_EncryptedChatStartedIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1932]!, self._r[1932]!, [_0]) + return formatWithArgumentRanges(self._s[1951]!, self._r[1951]!, [_0]) } - public var Passport_Language_en: String { return self._s[1933]! } - public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[1934]! } - public var Channel_Username_CreatePublicLinkHelp: String { return self._s[1935]! } - public var Login_CancelPhoneVerificationContinue: String { return self._s[1936]! } - public var ScheduledMessages_SendNow: String { return self._s[1937]! } - public var Checkout_NewCard_PaymentCard: String { return self._s[1939]! } - public var Login_InfoHelp: String { return self._s[1940]! } - public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[1941]! } - public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[1942]! } + public var Passport_Language_en: String { return self._s[1952]! } + public var AutoDownloadSettings_AutodownloadPhotos: String { return self._s[1953]! } + public var Channel_Username_CreatePublicLinkHelp: String { return self._s[1954]! } + public var Login_CancelPhoneVerificationContinue: String { return self._s[1955]! } + public var ScheduledMessages_SendNow: String { return self._s[1956]! } + public var Checkout_NewCard_PaymentCard: String { return self._s[1958]! } + public var Login_InfoHelp: String { return self._s[1959]! } + public var Contacts_PermissionsSuppressWarningTitle: String { return self._s[1960]! } + public var SettingsSearch_Synonyms_Stickers_FeaturedPacks: String { return self._s[1961]! } public func Channel_AdminLog_MessageChangedLinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1943]!, self._r[1943]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1962]!, self._r[1962]!, [_1, _2]) } - public var SocksProxySetup_AddProxy: String { return self._s[1946]! } - public var CreatePoll_Title: String { return self._s[1947]! } - public var Conversation_ViewTheme: String { return self._s[1948]! } - public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[1949]! } - public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[1950]! } - public var UserInfo_GroupsInCommon: String { return self._s[1951]! } - public var Call_AudioRouteHide: String { return self._s[1952]! } + public var SocksProxySetup_AddProxy: String { return self._s[1965]! } + public var CreatePoll_Title: String { return self._s[1966]! } + public var Conversation_ViewTheme: String { return self._s[1967]! } + public var SettingsSearch_Synonyms_Privacy_Data_SecretChatLinkPreview: String { return self._s[1968]! } + public var PasscodeSettings_SimplePasscodeHelp: String { return self._s[1969]! } + public var TwoFactorSetup_Intro_Text: String { return self._s[1970]! } + public var UserInfo_GroupsInCommon: String { return self._s[1971]! } + public var Call_AudioRouteHide: String { return self._s[1972]! } public func Wallet_Info_TransactionDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1954]!, self._r[1954]!, [_1, _2]) + return formatWithArgumentRanges(self._s[1974]!, self._r[1974]!, [_1, _2]) } - public var ContactInfo_PhoneLabelMobile: String { return self._s[1955]! } + public var ContactInfo_PhoneLabelMobile: String { return self._s[1975]! } public func ChatList_LeaveGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1956]!, self._r[1956]!, [_0]) + return formatWithArgumentRanges(self._s[1976]!, self._r[1976]!, [_0]) } - public var TextFormat_Bold: String { return self._s[1957]! } - public var FastTwoStepSetup_EmailSection: String { return self._s[1958]! } - public var Notifications_Title: String { return self._s[1959]! } - public var Group_Username_InvalidTooShort: String { return self._s[1960]! } - public var Channel_ErrorAddTooMuch: String { return self._s[1961]! } + public var TextFormat_Bold: String { return self._s[1977]! } + public var FastTwoStepSetup_EmailSection: String { return self._s[1978]! } + public var Notifications_Title: String { return self._s[1979]! } + public var Group_Username_InvalidTooShort: String { return self._s[1980]! } + public var Channel_ErrorAddTooMuch: String { return self._s[1981]! } public func DialogList_MultipleTypingSuffix(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1962]!, self._r[1962]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[1982]!, self._r[1982]!, ["\(_0)"]) } - public var VoiceOver_DiscardPreparedContent: String { return self._s[1964]! } - public var Stickers_SuggestAdded: String { return self._s[1965]! } - public var Login_CountryCode: String { return self._s[1966]! } - public var ChatSettings_AutoPlayVideos: String { return self._s[1967]! } - public var Map_GetDirections: String { return self._s[1968]! } - public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[1969]! } - public var Login_PhoneFloodError: String { return self._s[1970]! } + public var VoiceOver_DiscardPreparedContent: String { return self._s[1984]! } + public var Stickers_SuggestAdded: String { return self._s[1985]! } + public var Login_CountryCode: String { return self._s[1986]! } + public var ChatSettings_AutoPlayVideos: String { return self._s[1987]! } + public var Map_GetDirections: String { return self._s[1988]! } + public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[1989]! } + public var Login_PhoneFloodError: String { return self._s[1990]! } public func Time_MonthOfYear_m3(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1971]!, self._r[1971]!, [_0]) + return formatWithArgumentRanges(self._s[1991]!, self._r[1991]!, [_0]) } public func Wallet_Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1972]!, self._r[1972]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[1992]!, self._r[1992]!, [_1, _2, _3]) } - public var Settings_SetUsername: String { return self._s[1974]! } - public var Group_Location_ChangeLocation: String { return self._s[1975]! } - public var Notification_GroupInviterSelf: String { return self._s[1976]! } - public var InstantPage_TapToOpenLink: String { return self._s[1977]! } + public var Settings_SetUsername: String { return self._s[1994]! } + public var Group_Location_ChangeLocation: String { return self._s[1995]! } + public var Notification_GroupInviterSelf: String { return self._s[1996]! } + public var InstantPage_TapToOpenLink: String { return self._s[1997]! } public func Notification_ChannelInviter(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1978]!, self._r[1978]!, [_0]) + return formatWithArgumentRanges(self._s[1998]!, self._r[1998]!, [_0]) } - public var Watch_Suggestion_TalkLater: String { return self._s[1979]! } - public var SecretChat_Title: String { return self._s[1980]! } - public var Group_UpgradeNoticeText1: String { return self._s[1981]! } - public var AuthSessions_Title: String { return self._s[1982]! } + public var Watch_Suggestion_TalkLater: String { return self._s[1999]! } + public var SecretChat_Title: String { return self._s[2000]! } + public var Group_UpgradeNoticeText1: String { return self._s[2001]! } + public var AuthSessions_Title: String { return self._s[2002]! } public func TextFormat_AddLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1983]!, self._r[1983]!, [_0]) + return formatWithArgumentRanges(self._s[2003]!, self._r[2003]!, [_0]) } - public var PhotoEditor_CropAuto: String { return self._s[1984]! } - public var Channel_About_Title: String { return self._s[1985]! } - public var FastTwoStepSetup_EmailHelp: String { return self._s[1986]! } + public var PhotoEditor_CropAuto: String { return self._s[2004]! } + public var Channel_About_Title: String { return self._s[2005]! } + public var FastTwoStepSetup_EmailHelp: String { return self._s[2006]! } public func Conversation_Bytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1988]!, self._r[1988]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2008]!, self._r[2008]!, ["\(_0)"]) } - public var VoiceOver_MessageContextReport: String { return self._s[1989]! } - public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[1991]! } - public var Group_Setup_HistoryVisibleHelp: String { return self._s[1992]! } + public var VoiceOver_MessageContextReport: String { return self._s[2009]! } + public var Conversation_PinMessageAlert_OnlyPin: String { return self._s[2011]! } + public var Group_Setup_HistoryVisibleHelp: String { return self._s[2012]! } public func PUSH_MESSAGE_GIF(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1993]!, self._r[1993]!, [_1]) + return formatWithArgumentRanges(self._s[2013]!, self._r[2013]!, [_1]) } public func SharedMedia_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1995]!, self._r[1995]!, [_0]) - } - public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[1996]!, self._r[1996]!, [_0]) - } - public var Privacy_PaymentsClearInfoHelp: String { return self._s[1997]! } - public var Presence_online: String { return self._s[2000]! } - public var PasscodeSettings_Title: String { return self._s[2001]! } - public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2002]! } - public var Web_OpenExternal: String { return self._s[2003]! } - public var AutoDownloadSettings_AutoDownload: String { return self._s[2005]! } - public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2006]! } - public var LocalGroup_Title: String { return self._s[2007]! } - public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2008]!, self._r[2008]!, [_0]) - } - public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2009]! } - public var Map_YouAreHere: String { return self._s[2010]! } - public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2011]!, self._r[2011]!, [_0]) - } - public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2012]!, self._r[2012]!, [_0]) - } - public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2013]! } - public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2014]! } - public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2015]!, self._r[2015]!, [_0]) } - public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + public func TwoStepAuth_RecoveryEmailUnavailable(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2016]!, self._r[2016]!, [_0]) } - public var SocksProxySetup_Username: String { return self._s[2017]! } - public var Bot_Start: String { return self._s[2018]! } + public var Privacy_PaymentsClearInfoHelp: String { return self._s[2017]! } + public var Presence_online: String { return self._s[2020]! } + public var PasscodeSettings_Title: String { return self._s[2021]! } + public var Passport_Identity_ExpiryDatePlaceholder: String { return self._s[2022]! } + public var Web_OpenExternal: String { return self._s[2023]! } + public var AutoDownloadSettings_AutoDownload: String { return self._s[2025]! } + public var Channel_OwnershipTransfer_EnterPasswordText: String { return self._s[2026]! } + public var LocalGroup_Title: String { return self._s[2027]! } + public func AutoNightTheme_AutomaticHelp(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2028]!, self._r[2028]!, [_0]) + } + public var FastTwoStepSetup_PasswordConfirmationPlaceholder: String { return self._s[2029]! } + public var Map_YouAreHere: String { return self._s[2030]! } + public func AuthSessions_Message(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2031]!, self._r[2031]!, [_0]) + } + public func ChatList_DeleteChatConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2032]!, self._r[2032]!, [_0]) + } + public var PrivacyLastSeenSettings_AlwaysShareWith: String { return self._s[2033]! } + public var Target_InviteToGroupErrorAlreadyInvited: String { return self._s[2034]! } + public func AuthSessions_AppUnofficial(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2035]!, self._r[2035]!, [_0]) + } + public func DialogList_LiveLocationSharingTo(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2036]!, self._r[2036]!, [_0]) + } + public var SocksProxySetup_Username: String { return self._s[2037]! } + public var Bot_Start: String { return self._s[2038]! } public func Channel_AdminLog_EmptyFilterQueryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2019]!, self._r[2019]!, [_0]) + return formatWithArgumentRanges(self._s[2039]!, self._r[2039]!, [_0]) } public func Channel_AdminLog_MessagePinned(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2020]!, self._r[2020]!, [_0]) + return formatWithArgumentRanges(self._s[2040]!, self._r[2040]!, [_0]) } - public var Contacts_SortByPresence: String { return self._s[2021]! } - public var AccentColor_Title: String { return self._s[2023]! } - public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2024]! } + public var Contacts_SortByPresence: String { return self._s[2041]! } + public var AccentColor_Title: String { return self._s[2043]! } + public var Conversation_DiscardVoiceMessageTitle: String { return self._s[2044]! } public func PUSH_CHAT_CREATED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2025]!, self._r[2025]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2045]!, self._r[2045]!, [_1, _2]) } public func PrivacySettings_LastSeenContactsMinus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2026]!, self._r[2026]!, [_0]) + return formatWithArgumentRanges(self._s[2046]!, self._r[2046]!, [_0]) } public func Channel_AdminLog_MessageChangedLinkedGroup(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2027]!, self._r[2027]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2047]!, self._r[2047]!, [_1, _2]) } - public var Passport_Email_EnterOtherEmail: String { return self._s[2028]! } - public var Login_InfoAvatarPhoto: String { return self._s[2029]! } - public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2030]! } - public var Tour_Title4: String { return self._s[2031]! } - public var Passport_Identity_Translation: String { return self._s[2032]! } - public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2033]! } - public var Login_TermsOfServiceLabel: String { return self._s[2035]! } - public var Passport_Language_it: String { return self._s[2036]! } - public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2037]! } - public var Passport_Identity_SelfieHelp: String { return self._s[2038]! } - public var Conversation_ClearAll: String { return self._s[2040]! } - public var Wallet_Send_UninitializedText: String { return self._s[2042]! } - public var Channel_OwnershipTransfer_Title: String { return self._s[2043]! } - public var TwoStepAuth_FloodError: String { return self._s[2044]! } + public var Passport_Email_EnterOtherEmail: String { return self._s[2048]! } + public var Login_InfoAvatarPhoto: String { return self._s[2049]! } + public var Privacy_PaymentsClear_ShippingInfo: String { return self._s[2050]! } + public var Tour_Title4: String { return self._s[2051]! } + public var Passport_Identity_Translation: String { return self._s[2052]! } + public var SettingsSearch_Synonyms_Notifications_ContactJoined: String { return self._s[2053]! } + public var Login_TermsOfServiceLabel: String { return self._s[2055]! } + public var Passport_Language_it: String { return self._s[2056]! } + public var KeyCommand_JumpToNextUnreadChat: String { return self._s[2057]! } + public var Passport_Identity_SelfieHelp: String { return self._s[2058]! } + public var Conversation_ClearAll: String { return self._s[2060]! } + public var Wallet_Send_UninitializedText: String { return self._s[2062]! } + public var Channel_OwnershipTransfer_Title: String { return self._s[2063]! } + public var TwoStepAuth_FloodError: String { return self._s[2064]! } public func PUSH_CHANNEL_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2045]!, self._r[2045]!, [_1]) + return formatWithArgumentRanges(self._s[2065]!, self._r[2065]!, [_1]) } - public var Paint_Delete: String { return self._s[2046]! } + public var Paint_Delete: String { return self._s[2066]! } public func Wallet_Sent_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2047]!, self._r[2047]!, [_0]) + return formatWithArgumentRanges(self._s[2067]!, self._r[2067]!, [_0]) } - public var Privacy_AddNewPeer: String { return self._s[2048]! } + public var Privacy_AddNewPeer: String { return self._s[2068]! } public func Channel_AdminLog_MessageRank(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2049]!, self._r[2049]!, [_1]) + return formatWithArgumentRanges(self._s[2069]!, self._r[2069]!, [_1]) } - public var LogoutOptions_SetPasscodeText: String { return self._s[2050]! } + public var LogoutOptions_SetPasscodeText: String { return self._s[2070]! } public func Passport_AcceptHelp(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2051]!, self._r[2051]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2071]!, self._r[2071]!, [_1, _2]) } - public var Message_PinnedAudioMessage: String { return self._s[2052]! } + public var Message_PinnedAudioMessage: String { return self._s[2072]! } public func Watch_Time_ShortTodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2053]!, self._r[2053]!, [_0]) + return formatWithArgumentRanges(self._s[2073]!, self._r[2073]!, [_0]) } - public var Notification_Mute1hMin: String { return self._s[2054]! } - public var Notifications_GroupNotificationsSound: String { return self._s[2055]! } - public var Wallet_Month_GenNovember: String { return self._s[2056]! } - public var SocksProxySetup_ShareProxyList: String { return self._s[2057]! } - public var Conversation_MessageEditedLabel: String { return self._s[2058]! } - public var Notification_Exceptions_AlwaysOff: String { return self._s[2059]! } - public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2060]! } + public var Notification_Mute1hMin: String { return self._s[2074]! } + public var Notifications_GroupNotificationsSound: String { return self._s[2075]! } + public var Wallet_Month_GenNovember: String { return self._s[2076]! } + public var SocksProxySetup_ShareProxyList: String { return self._s[2077]! } + public var Conversation_MessageEditedLabel: String { return self._s[2078]! } + public func ClearCache_Success(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2079]!, self._r[2079]!, [_0, _1]) + } + public var Notification_Exceptions_AlwaysOff: String { return self._s[2080]! } + public var Notification_Exceptions_NewException_MessagePreviewHeader: String { return self._s[2081]! } public func Channel_AdminLog_MessageAdmin(_ _0: String, _ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2061]!, self._r[2061]!, [_0, _1, _2]) + return formatWithArgumentRanges(self._s[2082]!, self._r[2082]!, [_0, _1, _2]) } - public var NetworkUsageSettings_ResetStats: String { return self._s[2062]! } + public var NetworkUsageSettings_ResetStats: String { return self._s[2083]! } public func PUSH_MESSAGE_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2063]!, self._r[2063]!, [_1]) + return formatWithArgumentRanges(self._s[2084]!, self._r[2084]!, [_1]) } - public var AccessDenied_LocationTracking: String { return self._s[2064]! } - public var Month_GenOctober: String { return self._s[2065]! } - public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2066]! } - public var EnterPasscode_EnterPasscode: String { return self._s[2067]! } - public var MediaPicker_TimerTooltip: String { return self._s[2069]! } - public var SharedMedia_TitleAll: String { return self._s[2070]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2073]! } - public var Conversation_RestrictedMedia: String { return self._s[2074]! } - public var AccessDenied_PhotosRestricted: String { return self._s[2075]! } - public var Privacy_Forwards_WhoCanForward: String { return self._s[2077]! } - public var ChangePhoneNumberCode_Called: String { return self._s[2078]! } + public var AccessDenied_LocationTracking: String { return self._s[2085]! } + public var Month_GenOctober: String { return self._s[2086]! } + public var GroupInfo_InviteLink_RevokeAlert_Revoke: String { return self._s[2087]! } + public var EnterPasscode_EnterPasscode: String { return self._s[2088]! } + public var MediaPicker_TimerTooltip: String { return self._s[2090]! } + public var SharedMedia_TitleAll: String { return self._s[2091]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsExceptions: String { return self._s[2094]! } + public var Conversation_RestrictedMedia: String { return self._s[2095]! } + public var AccessDenied_PhotosRestricted: String { return self._s[2096]! } + public var Privacy_Forwards_WhoCanForward: String { return self._s[2098]! } + public var ChangePhoneNumberCode_Called: String { return self._s[2099]! } public func Notification_PinnedDocumentMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2079]!, self._r[2079]!, [_0]) + return formatWithArgumentRanges(self._s[2100]!, self._r[2100]!, [_0]) } - public var Conversation_SavedMessages: String { return self._s[2082]! } - public var Your_cards_expiration_month_is_invalid: String { return self._s[2084]! } - public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2085]! } + public var Conversation_SavedMessages: String { return self._s[2103]! } + public var Your_cards_expiration_month_is_invalid: String { return self._s[2105]! } + public var FastTwoStepSetup_PasswordPlaceholder: String { return self._s[2106]! } public func Target_ShareGameConfirmationGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2087]!, self._r[2087]!, [_0]) + return formatWithArgumentRanges(self._s[2108]!, self._r[2108]!, [_0]) } - public var VoiceOver_Chat_YourMessage: String { return self._s[2088]! } + public var VoiceOver_Chat_YourMessage: String { return self._s[2109]! } public func VoiceOver_Chat_Title(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2089]!, self._r[2089]!, [_0]) + return formatWithArgumentRanges(self._s[2110]!, self._r[2110]!, [_0]) } - public var ReportPeer_AlertSuccess: String { return self._s[2090]! } - public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2091]! } + public var ReportPeer_AlertSuccess: String { return self._s[2111]! } + public var PhotoEditor_CropAspectRatioOriginal: String { return self._s[2112]! } public func InstantPage_RelatedArticleAuthorAndDateTitle(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2092]!, self._r[2092]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2113]!, self._r[2113]!, [_1, _2]) } - public var Checkout_PasswordEntry_Title: String { return self._s[2093]! } - public var PhotoEditor_FadeTool: String { return self._s[2094]! } - public var Privacy_ContactsReset: String { return self._s[2095]! } + public var Checkout_PasswordEntry_Title: String { return self._s[2114]! } + public var PhotoEditor_FadeTool: String { return self._s[2115]! } + public var Privacy_ContactsReset: String { return self._s[2116]! } public func Channel_AdminLog_MessageRestrictedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2097]!, self._r[2097]!, [_0]) - } - public var Message_PinnedVideoMessage: String { return self._s[2098]! } - public var ChatList_Mute: String { return self._s[2099]! } - public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2100]!, self._r[2100]!, [_1, _2, _3]) - } - public var Permissions_CellularDataText_v0: String { return self._s[2101]! } - public var ShareMenu_SelectChats: String { return self._s[2104]! } - public var ChatList_Context_Unarchive: String { return self._s[2105]! } - public var MusicPlayer_VoiceNote: String { return self._s[2106]! } - public var Conversation_RestrictedText: String { return self._s[2107]! } - public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2108]! } - public var Wallet_Month_GenApril: String { return self._s[2109]! } - public var Wallet_Month_ShortMarch: String { return self._s[2110]! } - public var TwoStepAuth_DisableSuccess: String { return self._s[2111]! } - public var Cache_Videos: String { return self._s[2112]! } - public var PrivacySettings_PhoneNumber: String { return self._s[2113]! } - public var Wallet_Month_GenFebruary: String { return self._s[2114]! } - public var FeatureDisabled_Oops: String { return self._s[2116]! } - public var Passport_Address_PostcodePlaceholder: String { return self._s[2117]! } - public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2118]!, self._r[2118]!, [_0]) } - public var Stickers_GroupStickersHelp: String { return self._s[2119]! } - public var GroupPermission_NoSendPolls: String { return self._s[2120]! } - public var Wallet_Qr_ScanCode: String { return self._s[2121]! } - public var Message_VideoExpired: String { return self._s[2123]! } - public var Notifications_Badge: String { return self._s[2124]! } - public var GroupInfo_GroupHistoryVisible: String { return self._s[2125]! } - public var Wallet_Receive_AddressCopied: String { return self._s[2126]! } - public var CreatePoll_OptionPlaceholder: String { return self._s[2127]! } - public var Username_InvalidTooShort: String { return self._s[2128]! } - public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2129]! } - public var Channel_AdminLog_PinMessages: String { return self._s[2130]! } - public var ArchivedChats_IntroTitle3: String { return self._s[2131]! } + public var Message_PinnedVideoMessage: String { return self._s[2119]! } + public var ChatList_Mute: String { return self._s[2120]! } + public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2121]!, self._r[2121]!, [_1, _2, _3]) + } + public var Permissions_CellularDataText_v0: String { return self._s[2122]! } + public var ShareMenu_SelectChats: String { return self._s[2125]! } + public var ChatList_Context_Unarchive: String { return self._s[2126]! } + public var MusicPlayer_VoiceNote: String { return self._s[2127]! } + public var Conversation_RestrictedText: String { return self._s[2128]! } + public var SettingsSearch_Synonyms_Privacy_Data_DeleteDrafts: String { return self._s[2129]! } + public var Wallet_Month_GenApril: String { return self._s[2130]! } + public var Wallet_Month_ShortMarch: String { return self._s[2131]! } + public var TwoStepAuth_DisableSuccess: String { return self._s[2132]! } + public var Cache_Videos: String { return self._s[2133]! } + public var PrivacySettings_PhoneNumber: String { return self._s[2134]! } + public var Wallet_Month_GenFebruary: String { return self._s[2135]! } + public var FeatureDisabled_Oops: String { return self._s[2137]! } + public var Passport_Address_PostcodePlaceholder: String { return self._s[2138]! } + public func AddContact_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2139]!, self._r[2139]!, [_0]) + } + public var Stickers_GroupStickersHelp: String { return self._s[2140]! } + public var GroupPermission_NoSendPolls: String { return self._s[2141]! } + public var Wallet_Qr_ScanCode: String { return self._s[2142]! } + public var Message_VideoExpired: String { return self._s[2144]! } + public var Notifications_Badge: String { return self._s[2145]! } + public var GroupInfo_GroupHistoryVisible: String { return self._s[2146]! } + public var Wallet_Receive_AddressCopied: String { return self._s[2147]! } + public var CreatePoll_OptionPlaceholder: String { return self._s[2148]! } + public var Username_InvalidTooShort: String { return self._s[2149]! } + public var EnterPasscode_EnterNewPasscodeChange: String { return self._s[2150]! } + public var Channel_AdminLog_PinMessages: String { return self._s[2151]! } + public var ArchivedChats_IntroTitle3: String { return self._s[2152]! } public func Notification_MessageLifetimeRemoved(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2132]!, self._r[2132]!, [_1]) + return formatWithArgumentRanges(self._s[2153]!, self._r[2153]!, [_1]) } - public var Permissions_SiriAllowInSettings_v0: String { return self._s[2133]! } - public var Conversation_DefaultRestrictedText: String { return self._s[2134]! } - public var SharedMedia_CategoryDocs: String { return self._s[2137]! } + public var Permissions_SiriAllowInSettings_v0: String { return self._s[2154]! } + public var Conversation_DefaultRestrictedText: String { return self._s[2155]! } + public var SharedMedia_CategoryDocs: String { return self._s[2158]! } public func PUSH_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2138]!, self._r[2138]!, [_1]) + return formatWithArgumentRanges(self._s[2159]!, self._r[2159]!, [_1]) } - public var Wallet_Send_UninitializedTitle: String { return self._s[2139]! } - public var Privacy_Forwards_NeverLink: String { return self._s[2141]! } + public var Wallet_Send_UninitializedTitle: String { return self._s[2160]! } + public var Privacy_Forwards_NeverLink: String { return self._s[2162]! } public func Notification_MessageLifetimeChangedOutgoing(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2142]!, self._r[2142]!, [_1]) + return formatWithArgumentRanges(self._s[2163]!, self._r[2163]!, [_1]) } - public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2143]! } + public var CheckoutInfo_ErrorShippingNotAvailable: String { return self._s[2164]! } public func Time_MonthOfYear_m12(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2144]!, self._r[2144]!, [_0]) + return formatWithArgumentRanges(self._s[2165]!, self._r[2165]!, [_0]) } - public var ChatSettings_PrivateChats: String { return self._s[2145]! } - public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2146]! } - public var Conversation_PrivateMessageLinkCopied: String { return self._s[2147]! } - public var Channel_UpdatePhotoItem: String { return self._s[2148]! } - public var GroupInfo_LeftStatus: String { return self._s[2149]! } - public var Watch_MessageView_Forward: String { return self._s[2151]! } - public var ReportPeer_ReasonChildAbuse: String { return self._s[2152]! } - public var Cache_ClearEmpty: String { return self._s[2154]! } - public var Localization_LanguageName: String { return self._s[2155]! } - public var WebSearch_GIFs: String { return self._s[2156]! } - public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2157]! } - public var Username_InvalidStartsWithNumber: String { return self._s[2158]! } - public var Common_Back: String { return self._s[2159]! } - public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2160]! } - public var Wallet_Send_Send: String { return self._s[2161]! } + public var ChatSettings_PrivateChats: String { return self._s[2166]! } + public var SettingsSearch_Synonyms_EditProfile_Logout: String { return self._s[2167]! } + public var Conversation_PrivateMessageLinkCopied: String { return self._s[2168]! } + public var Channel_UpdatePhotoItem: String { return self._s[2169]! } + public var GroupInfo_LeftStatus: String { return self._s[2170]! } + public var Watch_MessageView_Forward: String { return self._s[2172]! } + public var ReportPeer_ReasonChildAbuse: String { return self._s[2173]! } + public var Cache_ClearEmpty: String { return self._s[2175]! } + public var Localization_LanguageName: String { return self._s[2176]! } + public var WebSearch_GIFs: String { return self._s[2177]! } + public var Notifications_DisplayNamesOnLockScreenInfoWithLink: String { return self._s[2178]! } + public var Username_InvalidStartsWithNumber: String { return self._s[2179]! } + public var Common_Back: String { return self._s[2180]! } + public var Passport_Identity_DateOfBirthPlaceholder: String { return self._s[2181]! } + public var Wallet_Send_Send: String { return self._s[2182]! } public func PUSH_CHANNEL_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2162]!, self._r[2162]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2183]!, self._r[2183]!, [_1, _2]) } - public var Wallet_Info_RefreshErrorTitle: String { return self._s[2163]! } - public var Wallet_Month_GenJune: String { return self._s[2164]! } - public var Passport_Email_Help: String { return self._s[2165]! } - public var Watch_Conversation_Reply: String { return self._s[2167]! } - public var Conversation_EditingMessageMediaChange: String { return self._s[2169]! } - public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2170]! } - public var Channel_BanUser_Unban: String { return self._s[2172]! } - public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2173]! } - public var Group_Username_CreatePublicLinkHelp: String { return self._s[2174]! } - public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2176]! } - public var Wallet_Send_AddressHeader: String { return self._s[2177]! } - public var Passport_Identity_Name: String { return self._s[2178]! } + public var Wallet_Info_RefreshErrorTitle: String { return self._s[2184]! } + public var Wallet_Month_GenJune: String { return self._s[2185]! } + public var Passport_Email_Help: String { return self._s[2186]! } + public var Watch_Conversation_Reply: String { return self._s[2188]! } + public var Conversation_EditingMessageMediaChange: String { return self._s[2190]! } + public var Passport_Identity_IssueDatePlaceholder: String { return self._s[2191]! } + public var Channel_BanUser_Unban: String { return self._s[2193]! } + public var Channel_EditAdmin_PermissionPostMessages: String { return self._s[2194]! } + public var Group_Username_CreatePublicLinkHelp: String { return self._s[2195]! } + public var TwoStepAuth_ConfirmEmailCodePlaceholder: String { return self._s[2197]! } + public var Wallet_Send_AddressHeader: String { return self._s[2198]! } + public var Passport_Identity_Name: String { return self._s[2199]! } public func Channel_DiscussionGroup_HeaderGroupSet(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2179]!, self._r[2179]!, [_0]) - } - public var GroupRemoved_ViewUserInfo: String { return self._s[2180]! } - public var Conversation_BlockUser: String { return self._s[2181]! } - public var Month_GenJanuary: String { return self._s[2182]! } - public var ChatSettings_TextSize: String { return self._s[2183]! } - public var Notification_PassportValuePhone: String { return self._s[2184]! } - public var Passport_Language_ne: String { return self._s[2185]! } - public var Notification_CallBack: String { return self._s[2186]! } - public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2187]! } - public var TwoStepAuth_EmailHelp: String { return self._s[2188]! } - public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2189]!, self._r[2189]!, [_0]) - } - public var Channel_Info_Management: String { return self._s[2190]! } - public var Passport_FieldIdentityUploadHelp: String { return self._s[2191]! } - public var Stickers_FrequentlyUsed: String { return self._s[2192]! } - public var Channel_BanUser_PermissionSendMessages: String { return self._s[2193]! } - public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2195]! } - public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2196]!, self._r[2196]!, [_1, "\(_2)"]) - } - public var Passport_Address_EditResidentialAddress: String { return self._s[2197]! } - public var PrivacyPolicy_DeclineTitle: String { return self._s[2198]! } - public var CreatePoll_TextHeader: String { return self._s[2199]! } - public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2200]!, self._r[2200]!, [_0]) } - public var PhotoEditor_QualityMedium: String { return self._s[2201]! } - public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2202]! } - public var Conversation_StatusKickedFromChannel: String { return self._s[2204]! } - public var CheckoutInfo_ReceiverInfoName: String { return self._s[2205]! } - public var Group_ErrorSendRestrictedStickers: String { return self._s[2206]! } + public var GroupRemoved_ViewUserInfo: String { return self._s[2201]! } + public var Conversation_BlockUser: String { return self._s[2202]! } + public var Month_GenJanuary: String { return self._s[2203]! } + public var ChatSettings_TextSize: String { return self._s[2204]! } + public var Notification_PassportValuePhone: String { return self._s[2205]! } + public var Passport_Language_ne: String { return self._s[2206]! } + public var Notification_CallBack: String { return self._s[2207]! } + public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[2208]! } + public var TwoStepAuth_EmailHelp: String { return self._s[2209]! } + public func Time_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2210]!, self._r[2210]!, [_0]) + } + public var Channel_Info_Management: String { return self._s[2211]! } + public var Passport_FieldIdentityUploadHelp: String { return self._s[2212]! } + public var Stickers_FrequentlyUsed: String { return self._s[2213]! } + public var Channel_BanUser_PermissionSendMessages: String { return self._s[2214]! } + public var Passport_Address_OneOfTypeUtilityBill: String { return self._s[2216]! } + public func LOCAL_CHANNEL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2217]!, self._r[2217]!, [_1, "\(_2)"]) + } + public var TwoFactorSetup_Password_Title: String { return self._s[2218]! } + public var Passport_Address_EditResidentialAddress: String { return self._s[2219]! } + public var PrivacyPolicy_DeclineTitle: String { return self._s[2220]! } + public var CreatePoll_TextHeader: String { return self._s[2221]! } + public func Checkout_SavePasswordTimeoutAndTouchId(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2222]!, self._r[2222]!, [_0]) + } + public var PhotoEditor_QualityMedium: String { return self._s[2223]! } + public var InfoPlist_NSMicrophoneUsageDescription: String { return self._s[2224]! } + public var Conversation_StatusKickedFromChannel: String { return self._s[2226]! } + public var CheckoutInfo_ReceiverInfoName: String { return self._s[2227]! } + public var Group_ErrorSendRestrictedStickers: String { return self._s[2228]! } public func Conversation_RestrictedInlineTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2207]!, self._r[2207]!, [_0]) - } - public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2208]!, self._r[2208]!, [_1]) - } - public var LogoutOptions_LogOutWalletInfo: String { return self._s[2209]! } - public var Conversation_LinkDialogOpen: String { return self._s[2211]! } - public var VoiceOver_Chat_PollNoVotes: String { return self._s[2212]! } - public var Settings_Username: String { return self._s[2214]! } - public var Conversation_Block: String { return self._s[2216]! } - public var Wallpaper_Wallpaper: String { return self._s[2217]! } - public var SocksProxySetup_UseProxy: String { return self._s[2219]! } - public var Wallet_Send_Confirmation: String { return self._s[2220]! } - public var EditTheme_UploadEditedTheme: String { return self._s[2221]! } - public var UserInfo_ShareMyContactInfo: String { return self._s[2222]! } - public var MessageTimer_Forever: String { return self._s[2223]! } - public var Privacy_Calls_WhoCanCallMe: String { return self._s[2224]! } - public var PhotoEditor_DiscardChanges: String { return self._s[2225]! } - public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2226]! } - public var Passport_Language_da: String { return self._s[2227]! } - public var SocksProxySetup_PortPlaceholder: String { return self._s[2228]! } - public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2229]!, self._r[2229]!, [_0]) } - public var Passport_Address_EditPassportRegistration: String { return self._s[2230]! } + public func Channel_AdminLog_MessageTransferedName(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2230]!, self._r[2230]!, [_1]) + } + public var LogoutOptions_LogOutWalletInfo: String { return self._s[2231]! } + public var TwoFactorSetup_Email_SkipConfirmationTitle: String { return self._s[2232]! } + public var Conversation_LinkDialogOpen: String { return self._s[2234]! } + public var TwoFactorSetup_Hint_Title: String { return self._s[2235]! } + public var VoiceOver_Chat_PollNoVotes: String { return self._s[2236]! } + public var Settings_Username: String { return self._s[2238]! } + public var Conversation_Block: String { return self._s[2240]! } + public var Wallpaper_Wallpaper: String { return self._s[2241]! } + public var SocksProxySetup_UseProxy: String { return self._s[2243]! } + public var Wallet_Send_Confirmation: String { return self._s[2244]! } + public var EditTheme_UploadEditedTheme: String { return self._s[2245]! } + public var UserInfo_ShareMyContactInfo: String { return self._s[2246]! } + public var MessageTimer_Forever: String { return self._s[2247]! } + public var Privacy_Calls_WhoCanCallMe: String { return self._s[2248]! } + public var PhotoEditor_DiscardChanges: String { return self._s[2249]! } + public var AuthSessions_TerminateOtherSessionsHelp: String { return self._s[2250]! } + public var Passport_Language_da: String { return self._s[2251]! } + public var SocksProxySetup_PortPlaceholder: String { return self._s[2252]! } + public func SecretGIF_NotViewedYet(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2253]!, self._r[2253]!, [_0]) + } + public var Passport_Address_EditPassportRegistration: String { return self._s[2254]! } public func Channel_AdminLog_MessageChangedGroupAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2232]!, self._r[2232]!, [_0]) + return formatWithArgumentRanges(self._s[2256]!, self._r[2256]!, [_0]) } - public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2234]! } - public var Conversation_SearchByName_Prefix: String { return self._s[2235]! } - public var Conversation_PinnedPoll: String { return self._s[2236]! } - public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2237]! } + public var Passport_Identity_ResidenceCountryPlaceholder: String { return self._s[2258]! } + public var Conversation_SearchByName_Prefix: String { return self._s[2259]! } + public var Conversation_PinnedPoll: String { return self._s[2260]! } + public var Conversation_EmptyGifPanelPlaceholder: String { return self._s[2261]! } public func PUSH_ENCRYPTION_ACCEPT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2238]!, self._r[2238]!, [_1]) + return formatWithArgumentRanges(self._s[2262]!, self._r[2262]!, [_1]) } - public var WallpaperSearch_ColorPurple: String { return self._s[2239]! } - public var Cache_ByPeerHeader: String { return self._s[2240]! } + public var WallpaperSearch_ColorPurple: String { return self._s[2263]! } + public var Cache_ByPeerHeader: String { return self._s[2264]! } public func Conversation_EncryptedPlaceholderTitleIncoming(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2241]!, self._r[2241]!, [_0]) + return formatWithArgumentRanges(self._s[2265]!, self._r[2265]!, [_0]) } - public var ChatSettings_AutoDownloadDocuments: String { return self._s[2242]! } - public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2245]! } - public var Wallet_Completed_Title: String { return self._s[2246]! } - public var Notification_PinnedMessage: String { return self._s[2247]! } - public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2249]! } - public var Contacts_SortBy: String { return self._s[2250]! } + public var ChatSettings_AutoDownloadDocuments: String { return self._s[2266]! } + public var Appearance_ThemePreview_Chat_3_Text: String { return self._s[2269]! } + public var Wallet_Completed_Title: String { return self._s[2270]! } + public var Notification_PinnedMessage: String { return self._s[2271]! } + public var TwoFactorSetup_EmailVerification_Placeholder: String { return self._s[2272]! } + public var VoiceOver_Chat_RecordModeVideoMessage: String { return self._s[2274]! } + public var Contacts_SortBy: String { return self._s[2275]! } public func PUSH_CHANNEL_MESSAGE_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2251]!, self._r[2251]!, [_1]) + return formatWithArgumentRanges(self._s[2276]!, self._r[2276]!, [_1]) } public func PUSH_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2253]!, self._r[2253]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2278]!, self._r[2278]!, [_1, _2]) } - public var Call_EncryptionKey_Title: String { return self._s[2254]! } - public var Watch_UserInfo_Service: String { return self._s[2255]! } - public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2257]! } - public var Conversation_Unpin: String { return self._s[2259]! } - public var CancelResetAccount_Title: String { return self._s[2260]! } - public var Map_LiveLocationFor15Minutes: String { return self._s[2261]! } + public var Call_EncryptionKey_Title: String { return self._s[2279]! } + public var Watch_UserInfo_Service: String { return self._s[2280]! } + public var SettingsSearch_Synonyms_Data_SaveEditedPhotos: String { return self._s[2282]! } + public var Conversation_Unpin: String { return self._s[2284]! } + public var CancelResetAccount_Title: String { return self._s[2285]! } + public var Map_LiveLocationFor15Minutes: String { return self._s[2286]! } public func Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2263]!, self._r[2263]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2288]!, self._r[2288]!, [_1, _2, _3]) } - public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2264]! } - public var CallSettings_Title: String { return self._s[2265]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2266]! } - public var PasscodeSettings_EncryptDataHelp: String { return self._s[2268]! } - public var AutoDownloadSettings_Contacts: String { return self._s[2269]! } + public var Group_Members_AddMemberBotErrorNotAllowed: String { return self._s[2289]! } + public var CallSettings_Title: String { return self._s[2290]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground: String { return self._s[2291]! } + public var PasscodeSettings_EncryptDataHelp: String { return self._s[2293]! } + public var AutoDownloadSettings_Contacts: String { return self._s[2294]! } public func Channel_AdminLog_MessageRankName(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2270]!, self._r[2270]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2295]!, self._r[2295]!, [_1, _2]) } - public var Passport_Identity_DocumentDetails: String { return self._s[2271]! } - public var LoginPassword_PasswordHelp: String { return self._s[2272]! } - public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2273]! } - public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2274]! } - public var Checkout_TotalPaidAmount: String { return self._s[2275]! } + public var Passport_Identity_DocumentDetails: String { return self._s[2296]! } + public var LoginPassword_PasswordHelp: String { return self._s[2297]! } + public var SettingsSearch_Synonyms_Data_AutoDownloadUsingWifi: String { return self._s[2298]! } + public var PrivacyLastSeenSettings_CustomShareSettings_Delete: String { return self._s[2299]! } + public var Checkout_TotalPaidAmount: String { return self._s[2300]! } public func FileSize_KB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2276]!, self._r[2276]!, [_0]) + return formatWithArgumentRanges(self._s[2301]!, self._r[2301]!, [_0]) } - public var PasscodeSettings_ChangePasscode: String { return self._s[2277]! } - public var Conversation_SecretLinkPreviewAlert: String { return self._s[2279]! } - public var Privacy_SecretChatsLinkPreviews: String { return self._s[2280]! } + public var PasscodeSettings_ChangePasscode: String { return self._s[2302]! } + public var Conversation_SecretLinkPreviewAlert: String { return self._s[2304]! } + public var Privacy_SecretChatsLinkPreviews: String { return self._s[2305]! } public func PUSH_CHANNEL_MESSAGE_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2281]!, self._r[2281]!, [_1]) + return formatWithArgumentRanges(self._s[2306]!, self._r[2306]!, [_1]) } - public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2282]! } - public var Contacts_InviteFriends: String { return self._s[2284]! } - public var Map_ChooseLocationTitle: String { return self._s[2285]! } - public var Conversation_StopPoll: String { return self._s[2287]! } + public var VoiceOver_Chat_ReplyToYourMessage: String { return self._s[2307]! } + public var Contacts_InviteFriends: String { return self._s[2309]! } + public var Map_ChooseLocationTitle: String { return self._s[2310]! } + public var Conversation_StopPoll: String { return self._s[2312]! } public func WebSearch_SearchNoResultsDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2288]!, self._r[2288]!, [_0]) + return formatWithArgumentRanges(self._s[2313]!, self._r[2313]!, [_0]) } - public var Call_Camera: String { return self._s[2289]! } - public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2290]! } - public var Calls_RatingFeedback: String { return self._s[2291]! } - public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2292]! } - public var Wallet_Alert_OK: String { return self._s[2293]! } - public var NotificationsSound_Pulse: String { return self._s[2294]! } - public var Watch_LastSeen_Lately: String { return self._s[2295]! } - public var ReportGroupLocation_Report: String { return self._s[2298]! } - public var Widget_NoUsers: String { return self._s[2299]! } - public var Conversation_UnvotePoll: String { return self._s[2300]! } - public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2302]! } - public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2303]! } - public var NotificationsSound_Circles: String { return self._s[2304]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2307]! } - public var Wallet_Settings_DeleteWallet: String { return self._s[2308]! } - public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2309]! } - public var Proxy_TooltipUnavailable: String { return self._s[2310]! } - public var Passport_Identity_CountryPlaceholder: String { return self._s[2312]! } - public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2314]! } - public var Conversation_FileDropbox: String { return self._s[2315]! } - public var Notifications_ExceptionsUnmuted: String { return self._s[2316]! } - public var Tour_Text3: String { return self._s[2318]! } - public var Login_ResetAccountProtected_Title: String { return self._s[2320]! } - public var GroupPermission_NoSendMessages: String { return self._s[2321]! } - public var WallpaperSearch_ColorTitle: String { return self._s[2322]! } - public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2323]! } + public var Call_Camera: String { return self._s[2314]! } + public var LogoutOptions_ChangePhoneNumberTitle: String { return self._s[2315]! } + public var Calls_RatingFeedback: String { return self._s[2316]! } + public var GroupInfo_BroadcastListNamePlaceholder: String { return self._s[2317]! } + public var Wallet_Alert_OK: String { return self._s[2318]! } + public var NotificationsSound_Pulse: String { return self._s[2319]! } + public var Watch_LastSeen_Lately: String { return self._s[2320]! } + public var ReportGroupLocation_Report: String { return self._s[2323]! } + public var Widget_NoUsers: String { return self._s[2324]! } + public var Conversation_UnvotePoll: String { return self._s[2325]! } + public var SettingsSearch_Synonyms_Privacy_ProfilePhoto: String { return self._s[2327]! } + public var Privacy_ProfilePhoto_WhoCanSeeMyPhoto: String { return self._s[2328]! } + public var NotificationsSound_Circles: String { return self._s[2329]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Title: String { return self._s[2332]! } + public var Wallet_Settings_DeleteWallet: String { return self._s[2333]! } + public var TwoStepAuth_RecoveryCodeExpired: String { return self._s[2334]! } + public var Proxy_TooltipUnavailable: String { return self._s[2335]! } + public var Passport_Identity_CountryPlaceholder: String { return self._s[2337]! } + public var GroupInfo_Permissions_SlowmodeInfo: String { return self._s[2339]! } + public var Conversation_FileDropbox: String { return self._s[2340]! } + public var Notifications_ExceptionsUnmuted: String { return self._s[2341]! } + public var Tour_Text3: String { return self._s[2343]! } + public var Login_ResetAccountProtected_Title: String { return self._s[2345]! } + public var GroupPermission_NoSendMessages: String { return self._s[2346]! } + public var WallpaperSearch_ColorTitle: String { return self._s[2347]! } + public var ChatAdmins_AllMembersAreAdminsOnHelp: String { return self._s[2348]! } public func Conversation_LiveLocationYouAnd(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2325]!, self._r[2325]!, [_0]) + return formatWithArgumentRanges(self._s[2350]!, self._r[2350]!, [_0]) } - public var GroupInfo_AddParticipantTitle: String { return self._s[2326]! } - public var Checkout_ShippingOption_Title: String { return self._s[2327]! } - public var ChatSettings_AutoDownloadTitle: String { return self._s[2328]! } + public var GroupInfo_AddParticipantTitle: String { return self._s[2351]! } + public var Checkout_ShippingOption_Title: String { return self._s[2352]! } + public var ChatSettings_AutoDownloadTitle: String { return self._s[2353]! } public func DialogList_SingleTypingSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2329]!, self._r[2329]!, [_0]) + return formatWithArgumentRanges(self._s[2354]!, self._r[2354]!, [_0]) } public func ChatSettings_AutoDownloadSettings_TypeVideo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2330]!, self._r[2330]!, [_0]) + return formatWithArgumentRanges(self._s[2355]!, self._r[2355]!, [_0]) } - public var Channel_Management_LabelAdministrator: String { return self._s[2331]! } - public var EditTheme_FileReadError: String { return self._s[2332]! } - public var OwnershipTransfer_ComeBackLater: String { return self._s[2333]! } - public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2334]! } - public var AutoDownloadSettings_Photos: String { return self._s[2336]! } - public var Appearance_PreviewIncomingText: String { return self._s[2337]! } - public var ChatList_Context_MarkAllAsRead: String { return self._s[2338]! } - public var ChannelInfo_ConfirmLeave: String { return self._s[2339]! } - public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2340]! } - public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2341]! } - public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2342]! } - public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2343]! } - public var GroupInfo_SetGroupPhotoStop: String { return self._s[2344]! } - public var Notification_SecretChatScreenshot: String { return self._s[2345]! } - public var AccessDenied_Wallpapers: String { return self._s[2346]! } - public var ChatList_Context_Mute: String { return self._s[2348]! } - public var Passport_Address_City: String { return self._s[2349]! } - public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2350]! } - public var Appearance_ThemeCarouselClassic: String { return self._s[2351]! } - public var SocksProxySetup_SecretPlaceholder: String { return self._s[2352]! } - public var AccessDenied_LocationDisabled: String { return self._s[2353]! } - public var Group_Location_Title: String { return self._s[2354]! } - public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2356]! } - public var GroupInfo_Sound: String { return self._s[2357]! } - public var ChannelInfo_ScamChannelWarning: String { return self._s[2358]! } - public var Stickers_RemoveFromFavorites: String { return self._s[2359]! } - public var Contacts_Title: String { return self._s[2360]! } - public var EditTheme_ThemeTemplateAlertText: String { return self._s[2361]! } - public var Passport_Language_fr: String { return self._s[2362]! } - public var Notifications_ResetAllNotifications: String { return self._s[2363]! } - public var PrivacySettings_SecurityTitle: String { return self._s[2366]! } - public var Checkout_NewCard_Title: String { return self._s[2367]! } - public var Login_HaveNotReceivedCodeInternal: String { return self._s[2368]! } - public var Conversation_ForwardChats: String { return self._s[2369]! } - public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2371]! } - public var PasscodeSettings_4DigitCode: String { return self._s[2372]! } - public var Settings_FAQ: String { return self._s[2374]! } - public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2375]! } - public var Conversation_ContextMenuForward: String { return self._s[2376]! } - public var VoiceOver_Chat_YourPhoto: String { return self._s[2379]! } - public var PrivacyPolicy_Title: String { return self._s[2382]! } - public var Notifications_TextTone: String { return self._s[2383]! } - public var Profile_CreateNewContact: String { return self._s[2384]! } - public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2385]! } - public var Call_Speaker: String { return self._s[2387]! } - public var AutoNightTheme_AutomaticSection: String { return self._s[2388]! } - public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2390]! } - public var Channel_Username_InvalidCharacters: String { return self._s[2391]! } + public var Channel_Management_LabelAdministrator: String { return self._s[2356]! } + public var EditTheme_FileReadError: String { return self._s[2357]! } + public var OwnershipTransfer_ComeBackLater: String { return self._s[2358]! } + public var PrivacyLastSeenSettings_NeverShareWith_Placeholder: String { return self._s[2359]! } + public var AutoDownloadSettings_Photos: String { return self._s[2361]! } + public var Appearance_PreviewIncomingText: String { return self._s[2362]! } + public var ChatList_Context_MarkAllAsRead: String { return self._s[2363]! } + public var ChannelInfo_ConfirmLeave: String { return self._s[2364]! } + public var MediaPicker_MomentsDateRangeSameMonthYearFormat: String { return self._s[2365]! } + public var Passport_Identity_DocumentNumberPlaceholder: String { return self._s[2366]! } + public var Channel_AdminLogFilter_EventsNewMembers: String { return self._s[2367]! } + public var PasscodeSettings_AutoLock_IfAwayFor_5minutes: String { return self._s[2368]! } + public var GroupInfo_SetGroupPhotoStop: String { return self._s[2369]! } + public var Notification_SecretChatScreenshot: String { return self._s[2370]! } + public var AccessDenied_Wallpapers: String { return self._s[2371]! } + public var ChatList_Context_Mute: String { return self._s[2373]! } + public var Passport_Address_City: String { return self._s[2374]! } + public var InfoPlist_NSPhotoLibraryAddUsageDescription: String { return self._s[2375]! } + public var Appearance_ThemeCarouselClassic: String { return self._s[2376]! } + public var SocksProxySetup_SecretPlaceholder: String { return self._s[2377]! } + public var AccessDenied_LocationDisabled: String { return self._s[2378]! } + public var Group_Location_Title: String { return self._s[2379]! } + public var SocksProxySetup_HostnamePlaceholder: String { return self._s[2381]! } + public var GroupInfo_Sound: String { return self._s[2382]! } + public var ChannelInfo_ScamChannelWarning: String { return self._s[2383]! } + public var Stickers_RemoveFromFavorites: String { return self._s[2384]! } + public var Contacts_Title: String { return self._s[2385]! } + public var EditTheme_ThemeTemplateAlertText: String { return self._s[2386]! } + public var Passport_Language_fr: String { return self._s[2387]! } + public var TwoFactorSetup_EmailVerification_Action: String { return self._s[2388]! } + public var Notifications_ResetAllNotifications: String { return self._s[2389]! } + public var PrivacySettings_SecurityTitle: String { return self._s[2392]! } + public var Checkout_NewCard_Title: String { return self._s[2393]! } + public var Login_HaveNotReceivedCodeInternal: String { return self._s[2394]! } + public var Conversation_ForwardChats: String { return self._s[2395]! } + public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[2397]! } + public var PasscodeSettings_4DigitCode: String { return self._s[2398]! } + public var Settings_FAQ: String { return self._s[2400]! } + public var AutoDownloadSettings_DocumentsTitle: String { return self._s[2401]! } + public var Conversation_ContextMenuForward: String { return self._s[2402]! } + public var VoiceOver_Chat_YourPhoto: String { return self._s[2405]! } + public var PrivacyPolicy_Title: String { return self._s[2408]! } + public var Notifications_TextTone: String { return self._s[2409]! } + public var Profile_CreateNewContact: String { return self._s[2410]! } + public var PrivacyPhoneNumberSettings_WhoCanSeeMyPhoneNumber: String { return self._s[2411]! } + public var TwoFactorSetup_EmailVerification_Title: String { return self._s[2413]! } + public var Call_Speaker: String { return self._s[2414]! } + public var AutoNightTheme_AutomaticSection: String { return self._s[2415]! } + public var Channel_OwnershipTransfer_EnterPassword: String { return self._s[2417]! } + public var Channel_Username_InvalidCharacters: String { return self._s[2418]! } public func Channel_AdminLog_MessageChangedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2392]!, self._r[2392]!, [_0]) + return formatWithArgumentRanges(self._s[2419]!, self._r[2419]!, [_0]) } - public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2393]! } - public var PrivacySettings_LastSeenTitle: String { return self._s[2394]! } - public var Channel_AdminLog_CanInviteUsers: String { return self._s[2395]! } - public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2396]! } - public var OwnershipTransfer_SecurityCheck: String { return self._s[2397]! } - public var Conversation_MessageDeliveryFailed: String { return self._s[2398]! } - public var Watch_ChatList_NoConversationsText: String { return self._s[2399]! } - public var Bot_Unblock: String { return self._s[2400]! } - public var TextFormat_Italic: String { return self._s[2401]! } - public var WallpaperSearch_ColorPink: String { return self._s[2402]! } - public var Settings_About_Help: String { return self._s[2403]! } - public var SearchImages_Title: String { return self._s[2404]! } - public var Weekday_Wednesday: String { return self._s[2405]! } - public var Conversation_ClousStorageInfo_Description1: String { return self._s[2406]! } - public var ExplicitContent_AlertTitle: String { return self._s[2407]! } + public var AutoDownloadSettings_AutodownloadFiles: String { return self._s[2420]! } + public var PrivacySettings_LastSeenTitle: String { return self._s[2421]! } + public var Channel_AdminLog_CanInviteUsers: String { return self._s[2422]! } + public var SettingsSearch_Synonyms_Privacy_Data_ClearPaymentsInfo: String { return self._s[2423]! } + public var OwnershipTransfer_SecurityCheck: String { return self._s[2424]! } + public var Conversation_MessageDeliveryFailed: String { return self._s[2425]! } + public var Watch_ChatList_NoConversationsText: String { return self._s[2426]! } + public var Bot_Unblock: String { return self._s[2427]! } + public var TextFormat_Italic: String { return self._s[2428]! } + public var WallpaperSearch_ColorPink: String { return self._s[2429]! } + public var Settings_About_Help: String { return self._s[2430]! } + public var SearchImages_Title: String { return self._s[2431]! } + public var Weekday_Wednesday: String { return self._s[2432]! } + public var Conversation_ClousStorageInfo_Description1: String { return self._s[2433]! } + public var ExplicitContent_AlertTitle: String { return self._s[2434]! } public func Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2408]!, self._r[2408]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2435]!, self._r[2435]!, [_1, _2, _3]) } - public var Channel_DiscussionGroup_Create: String { return self._s[2409]! } - public var Weekday_Thursday: String { return self._s[2410]! } - public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2411]! } - public var Channel_Members_AddMembersHelp: String { return self._s[2412]! } + public var Channel_DiscussionGroup_Create: String { return self._s[2436]! } + public var Weekday_Thursday: String { return self._s[2437]! } + public var Channel_BanUser_PermissionChangeGroupInfo: String { return self._s[2438]! } + public var Channel_Members_AddMembersHelp: String { return self._s[2439]! } public func Checkout_SavePasswordTimeout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2413]!, self._r[2413]!, [_0]) - } - public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2414]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2415]! } - public var Passport_RequestedInformation: String { return self._s[2416]! } - public var Login_PhoneAndCountryHelp: String { return self._s[2417]! } - public var Conversation_EncryptionProcessing: String { return self._s[2419]! } - public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2420]! } - public var PhotoEditor_EnhanceTool: String { return self._s[2422]! } - public var Channel_Setup_Title: String { return self._s[2423]! } - public var Conversation_SearchPlaceholder: String { return self._s[2424]! } - public var AccessDenied_LocationAlwaysDenied: String { return self._s[2425]! } - public var Checkout_ErrorGeneric: String { return self._s[2426]! } - public var Passport_Language_hu: String { return self._s[2427]! } - public var Wallet_Month_ShortSeptember: String { return self._s[2428]! } - public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2430]!, self._r[2430]!, [_0]) - } - public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2433]!, self._r[2433]!, [_1]) - } - public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2434]! } - public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2435]!, self._r[2435]!, [_0]) - } - public var Conversation_CloudStorageInfo_Title: String { return self._s[2436]! } - public var Group_Location_Info: String { return self._s[2437]! } - public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2438]! } - public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2439]! } - public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2440]!, self._r[2440]!, [_0]) } - public var Conversation_ClearPrivateHistory: String { return self._s[2441]! } - public var ContactInfo_PhoneLabelHome: String { return self._s[2442]! } - public var Appearance_RemoveThemeConfirmation: String { return self._s[2443]! } - public var PrivacySettings_LastSeenContacts: String { return self._s[2444]! } - public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2445]!, self._r[2445]!, [_0]) + public var Channel_DiscussionGroup_LinkGroup: String { return self._s[2441]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsVibrate: String { return self._s[2442]! } + public var Passport_RequestedInformation: String { return self._s[2443]! } + public var Login_PhoneAndCountryHelp: String { return self._s[2444]! } + public var Conversation_EncryptionProcessing: String { return self._s[2446]! } + public var Notifications_PermissionsSuppressWarningTitle: String { return self._s[2447]! } + public var PhotoEditor_EnhanceTool: String { return self._s[2449]! } + public var Channel_Setup_Title: String { return self._s[2450]! } + public var Conversation_SearchPlaceholder: String { return self._s[2451]! } + public var AccessDenied_LocationAlwaysDenied: String { return self._s[2452]! } + public var Checkout_ErrorGeneric: String { return self._s[2453]! } + public var Passport_Language_hu: String { return self._s[2454]! } + public var Wallet_Month_ShortSeptember: String { return self._s[2455]! } + public func Passport_Identity_UploadOneOfScan(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2457]!, self._r[2457]!, [_0]) } - public var Passport_Language_cs: String { return self._s[2446]! } - public var Message_PinnedAnimationMessage: String { return self._s[2448]! } - public var Passport_Identity_ReverseSideHelp: String { return self._s[2450]! } - public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2451]! } - public var Wallet_Info_TransactionTo: String { return self._s[2453]! } - public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2454]! } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2455]! } - public var Embed_PlayingInPIP: String { return self._s[2456]! } - public var AutoNightTheme_ScheduleSection: String { return self._s[2457]! } - public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2458]!, self._r[2458]!, [_0]) - } - public var MediaPicker_LivePhotoDescription: String { return self._s[2459]! } - public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { + public func PUSH_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2460]!, self._r[2460]!, [_1]) } - public var Notification_PaymentSent: String { return self._s[2461]! } - public var PhotoEditor_CurvesGreen: String { return self._s[2462]! } - public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2463]! } - public var SaveIncomingPhotosSettings_Title: String { return self._s[2464]! } - public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2465]! } - public var VoiceOver_Chat_PagePreview: String { return self._s[2466]! } + public var ChatList_DeleteSavedMessagesConfirmationTitle: String { return self._s[2461]! } + public func UserInfo_BlockConfirmationTitle(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2462]!, self._r[2462]!, [_0]) + } + public var Conversation_CloudStorageInfo_Title: String { return self._s[2463]! } + public var Group_Location_Info: String { return self._s[2464]! } + public var PhotoEditor_CropAspectRatioSquare: String { return self._s[2465]! } + public var Permissions_PeopleNearbyAllow_v0: String { return self._s[2466]! } + public func Notification_Exceptions_MutedUntil(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2467]!, self._r[2467]!, [_0]) + } + public var Conversation_ClearPrivateHistory: String { return self._s[2468]! } + public var ContactInfo_PhoneLabelHome: String { return self._s[2469]! } + public var Appearance_RemoveThemeConfirmation: String { return self._s[2470]! } + public var PrivacySettings_LastSeenContacts: String { return self._s[2471]! } + public func ChangePhone_ErrorOccupied(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2472]!, self._r[2472]!, [_0]) + } + public var Passport_Language_cs: String { return self._s[2473]! } + public var Message_PinnedAnimationMessage: String { return self._s[2475]! } + public var Passport_Identity_ReverseSideHelp: String { return self._s[2477]! } + public var SettingsSearch_Synonyms_Data_Storage_Title: String { return self._s[2478]! } + public var Wallet_Info_TransactionTo: String { return self._s[2480]! } + public var ChatList_DeleteForEveryoneConfirmationText: String { return self._s[2481]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndTouchId: String { return self._s[2482]! } + public var Embed_PlayingInPIP: String { return self._s[2483]! } + public var AutoNightTheme_ScheduleSection: String { return self._s[2484]! } + public func Call_EmojiDescription(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2485]!, self._r[2485]!, [_0]) + } + public var MediaPicker_LivePhotoDescription: String { return self._s[2486]! } + public func Channel_AdminLog_MessageRestrictedName(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2487]!, self._r[2487]!, [_1]) + } + public var Notification_PaymentSent: String { return self._s[2488]! } + public var PhotoEditor_CurvesGreen: String { return self._s[2489]! } + public var Notification_Exceptions_PreviewAlwaysOff: String { return self._s[2490]! } + public var SaveIncomingPhotosSettings_Title: String { return self._s[2491]! } + public var NotificationSettings_ShowNotificationsAllAccounts: String { return self._s[2492]! } + public var VoiceOver_Chat_PagePreview: String { return self._s[2493]! } public func PUSH_MESSAGE_SCREENSHOT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2469]!, self._r[2469]!, [_1]) - } - public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2470]!, self._r[2470]!, [_1]) - } - public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2471]!, self._r[2471]!, [_1]) - } - public var NetworkUsageSettings_CallDataSection: String { return self._s[2473]! } - public var PasscodeSettings_HelpTop: String { return self._s[2474]! } - public var Conversation_WalletRequiredTitle: String { return self._s[2475]! } - public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2476]! } - public var Passport_Address_TypeRentalAgreement: String { return self._s[2477]! } - public var EditTheme_ShortLink: String { return self._s[2478]! } - public var ProxyServer_VoiceOver_Active: String { return self._s[2479]! } - public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2480]! } - public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2481]! } - public var Call_Accept: String { return self._s[2483]! } - public var GroupRemoved_RemoveInfo: String { return self._s[2484]! } - public var Month_GenMarch: String { return self._s[2486]! } - public var PhotoEditor_ShadowsTool: String { return self._s[2487]! } - public var LoginPassword_Title: String { return self._s[2488]! } - public var Call_End: String { return self._s[2489]! } - public var Watch_Conversation_GroupInfo: String { return self._s[2490]! } - public var VoiceOver_Chat_Contact: String { return self._s[2491]! } - public var EditTheme_Create_Preview_IncomingText: String { return self._s[2492]! } - public var CallSettings_Always: String { return self._s[2493]! } - public var CallFeedback_Success: String { return self._s[2494]! } - public var TwoStepAuth_SetupHint: String { return self._s[2495]! } - public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2496]!, self._r[2496]!, [_1]) } - public var ConversationProfile_UsersTooMuchError: String { return self._s[2497]! } - public var Login_PhoneTitle: String { return self._s[2498]! } - public var Passport_FieldPhoneHelp: String { return self._s[2499]! } - public var Weekday_ShortSunday: String { return self._s[2500]! } - public var Passport_InfoFAQ_URL: String { return self._s[2501]! } - public var ContactInfo_Job: String { return self._s[2503]! } - public var UserInfo_InviteBotToGroup: String { return self._s[2504]! } - public var Appearance_ThemeCarouselNightBlue: String { return self._s[2505]! } - public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2506]! } - public var Invite_ChannelsTooMuch: String { return self._s[2507]! } - public var Wallet_Send_ConfirmationConfirm: String { return self._s[2508]! } - public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2509]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2510]! } - public var Wallet_Receive_AmountText: String { return self._s[2511]! } - public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2512]! } - public var CallFeedback_ReasonNoise: String { return self._s[2513]! } - public var Appearance_AppIconDefault: String { return self._s[2515]! } - public var Passport_Identity_AddInternalPassport: String { return self._s[2516]! } - public var MediaPicker_AddCaption: String { return self._s[2517]! } - public var CallSettings_TabIconDescription: String { return self._s[2518]! } + public func PUSH_MESSAGE_PHOTO_SECRET(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2497]!, self._r[2497]!, [_1]) + } + public func ApplyLanguage_UnsufficientDataText(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2498]!, self._r[2498]!, [_1]) + } + public var NetworkUsageSettings_CallDataSection: String { return self._s[2500]! } + public var PasscodeSettings_HelpTop: String { return self._s[2501]! } + public var Conversation_WalletRequiredTitle: String { return self._s[2502]! } + public var Group_OwnershipTransfer_ErrorAdminsTooMuch: String { return self._s[2503]! } + public var Passport_Address_TypeRentalAgreement: String { return self._s[2504]! } + public var EditTheme_ShortLink: String { return self._s[2505]! } + public var ProxyServer_VoiceOver_Active: String { return self._s[2506]! } + public var ReportPeer_ReasonOther_Placeholder: String { return self._s[2507]! } + public var CheckoutInfo_ErrorPhoneInvalid: String { return self._s[2508]! } + public var Call_Accept: String { return self._s[2510]! } + public var GroupRemoved_RemoveInfo: String { return self._s[2511]! } + public var Month_GenMarch: String { return self._s[2513]! } + public var PhotoEditor_ShadowsTool: String { return self._s[2514]! } + public var LoginPassword_Title: String { return self._s[2515]! } + public var Call_End: String { return self._s[2516]! } + public var Watch_Conversation_GroupInfo: String { return self._s[2517]! } + public var VoiceOver_Chat_Contact: String { return self._s[2518]! } + public var EditTheme_Create_Preview_IncomingText: String { return self._s[2519]! } + public var CallSettings_Always: String { return self._s[2520]! } + public var CallFeedback_Success: String { return self._s[2521]! } + public var TwoStepAuth_SetupHint: String { return self._s[2522]! } + public func AddContact_ContactWillBeSharedAfterMutual(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2523]!, self._r[2523]!, [_1]) + } + public var ConversationProfile_UsersTooMuchError: String { return self._s[2524]! } + public var Login_PhoneTitle: String { return self._s[2525]! } + public var Passport_FieldPhoneHelp: String { return self._s[2526]! } + public var Weekday_ShortSunday: String { return self._s[2527]! } + public var Passport_InfoFAQ_URL: String { return self._s[2528]! } + public var ContactInfo_Job: String { return self._s[2530]! } + public var UserInfo_InviteBotToGroup: String { return self._s[2531]! } + public var Appearance_ThemeCarouselNightBlue: String { return self._s[2532]! } + public var TwoFactorSetup_Email_Text: String { return self._s[2533]! } + public var TwoStepAuth_PasswordRemovePassportConfirmation: String { return self._s[2534]! } + public var Invite_ChannelsTooMuch: String { return self._s[2535]! } + public var Wallet_Send_ConfirmationConfirm: String { return self._s[2536]! } + public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[2537]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsPreview: String { return self._s[2538]! } + public var Wallet_Receive_AmountText: String { return self._s[2539]! } + public var Passport_DeletePersonalDetailsConfirmation: String { return self._s[2540]! } + public var CallFeedback_ReasonNoise: String { return self._s[2541]! } + public var Appearance_AppIconDefault: String { return self._s[2543]! } + public var Passport_Identity_AddInternalPassport: String { return self._s[2544]! } + public var MediaPicker_AddCaption: String { return self._s[2545]! } + public var CallSettings_TabIconDescription: String { return self._s[2546]! } public func VoiceOver_Chat_Caption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2519]!, self._r[2519]!, [_0]) + return formatWithArgumentRanges(self._s[2547]!, self._r[2547]!, [_0]) } - public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2520]! } - public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2521]! } - public var Passport_Identity_TypePersonalDetails: String { return self._s[2522]! } - public var DialogList_SearchSectionRecent: String { return self._s[2523]! } - public var PrivacyPolicy_DeclineMessage: String { return self._s[2524]! } - public var LogoutOptions_ClearCacheText: String { return self._s[2527]! } - public var LastSeen_WithinAWeek: String { return self._s[2528]! } - public var ChannelMembers_GroupAdminsTitle: String { return self._s[2529]! } - public var Conversation_CloudStorage_ChatStatus: String { return self._s[2531]! } - public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2532]! } + public var ChatList_UndoArchiveHiddenTitle: String { return self._s[2548]! } + public var Privacy_GroupsAndChannels_AlwaysAllow: String { return self._s[2549]! } + public var Passport_Identity_TypePersonalDetails: String { return self._s[2550]! } + public var DialogList_SearchSectionRecent: String { return self._s[2551]! } + public var PrivacyPolicy_DeclineMessage: String { return self._s[2552]! } + public var LogoutOptions_ClearCacheText: String { return self._s[2555]! } + public var LastSeen_WithinAWeek: String { return self._s[2556]! } + public var ChannelMembers_GroupAdminsTitle: String { return self._s[2557]! } + public var Conversation_CloudStorage_ChatStatus: String { return self._s[2559]! } + public var VoiceOver_Media_PlaybackRateNormal: String { return self._s[2560]! } public func AddContact_SharedContactExceptionInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2533]!, self._r[2533]!, [_0]) + return formatWithArgumentRanges(self._s[2561]!, self._r[2561]!, [_0]) } - public var Passport_Address_TypeResidentialAddress: String { return self._s[2534]! } - public var Conversation_StatusLeftGroup: String { return self._s[2535]! } - public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2536]! } - public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2538]! } - public var GroupPermission_AddSuccess: String { return self._s[2539]! } - public var PhotoEditor_BlurToolRadial: String { return self._s[2541]! } - public var Conversation_ContextMenuCopy: String { return self._s[2542]! } - public var AccessDenied_CallMicrophone: String { return self._s[2543]! } + public var Passport_Address_TypeResidentialAddress: String { return self._s[2562]! } + public var Conversation_StatusLeftGroup: String { return self._s[2563]! } + public var SocksProxySetup_ProxyDetailsTitle: String { return self._s[2564]! } + public var SettingsSearch_Synonyms_Calls_Title: String { return self._s[2566]! } + public var GroupPermission_AddSuccess: String { return self._s[2567]! } + public var PhotoEditor_BlurToolRadial: String { return self._s[2569]! } + public var Conversation_ContextMenuCopy: String { return self._s[2570]! } + public var AccessDenied_CallMicrophone: String { return self._s[2571]! } public func Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2544]!, self._r[2544]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2572]!, self._r[2572]!, [_1, _2, _3]) } - public var Login_InvalidFirstNameError: String { return self._s[2545]! } - public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2546]! } - public var Checkout_PaymentMethod_New: String { return self._s[2547]! } - public var ShareMenu_CopyShareLinkGame: String { return self._s[2548]! } - public var PhotoEditor_QualityTool: String { return self._s[2549]! } - public var Login_SendCodeViaSms: String { return self._s[2550]! } - public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2551]! } - public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2552]! } - public var Wallet_Receive_CopyAddress: String { return self._s[2553]! } - public var Login_EmailNotConfiguredError: String { return self._s[2554]! } - public var SocksProxySetup_Status: String { return self._s[2555]! } - public var PrivacyPolicy_Accept: String { return self._s[2556]! } - public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2557]! } - public var Appearance_AppIconClassicX: String { return self._s[2558]! } + public var Login_InvalidFirstNameError: String { return self._s[2573]! } + public var Notifications_Badge_CountUnreadMessages_InfoOn: String { return self._s[2574]! } + public var Checkout_PaymentMethod_New: String { return self._s[2575]! } + public var ShareMenu_CopyShareLinkGame: String { return self._s[2576]! } + public var PhotoEditor_QualityTool: String { return self._s[2577]! } + public var Login_SendCodeViaSms: String { return self._s[2578]! } + public var SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor: String { return self._s[2579]! } + public var Chat_SlowmodeAttachmentLimitReached: String { return self._s[2580]! } + public var Wallet_Receive_CopyAddress: String { return self._s[2581]! } + public var Login_EmailNotConfiguredError: String { return self._s[2582]! } + public var SocksProxySetup_Status: String { return self._s[2583]! } + public var Conversation_ScheduleMessage_SendWhenOnline: String { return self._s[2584]! } + public var PrivacyPolicy_Accept: String { return self._s[2585]! } + public var Notifications_ExceptionsMessagePlaceholder: String { return self._s[2586]! } + public var Appearance_AppIconClassicX: String { return self._s[2587]! } public func PUSH_CHAT_MESSAGE_TEXT(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2559]!, self._r[2559]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2588]!, self._r[2588]!, [_1, _2, _3]) } - public var OwnershipTransfer_SecurityRequirements: String { return self._s[2560]! } - public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2562]! } - public var AutoNightTheme_Automatic: String { return self._s[2563]! } - public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2564]! } - public var Privacy_ContactsSyncHelp: String { return self._s[2565]! } - public var Cache_Help: String { return self._s[2566]! } - public var Group_ErrorAccessDenied: String { return self._s[2567]! } - public var Passport_Language_fa: String { return self._s[2568]! } - public var Wallet_Intro_Text: String { return self._s[2569]! } - public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2570]! } - public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2571]! } - public var PrivacySettings_LastSeen: String { return self._s[2572]! } + public var OwnershipTransfer_SecurityRequirements: String { return self._s[2589]! } + public var InfoPlist_NSLocationAlwaysUsageDescription: String { return self._s[2591]! } + public var AutoNightTheme_Automatic: String { return self._s[2592]! } + public var Channel_Username_InvalidStartsWithNumber: String { return self._s[2593]! } + public var Privacy_ContactsSyncHelp: String { return self._s[2594]! } + public var Cache_Help: String { return self._s[2595]! } + public var Group_ErrorAccessDenied: String { return self._s[2596]! } + public var Passport_Language_fa: String { return self._s[2597]! } + public var Wallet_Intro_Text: String { return self._s[2598]! } + public var Login_ResetAccountProtected_TimerTitle: String { return self._s[2599]! } + public var VoiceOver_Chat_YourVideoMessage: String { return self._s[2600]! } + public var PrivacySettings_LastSeen: String { return self._s[2601]! } public func DialogList_MultipleTyping(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2573]!, self._r[2573]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2602]!, self._r[2602]!, [_0, _1]) } - public var Wallet_Configuration_Apply: String { return self._s[2577]! } - public var Preview_SaveGif: String { return self._s[2578]! } - public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2579]! } - public var Profile_About: String { return self._s[2580]! } - public var Channel_About_Placeholder: String { return self._s[2581]! } - public var Login_InfoTitle: String { return self._s[2582]! } + public var Wallet_Configuration_Apply: String { return self._s[2606]! } + public var Preview_SaveGif: String { return self._s[2607]! } + public var SettingsSearch_Synonyms_Privacy_TwoStepAuth: String { return self._s[2608]! } + public var Profile_About: String { return self._s[2609]! } + public var Channel_About_Placeholder: String { return self._s[2610]! } + public var Login_InfoTitle: String { return self._s[2611]! } public func TwoStepAuth_SetupPendingEmail(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2583]!, self._r[2583]!, [_0]) + return formatWithArgumentRanges(self._s[2612]!, self._r[2612]!, [_0]) } - public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2584]! } - public var Watch_Suggestion_CantTalk: String { return self._s[2586]! } - public var ContactInfo_Title: String { return self._s[2587]! } - public var Media_ShareThisVideo: String { return self._s[2588]! } - public var Weekday_ShortFriday: String { return self._s[2589]! } - public var AccessDenied_Contacts: String { return self._s[2591]! } - public var Notification_CallIncomingShort: String { return self._s[2592]! } - public var Group_Setup_TypePublic: String { return self._s[2593]! } - public var Notifications_MessageNotificationsExceptions: String { return self._s[2594]! } - public var Notifications_Badge_IncludeChannels: String { return self._s[2595]! } - public var Notifications_MessageNotificationsPreview: String { return self._s[2598]! } - public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2599]! } - public var Group_ErrorAddTooMuchBots: String { return self._s[2600]! } - public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2601]! } - public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2602]! } + public var EditTheme_Expand_Preview_IncomingReplyText: String { return self._s[2613]! } + public var Watch_Suggestion_CantTalk: String { return self._s[2615]! } + public var ContactInfo_Title: String { return self._s[2616]! } + public var Media_ShareThisVideo: String { return self._s[2617]! } + public var Weekday_ShortFriday: String { return self._s[2618]! } + public var AccessDenied_Contacts: String { return self._s[2620]! } + public var Notification_CallIncomingShort: String { return self._s[2621]! } + public var Group_Setup_TypePublic: String { return self._s[2622]! } + public var Notifications_MessageNotificationsExceptions: String { return self._s[2623]! } + public var Notifications_Badge_IncludeChannels: String { return self._s[2624]! } + public var Notifications_MessageNotificationsPreview: String { return self._s[2627]! } + public var ConversationProfile_ErrorCreatingConversation: String { return self._s[2628]! } + public var Group_ErrorAddTooMuchBots: String { return self._s[2629]! } + public var Privacy_GroupsAndChannels_CustomShareHelp: String { return self._s[2630]! } + public var Permissions_CellularDataAllowInSettings_v0: String { return self._s[2631]! } public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2603]!, self._r[2603]!, [_0]) + return formatWithArgumentRanges(self._s[2632]!, self._r[2632]!, [_0]) } - public var DialogList_Typing: String { return self._s[2604]! } - public var CallFeedback_IncludeLogs: String { return self._s[2606]! } - public var Checkout_Phone: String { return self._s[2608]! } - public var Login_InfoFirstNamePlaceholder: String { return self._s[2611]! } - public var Privacy_Calls_Integration: String { return self._s[2612]! } - public var Notifications_PermissionsAllow: String { return self._s[2613]! } - public var TwoStepAuth_AddHintDescription: String { return self._s[2617]! } - public var Settings_ChatSettings: String { return self._s[2618]! } + public var DialogList_Typing: String { return self._s[2633]! } + public var CallFeedback_IncludeLogs: String { return self._s[2635]! } + public var Checkout_Phone: String { return self._s[2637]! } + public var Login_InfoFirstNamePlaceholder: String { return self._s[2640]! } + public var Privacy_Calls_Integration: String { return self._s[2641]! } + public var Notifications_PermissionsAllow: String { return self._s[2642]! } + public var TwoStepAuth_AddHintDescription: String { return self._s[2646]! } + public var Settings_ChatSettings: String { return self._s[2647]! } public func Channel_AdminLog_MessageInvitedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2619]!, self._r[2619]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2648]!, self._r[2648]!, [_1, _2]) } - public var GroupRemoved_DeleteUser: String { return self._s[2621]! } + public var GroupRemoved_DeleteUser: String { return self._s[2650]! } public func Channel_AdminLog_PollStopped(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2622]!, self._r[2622]!, [_0]) + return formatWithArgumentRanges(self._s[2651]!, self._r[2651]!, [_0]) } - public var Wallet_TransactionInfo_FeeInfoURL: String { return self._s[2623]! } + public var Wallet_TransactionInfo_FeeInfoURL: String { return self._s[2652]! } public func PUSH_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2624]!, self._r[2624]!, [_1]) + return formatWithArgumentRanges(self._s[2653]!, self._r[2653]!, [_1]) } - public var Login_ContinueWithLocalization: String { return self._s[2625]! } - public var Watch_Message_ForwardedFrom: String { return self._s[2626]! } - public var TwoStepAuth_EnterEmailCode: String { return self._s[2628]! } - public var Conversation_Unblock: String { return self._s[2629]! } - public var PrivacySettings_DataSettings: String { return self._s[2630]! } - public var Group_PublicLink_Info: String { return self._s[2631]! } + public var Login_ContinueWithLocalization: String { return self._s[2654]! } + public var Watch_Message_ForwardedFrom: String { return self._s[2655]! } + public var TwoStepAuth_EnterEmailCode: String { return self._s[2657]! } + public var Conversation_Unblock: String { return self._s[2658]! } + public var PrivacySettings_DataSettings: String { return self._s[2659]! } + public var Group_PublicLink_Info: String { return self._s[2660]! } public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2632]!, self._r[2632]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2661]!, self._r[2661]!, [_1, _2, _3]) } - public var Notifications_InAppNotificationsVibrate: String { return self._s[2633]! } + public var Notifications_InAppNotificationsVibrate: String { return self._s[2662]! } public func Privacy_GroupsAndChannels_InviteToChannelError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2634]!, self._r[2634]!, [_0, _1]) + return formatWithArgumentRanges(self._s[2663]!, self._r[2663]!, [_0, _1]) } - public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2636]! } - public var PrivacySettings_Passcode: String { return self._s[2638]! } - public var Call_Mute: String { return self._s[2639]! } - public var Wallet_Weekday_Yesterday: String { return self._s[2640]! } - public var Passport_Language_dz: String { return self._s[2641]! } - public var Wallet_Receive_AmountHeader: String { return self._s[2642]! } - public var Passport_Language_tk: String { return self._s[2643]! } + public var Wallet_RestoreFailed_CreateWallet: String { return self._s[2665]! } + public var PrivacySettings_Passcode: String { return self._s[2667]! } + public var Call_Mute: String { return self._s[2668]! } + public var Wallet_Weekday_Yesterday: String { return self._s[2669]! } + public var Passport_Language_dz: String { return self._s[2670]! } + public var Wallet_Receive_AmountHeader: String { return self._s[2671]! } + public var Passport_Language_tk: String { return self._s[2672]! } public func Login_EmailCodeSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2644]!, self._r[2644]!, [_0]) + return formatWithArgumentRanges(self._s[2673]!, self._r[2673]!, [_0]) } - public var Settings_Search: String { return self._s[2645]! } - public var Wallet_Month_ShortFebruary: String { return self._s[2646]! } - public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2647]! } - public var Conversation_ContextMenuReply: String { return self._s[2648]! } - public var WallpaperSearch_ColorBrown: String { return self._s[2649]! } - public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2650]! } - public var Tour_Title1: String { return self._s[2651]! } - public var Wallet_Alert_Cancel: String { return self._s[2652]! } - public var Conversation_ClearGroupHistory: String { return self._s[2654]! } - public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2655]! } - public var WallpaperPreview_Motion: String { return self._s[2656]! } + public var Settings_Search: String { return self._s[2674]! } + public var Wallet_Month_ShortFebruary: String { return self._s[2675]! } + public var InfoPlist_NSPhotoLibraryUsageDescription: String { return self._s[2676]! } + public var Conversation_ContextMenuReply: String { return self._s[2677]! } + public var WallpaperSearch_ColorBrown: String { return self._s[2678]! } + public var Chat_AttachmentMultipleForwardDisabled: String { return self._s[2679]! } + public var Tour_Title1: String { return self._s[2680]! } + public var Wallet_Alert_Cancel: String { return self._s[2681]! } + public var Conversation_ClearGroupHistory: String { return self._s[2683]! } + public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[2684]! } + public var WallpaperPreview_Motion: String { return self._s[2685]! } public func Checkout_PasswordEntry_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2657]!, self._r[2657]!, [_0]) + return formatWithArgumentRanges(self._s[2686]!, self._r[2686]!, [_0]) } - public var Call_RateCall: String { return self._s[2658]! } - public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2659]! } - public var Passport_PasswordCompleteSetup: String { return self._s[2660]! } - public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2661]! } - public var UserInfo_LastNamePlaceholder: String { return self._s[2663]! } + public var Call_RateCall: String { return self._s[2687]! } + public var Channel_AdminLog_BanSendStickersAndGifs: String { return self._s[2688]! } + public var Passport_PasswordCompleteSetup: String { return self._s[2689]! } + public var Conversation_InputTextSilentBroadcastPlaceholder: String { return self._s[2690]! } + public var UserInfo_LastNamePlaceholder: String { return self._s[2692]! } public func Login_WillCallYou(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2665]!, self._r[2665]!, [_0]) + return formatWithArgumentRanges(self._s[2694]!, self._r[2694]!, [_0]) } - public var Compose_Create: String { return self._s[2666]! } - public var Contacts_InviteToTelegram: String { return self._s[2667]! } - public var GroupInfo_Notifications: String { return self._s[2668]! } - public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2670]! } - public var Message_PinnedLiveLocationMessage: String { return self._s[2671]! } - public var Month_GenApril: String { return self._s[2672]! } - public var Appearance_AutoNightTheme: String { return self._s[2673]! } - public var ChatSettings_AutomaticAudioDownload: String { return self._s[2675]! } - public var Login_CodeSentSms: String { return self._s[2677]! } + public var Compose_Create: String { return self._s[2695]! } + public var Contacts_InviteToTelegram: String { return self._s[2696]! } + public var GroupInfo_Notifications: String { return self._s[2697]! } + public var ChatList_DeleteSavedMessagesConfirmationAction: String { return self._s[2699]! } + public var Message_PinnedLiveLocationMessage: String { return self._s[2700]! } + public var Month_GenApril: String { return self._s[2701]! } + public var Appearance_AutoNightTheme: String { return self._s[2702]! } + public var ChatSettings_AutomaticAudioDownload: String { return self._s[2704]! } + public var Login_CodeSentSms: String { return self._s[2706]! } public func UserInfo_UnblockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2678]!, self._r[2678]!, [_0]) + return formatWithArgumentRanges(self._s[2707]!, self._r[2707]!, [_0]) } - public var EmptyGroupInfo_Line3: String { return self._s[2679]! } - public var LogoutOptions_ContactSupportText: String { return self._s[2680]! } - public var Passport_Language_hr: String { return self._s[2681]! } - public var Common_ActionNotAllowedError: String { return self._s[2682]! } + public var EmptyGroupInfo_Line3: String { return self._s[2708]! } + public var LogoutOptions_ContactSupportText: String { return self._s[2709]! } + public var Passport_Language_hr: String { return self._s[2710]! } + public var Common_ActionNotAllowedError: String { return self._s[2711]! } public func Channel_AdminLog_MessageRestrictedNewSetting(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2683]!, self._r[2683]!, [_0]) - } - public var GroupInfo_InviteLink_CopyLink: String { return self._s[2684]! } - public var Wallet_Info_TransactionFrom: String { return self._s[2685]! } - public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2686]! } - public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2687]! } - public var Privacy_SecretChatsTitle: String { return self._s[2688]! } - public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2690]! } - public var GroupInfo_AddUserLeftError: String { return self._s[2691]! } - public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2692]! } - public var LogoutOptions_ContactSupportTitle: String { return self._s[2693]! } - public var Channel_AddBotErrorHaveRights: String { return self._s[2694]! } - public var Preview_DeleteGif: String { return self._s[2695]! } - public var GroupInfo_Permissions_Exceptions: String { return self._s[2696]! } - public var Group_ErrorNotMutualContact: String { return self._s[2697]! } - public var Notification_MessageLifetime5s: String { return self._s[2698]! } - public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2699]!, self._r[2699]!, [_0]) - } - public var VoiceOver_Chat_Video: String { return self._s[2700]! } - public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2702]! } - public var ReportSpam_DeleteThisChat: String { return self._s[2703]! } - public var Passport_Address_AddBankStatement: String { return self._s[2704]! } - public var Notification_CallIncoming: String { return self._s[2705]! } - public var Wallet_Words_NotDoneTitle: String { return self._s[2706]! } - public var Compose_NewGroupTitle: String { return self._s[2707]! } - public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2709]! } - public var Passport_Address_Postcode: String { return self._s[2711]! } - public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2712]!, self._r[2712]!, [_0]) } - public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2713]! } - public var Wallet_Month_ShortOctober: String { return self._s[2714]! } - public var VoiceOver_Chat_YourMusic: String { return self._s[2715]! } - public var WallpaperColors_Title: String { return self._s[2716]! } - public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2717]! } - public var VoiceOver_MessageContextForward: String { return self._s[2718]! } - public var GroupPermission_Duration: String { return self._s[2719]! } + public var GroupInfo_InviteLink_CopyLink: String { return self._s[2713]! } + public var Wallet_Info_TransactionFrom: String { return self._s[2714]! } + public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[2715]! } + public var Conversation_InputTextBroadcastPlaceholder: String { return self._s[2716]! } + public var Privacy_SecretChatsTitle: String { return self._s[2717]! } + public var Notification_SecretChatMessageScreenshotSelf: String { return self._s[2719]! } + public var GroupInfo_AddUserLeftError: String { return self._s[2720]! } + public var AutoDownloadSettings_TypePrivateChats: String { return self._s[2721]! } + public var LogoutOptions_ContactSupportTitle: String { return self._s[2722]! } + public var Channel_AddBotErrorHaveRights: String { return self._s[2723]! } + public var Preview_DeleteGif: String { return self._s[2724]! } + public var GroupInfo_Permissions_Exceptions: String { return self._s[2725]! } + public var Group_ErrorNotMutualContact: String { return self._s[2726]! } + public var Notification_MessageLifetime5s: String { return self._s[2727]! } + public func Watch_LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2728]!, self._r[2728]!, [_0]) + } + public var VoiceOver_Chat_Video: String { return self._s[2729]! } + public var Channel_OwnershipTransfer_ErrorPublicChannelsTooMuch: String { return self._s[2731]! } + public var ReportSpam_DeleteThisChat: String { return self._s[2732]! } + public var Passport_Address_AddBankStatement: String { return self._s[2733]! } + public var Notification_CallIncoming: String { return self._s[2734]! } + public var Wallet_Words_NotDoneTitle: String { return self._s[2735]! } + public var Compose_NewGroupTitle: String { return self._s[2736]! } + public var TwoStepAuth_RecoveryCodeHelp: String { return self._s[2738]! } + public var Passport_Address_Postcode: String { return self._s[2740]! } + public func LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2741]!, self._r[2741]!, [_0]) + } + public var Checkout_NewCard_SaveInfoHelp: String { return self._s[2742]! } + public var Wallet_Month_ShortOctober: String { return self._s[2743]! } + public var VoiceOver_Chat_YourMusic: String { return self._s[2744]! } + public var WallpaperColors_Title: String { return self._s[2745]! } + public var SocksProxySetup_ShareQRCodeInfo: String { return self._s[2746]! } + public var VoiceOver_MessageContextForward: String { return self._s[2747]! } + public var GroupPermission_Duration: String { return self._s[2748]! } public func Cache_Clear(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2720]!, self._r[2720]!, [_0]) - } - public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2721]! } - public var Username_Placeholder: String { return self._s[2722]! } - public var CallFeedback_WhatWentWrong: String { return self._s[2723]! } - public var Passport_FieldAddressUploadHelp: String { return self._s[2724]! } - public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2725]! } - public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2727]!, self._r[2727]!, [_1, _2]) - } - public var Passport_PasswordDescription: String { return self._s[2728]! } - public var Channel_MessagePhotoUpdated: String { return self._s[2729]! } - public var MediaPicker_TapToUngroupDescription: String { return self._s[2730]! } - public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2731]! } - public var AttachmentMenu_PhotoOrVideo: String { return self._s[2732]! } - public var Conversation_ContextMenuMore: String { return self._s[2733]! } - public var Privacy_PaymentsClearInfo: String { return self._s[2734]! } - public var CallSettings_TabIcon: String { return self._s[2735]! } - public var KeyCommand_Find: String { return self._s[2736]! } - public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2737]! } - public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2738]! } - public var Message_PinnedGame: String { return self._s[2739]! } - public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2740]! } - public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2742]! } - public var Login_CallRequestState2: String { return self._s[2744]! } - public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2746]! } - public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2747]!, self._r[2747]!, [_0]) - } - public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[2749]!, self._r[2749]!, [_0]) } - public var WallpaperPreview_Blurred: String { return self._s[2750]! } - public var Conversation_InstantPagePreview: String { return self._s[2751]! } + public var Bot_GroupStatusDoesNotReadHistory: String { return self._s[2750]! } + public var Username_Placeholder: String { return self._s[2751]! } + public var CallFeedback_WhatWentWrong: String { return self._s[2752]! } + public var Passport_FieldAddressUploadHelp: String { return self._s[2753]! } + public var Permissions_NotificationsAllowInSettings_v0: String { return self._s[2754]! } + public func Channel_AdminLog_MessageChangedUnlinkedChannel(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2756]!, self._r[2756]!, [_1, _2]) + } + public var Passport_PasswordDescription: String { return self._s[2757]! } + public var Channel_MessagePhotoUpdated: String { return self._s[2758]! } + public var MediaPicker_TapToUngroupDescription: String { return self._s[2759]! } + public var SettingsSearch_Synonyms_Notifications_BadgeCountUnreadMessages: String { return self._s[2760]! } + public var AttachmentMenu_PhotoOrVideo: String { return self._s[2761]! } + public var Conversation_ContextMenuMore: String { return self._s[2762]! } + public var Privacy_PaymentsClearInfo: String { return self._s[2763]! } + public var CallSettings_TabIcon: String { return self._s[2764]! } + public var KeyCommand_Find: String { return self._s[2765]! } + public var ClearCache_FreeSpaceDescription: String { return self._s[2766]! } + public var Appearance_ThemePreview_ChatList_7_Text: String { return self._s[2767]! } + public var EditTheme_Edit_Preview_IncomingText: String { return self._s[2768]! } + public var Message_PinnedGame: String { return self._s[2769]! } + public var VoiceOver_Chat_ForwardedFromYou: String { return self._s[2770]! } + public var Notifications_Badge_CountUnreadMessages_InfoOff: String { return self._s[2772]! } + public var Login_CallRequestState2: String { return self._s[2774]! } + public var CheckoutInfo_ReceiverInfoNamePlaceholder: String { return self._s[2776]! } + public func VoiceOver_Chat_PhotoFrom(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2777]!, self._r[2777]!, [_0]) + } + public func Checkout_PayPrice(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[2779]!, self._r[2779]!, [_0]) + } + public var WallpaperPreview_Blurred: String { return self._s[2780]! } + public var Conversation_InstantPagePreview: String { return self._s[2781]! } public func DialogList_SingleUploadingVideoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2752]!, self._r[2752]!, [_0]) + return formatWithArgumentRanges(self._s[2782]!, self._r[2782]!, [_0]) } - public var SecretTimer_VideoDescription: String { return self._s[2755]! } - public var WallpaperSearch_ColorRed: String { return self._s[2756]! } - public var GroupPermission_NoPinMessages: String { return self._s[2757]! } - public var Passport_Language_es: String { return self._s[2758]! } - public var Permissions_ContactsAllow_v0: String { return self._s[2760]! } - public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2761]! } + public var SecretTimer_VideoDescription: String { return self._s[2785]! } + public var WallpaperSearch_ColorRed: String { return self._s[2786]! } + public var GroupPermission_NoPinMessages: String { return self._s[2787]! } + public var Passport_Language_es: String { return self._s[2788]! } + public var Permissions_ContactsAllow_v0: String { return self._s[2790]! } + public var Conversation_EditingMessageMediaEditCurrentVideo: String { return self._s[2791]! } public func PUSH_CHAT_MESSAGE_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2762]!, self._r[2762]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2792]!, self._r[2792]!, [_1, _2]) } - public var Privacy_Forwards_CustomHelp: String { return self._s[2763]! } - public var WebPreview_GettingLinkInfo: String { return self._s[2764]! } - public var Watch_UserInfo_Unmute: String { return self._s[2765]! } - public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2766]! } - public var AccessDenied_CameraRestricted: String { return self._s[2768]! } + public var Privacy_Forwards_CustomHelp: String { return self._s[2793]! } + public var WebPreview_GettingLinkInfo: String { return self._s[2794]! } + public var Watch_UserInfo_Unmute: String { return self._s[2795]! } + public var GroupInfo_ChannelListNamePlaceholder: String { return self._s[2796]! } + public var AccessDenied_CameraRestricted: String { return self._s[2798]! } public func Conversation_Kilobytes(_ _0: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2769]!, self._r[2769]!, ["\(_0)"]) + return formatWithArgumentRanges(self._s[2799]!, self._r[2799]!, ["\(_0)"]) } - public var ChatList_ReadAll: String { return self._s[2771]! } - public var Settings_CopyUsername: String { return self._s[2772]! } - public var Contacts_SearchLabel: String { return self._s[2773]! } - public var Map_OpenInYandexNavigator: String { return self._s[2775]! } - public var PasscodeSettings_EncryptData: String { return self._s[2776]! } - public var WallpaperSearch_ColorPrefix: String { return self._s[2777]! } - public var Notifications_GroupNotificationsPreview: String { return self._s[2778]! } - public var DialogList_AdNoticeAlert: String { return self._s[2779]! } - public var Wallet_Month_GenMay: String { return self._s[2781]! } - public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2782]! } - public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2783]! } - public var Localization_LanguageCustom: String { return self._s[2784]! } - public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2785]! } - public var CallFeedback_Title: String { return self._s[2786]! } - public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2789]! } - public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2790]! } - public var Wallet_Intro_CreateErrorTitle: String { return self._s[2791]! } - public var Conversation_InfoGroup: String { return self._s[2792]! } - public var Compose_NewMessage: String { return self._s[2793]! } - public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2794]! } - public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2795]! } - public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2796]! } - public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2797]! } + public var ChatList_ReadAll: String { return self._s[2801]! } + public var Settings_CopyUsername: String { return self._s[2802]! } + public var Contacts_SearchLabel: String { return self._s[2803]! } + public var Map_OpenInYandexNavigator: String { return self._s[2805]! } + public var PasscodeSettings_EncryptData: String { return self._s[2806]! } + public var WallpaperSearch_ColorPrefix: String { return self._s[2807]! } + public var Notifications_GroupNotificationsPreview: String { return self._s[2808]! } + public var DialogList_AdNoticeAlert: String { return self._s[2809]! } + public var Wallet_Month_GenMay: String { return self._s[2811]! } + public var CheckoutInfo_ShippingInfoAddress1: String { return self._s[2812]! } + public var CheckoutInfo_ShippingInfoAddress2: String { return self._s[2813]! } + public var Localization_LanguageCustom: String { return self._s[2814]! } + public var Passport_Identity_TypeDriversLicenseUploadScan: String { return self._s[2815]! } + public var CallFeedback_Title: String { return self._s[2816]! } + public var VoiceOver_Chat_RecordPreviewVoiceMessage: String { return self._s[2819]! } + public var Passport_Address_OneOfTypePassportRegistration: String { return self._s[2820]! } + public var Wallet_Intro_CreateErrorTitle: String { return self._s[2821]! } + public var Conversation_InfoGroup: String { return self._s[2822]! } + public var Compose_NewMessage: String { return self._s[2823]! } + public var FastTwoStepSetup_HintPlaceholder: String { return self._s[2824]! } + public var ChatSettings_AutoDownloadVideoMessages: String { return self._s[2825]! } + public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[2826]! } + public var Channel_DiscussionGroup_UnlinkChannel: String { return self._s[2827]! } public func Passport_Scans_ScanIndex(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2798]!, self._r[2798]!, [_0]) + return formatWithArgumentRanges(self._s[2828]!, self._r[2828]!, [_0]) } - public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2799]! } - public var Login_CancelSignUpConfirmation: String { return self._s[2800]! } - public var ChangePhoneNumberCode_Help: String { return self._s[2801]! } - public var PrivacySettings_DeleteAccountHelp: String { return self._s[2802]! } - public var Channel_BlackList_Title: String { return self._s[2803]! } - public var UserInfo_PhoneCall: String { return self._s[2804]! } - public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2806]! } - public var Wallet_Month_ShortJanuary: String { return self._s[2807]! } - public var State_connecting: String { return self._s[2808]! } - public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2809]! } - public var Wallet_Month_GenMarch: String { return self._s[2810]! } - public var EditTheme_Expand_BottomInfo: String { return self._s[2811]! } + public var Channel_AdminLog_CanDeleteMessages: String { return self._s[2829]! } + public var Login_CancelSignUpConfirmation: String { return self._s[2830]! } + public var ChangePhoneNumberCode_Help: String { return self._s[2831]! } + public var PrivacySettings_DeleteAccountHelp: String { return self._s[2832]! } + public var Channel_BlackList_Title: String { return self._s[2833]! } + public var UserInfo_PhoneCall: String { return self._s[2834]! } + public var Passport_Address_OneOfTypeBankStatement: String { return self._s[2836]! } + public var Wallet_Month_ShortJanuary: String { return self._s[2837]! } + public var State_connecting: String { return self._s[2838]! } + public var Appearance_ThemePreview_ChatList_6_Text: String { return self._s[2839]! } + public var Wallet_Month_GenMarch: String { return self._s[2840]! } + public var EditTheme_Expand_BottomInfo: String { return self._s[2841]! } public func LastSeen_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2812]!, self._r[2812]!, [_0]) + return formatWithArgumentRanges(self._s[2842]!, self._r[2842]!, [_0]) } public func DialogList_SingleRecordingAudioSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2813]!, self._r[2813]!, [_0]) + return formatWithArgumentRanges(self._s[2843]!, self._r[2843]!, [_0]) } - public var Notifications_GroupNotifications: String { return self._s[2814]! } - public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2815]! } - public var Passport_Identity_EditPassport: String { return self._s[2816]! } - public var EnterPasscode_RepeatNewPasscode: String { return self._s[2818]! } - public var Localization_EnglishLanguageName: String { return self._s[2819]! } - public var Share_AuthDescription: String { return self._s[2820]! } - public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2821]! } - public var Passport_Identity_Surname: String { return self._s[2822]! } - public var Compose_TokenListPlaceholder: String { return self._s[2823]! } - public var Passport_Identity_OneOfTypePassport: String { return self._s[2824]! } - public var Settings_AboutEmpty: String { return self._s[2825]! } - public var Conversation_Unmute: String { return self._s[2826]! } - public var CreateGroup_ChannelsTooMuch: String { return self._s[2828]! } - public var Wallet_Sending_Text: String { return self._s[2829]! } + public var Notifications_GroupNotifications: String { return self._s[2844]! } + public var Conversation_SendMessageErrorTooMuchScheduled: String { return self._s[2845]! } + public var Passport_Identity_EditPassport: String { return self._s[2846]! } + public var EnterPasscode_RepeatNewPasscode: String { return self._s[2848]! } + public var Localization_EnglishLanguageName: String { return self._s[2849]! } + public var Share_AuthDescription: String { return self._s[2850]! } + public var SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert: String { return self._s[2851]! } + public var Passport_Identity_Surname: String { return self._s[2852]! } + public var Compose_TokenListPlaceholder: String { return self._s[2853]! } + public var Passport_Identity_OneOfTypePassport: String { return self._s[2854]! } + public var Settings_AboutEmpty: String { return self._s[2855]! } + public var Conversation_Unmute: String { return self._s[2856]! } + public var CreateGroup_ChannelsTooMuch: String { return self._s[2858]! } + public var Wallet_Sending_Text: String { return self._s[2859]! } public func PUSH_CONTACT_JOINED(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2830]!, self._r[2830]!, [_1]) + return formatWithArgumentRanges(self._s[2860]!, self._r[2860]!, [_1]) } - public var Login_CodeSentCall: String { return self._s[2831]! } - public var ContactInfo_PhoneLabelHomeFax: String { return self._s[2833]! } - public var ChatSettings_Appearance: String { return self._s[2834]! } - public var Appearance_PickAccentColor: String { return self._s[2835]! } + public var Login_CodeSentCall: String { return self._s[2861]! } + public var ContactInfo_PhoneLabelHomeFax: String { return self._s[2863]! } + public var ChatSettings_Appearance: String { return self._s[2864]! } + public var Appearance_PickAccentColor: String { return self._s[2865]! } public func PUSH_CHAT_MESSAGE_NOTEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2836]!, self._r[2836]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2866]!, self._r[2866]!, [_1, _2]) } public func PUSH_MESSAGE_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2837]!, self._r[2837]!, [_1]) + return formatWithArgumentRanges(self._s[2867]!, self._r[2867]!, [_1]) } - public var Notification_CallMissed: String { return self._s[2838]! } - public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[2839]! } - public var Channel_AdminLogFilter_EventsInfo: String { return self._s[2840]! } - public var Wallet_Month_GenOctober: String { return self._s[2842]! } - public var ChatAdmins_AdminLabel: String { return self._s[2843]! } - public var KeyCommand_JumpToNextChat: String { return self._s[2844]! } - public var Conversation_StopPollConfirmationTitle: String { return self._s[2846]! } - public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[2847]! } - public var Month_GenJune: String { return self._s[2848]! } - public var Watch_Location_Current: String { return self._s[2849]! } - public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[2850]! } - public var Conversation_TitleMute: String { return self._s[2851]! } + public var Notification_CallMissed: String { return self._s[2868]! } + public var SettingsSearch_Synonyms_Appearance_ChatBackground_Custom: String { return self._s[2869]! } + public var Channel_AdminLogFilter_EventsInfo: String { return self._s[2870]! } + public var Wallet_Month_GenOctober: String { return self._s[2872]! } + public var ChatAdmins_AdminLabel: String { return self._s[2873]! } + public var KeyCommand_JumpToNextChat: String { return self._s[2874]! } + public var Conversation_StopPollConfirmationTitle: String { return self._s[2876]! } + public var ChangePhoneNumberCode_CodePlaceholder: String { return self._s[2877]! } + public var Month_GenJune: String { return self._s[2878]! } + public var Watch_Location_Current: String { return self._s[2879]! } + public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[2880]! } + public var Conversation_TitleMute: String { return self._s[2881]! } public func PUSH_CHANNEL_MESSAGE_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2852]!, self._r[2852]!, [_1]) + return formatWithArgumentRanges(self._s[2882]!, self._r[2882]!, [_1]) } - public var GroupInfo_DeleteAndExit: String { return self._s[2853]! } + public var GroupInfo_DeleteAndExit: String { return self._s[2883]! } public func Conversation_Moderate_DeleteAllMessages(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2854]!, self._r[2854]!, [_0]) + return formatWithArgumentRanges(self._s[2884]!, self._r[2884]!, [_0]) } - public var Call_ReportPlaceholder: String { return self._s[2855]! } - public var Chat_SlowmodeSendError: String { return self._s[2856]! } - public var MaskStickerSettings_Info: String { return self._s[2857]! } - public var EditTheme_Expand_TopInfo: String { return self._s[2858]! } + public var Call_ReportPlaceholder: String { return self._s[2885]! } + public var Chat_SlowmodeSendError: String { return self._s[2886]! } + public var MaskStickerSettings_Info: String { return self._s[2887]! } + public var EditTheme_Expand_TopInfo: String { return self._s[2888]! } public func GroupInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2859]!, self._r[2859]!, [_0]) + return formatWithArgumentRanges(self._s[2889]!, self._r[2889]!, [_0]) } - public var Checkout_NewCard_PostcodeTitle: String { return self._s[2860]! } - public var Passport_Address_RegionPlaceholder: String { return self._s[2862]! } - public var Contacts_ShareTelegram: String { return self._s[2863]! } - public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[2864]! } - public var Channel_ErrorAccessDenied: String { return self._s[2865]! } - public var UserInfo_ScamBotWarning: String { return self._s[2867]! } - public var Stickers_GroupChooseStickerPack: String { return self._s[2868]! } - public var Call_ConnectionErrorTitle: String { return self._s[2869]! } - public var UserInfo_NotificationsEnable: String { return self._s[2870]! } - public var ArchivedChats_IntroText1: String { return self._s[2871]! } - public var Tour_Text4: String { return self._s[2874]! } - public var WallpaperSearch_Recent: String { return self._s[2875]! } - public var GroupInfo_ScamGroupWarning: String { return self._s[2876]! } - public var Profile_MessageLifetime2s: String { return self._s[2878]! } - public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[2879]! } - public var Notification_MessageLifetime2s: String { return self._s[2880]! } + public var Checkout_NewCard_PostcodeTitle: String { return self._s[2890]! } + public var Passport_Address_RegionPlaceholder: String { return self._s[2892]! } + public var Contacts_ShareTelegram: String { return self._s[2893]! } + public var EnterPasscode_EnterNewPasscodeNew: String { return self._s[2894]! } + public var Channel_ErrorAccessDenied: String { return self._s[2895]! } + public var UserInfo_ScamBotWarning: String { return self._s[2897]! } + public var Stickers_GroupChooseStickerPack: String { return self._s[2898]! } + public var Call_ConnectionErrorTitle: String { return self._s[2899]! } + public var UserInfo_NotificationsEnable: String { return self._s[2900]! } + public var ArchivedChats_IntroText1: String { return self._s[2901]! } + public var Tour_Text4: String { return self._s[2904]! } + public var WallpaperSearch_Recent: String { return self._s[2905]! } + public var GroupInfo_ScamGroupWarning: String { return self._s[2906]! } + public var Profile_MessageLifetime2s: String { return self._s[2908]! } + public var Appearance_ThemePreview_ChatList_5_Text: String { return self._s[2909]! } + public var Notification_MessageLifetime2s: String { return self._s[2910]! } public func Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2881]!, self._r[2881]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2911]!, self._r[2911]!, [_1, _2, _3]) } - public var Cache_ClearCache: String { return self._s[2882]! } - public var AutoNightTheme_UpdateLocation: String { return self._s[2883]! } - public var Permissions_NotificationsUnreachableText_v0: String { return self._s[2884]! } + public var Cache_ClearCache: String { return self._s[2912]! } + public var AutoNightTheme_UpdateLocation: String { return self._s[2913]! } + public var Permissions_NotificationsUnreachableText_v0: String { return self._s[2914]! } public func Channel_AdminLog_MessageChangedGroupUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2888]!, self._r[2888]!, [_0]) + return formatWithArgumentRanges(self._s[2918]!, self._r[2918]!, [_0]) } public func Conversation_ShareMyPhoneNumber_StatusSuccess(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2890]!, self._r[2890]!, [_0]) + return formatWithArgumentRanges(self._s[2920]!, self._r[2920]!, [_0]) } - public var LocalGroup_Text: String { return self._s[2891]! } - public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[2892]! } - public var SocksProxySetup_TypeSocks: String { return self._s[2893]! } - public var ChatList_UnarchiveAction: String { return self._s[2894]! } - public var AutoNightTheme_Title: String { return self._s[2895]! } - public var InstantPage_FeedbackButton: String { return self._s[2896]! } - public var Passport_FieldAddress: String { return self._s[2897]! } + public var LocalGroup_Text: String { return self._s[2921]! } + public var Channel_AdminLog_EmptyFilterTitle: String { return self._s[2922]! } + public var SocksProxySetup_TypeSocks: String { return self._s[2923]! } + public var ChatList_UnarchiveAction: String { return self._s[2924]! } + public var AutoNightTheme_Title: String { return self._s[2925]! } + public var InstantPage_FeedbackButton: String { return self._s[2926]! } + public var Passport_FieldAddress: String { return self._s[2927]! } public func Channel_AdminLog_SetSlowmode(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2898]!, self._r[2898]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2928]!, self._r[2928]!, [_1, _2]) } - public var Month_ShortMarch: String { return self._s[2899]! } + public var Month_ShortMarch: String { return self._s[2929]! } public func PUSH_MESSAGE_INVOICE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2900]!, self._r[2900]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2930]!, self._r[2930]!, [_1, _2]) } - public var SocksProxySetup_UsernamePlaceholder: String { return self._s[2901]! } - public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[2902]! } - public var Passport_FloodError: String { return self._s[2903]! } - public var SecretGif_Title: String { return self._s[2904]! } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[2905]! } - public var ChatList_Context_UnhideArchive: String { return self._s[2906]! } - public var Passport_Language_th: String { return self._s[2908]! } - public var Passport_Address_Address: String { return self._s[2909]! } - public var Login_InvalidLastNameError: String { return self._s[2910]! } - public var Notifications_InAppNotificationsPreview: String { return self._s[2911]! } - public var Notifications_PermissionsUnreachableTitle: String { return self._s[2912]! } - public var ChatList_Context_Archive: String { return self._s[2913]! } - public var SettingsSearch_FAQ: String { return self._s[2914]! } - public var ShareMenu_Send: String { return self._s[2915]! } - public var WallpaperSearch_ColorYellow: String { return self._s[2917]! } - public var Month_GenNovember: String { return self._s[2919]! } - public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[2921]! } + public var SocksProxySetup_UsernamePlaceholder: String { return self._s[2931]! } + public var Conversation_ShareInlineBotLocationConfirmation: String { return self._s[2932]! } + public var Passport_FloodError: String { return self._s[2933]! } + public var SecretGif_Title: String { return self._s[2934]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOn: String { return self._s[2935]! } + public var ChatList_Context_UnhideArchive: String { return self._s[2936]! } + public var Passport_Language_th: String { return self._s[2938]! } + public var Passport_Address_Address: String { return self._s[2939]! } + public var Login_InvalidLastNameError: String { return self._s[2940]! } + public var Notifications_InAppNotificationsPreview: String { return self._s[2941]! } + public var Notifications_PermissionsUnreachableTitle: String { return self._s[2942]! } + public var ChatList_Context_Archive: String { return self._s[2943]! } + public var SettingsSearch_FAQ: String { return self._s[2944]! } + public var ShareMenu_Send: String { return self._s[2945]! } + public var WallpaperSearch_ColorYellow: String { return self._s[2947]! } + public var Month_GenNovember: String { return self._s[2949]! } + public var SettingsSearch_Synonyms_Appearance_LargeEmoji: String { return self._s[2951]! } public func Conversation_ShareMyPhoneNumberConfirmation(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2922]!, self._r[2922]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2952]!, self._r[2952]!, [_1, _2]) } - public var Checkout_Email: String { return self._s[2923]! } - public var NotificationsSound_Tritone: String { return self._s[2924]! } - public var StickerPacksSettings_ManagingHelp: String { return self._s[2926]! } - public var Wallet_ContextMenuCopy: String { return self._s[2928]! } + public var Conversation_SwipeToReplyHintText: String { return self._s[2953]! } + public var Checkout_Email: String { return self._s[2954]! } + public var NotificationsSound_Tritone: String { return self._s[2955]! } + public var StickerPacksSettings_ManagingHelp: String { return self._s[2957]! } + public var Wallet_ContextMenuCopy: String { return self._s[2959]! } public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2930]!, self._r[2930]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[2961]!, self._r[2961]!, [_1, _2, _3]) } public func PUSH_PINNED_ROUND(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2931]!, self._r[2931]!, [_1]) + return formatWithArgumentRanges(self._s[2962]!, self._r[2962]!, [_1]) } - public var ChangePhoneNumberNumber_Help: String { return self._s[2932]! } + public var ChangePhoneNumberNumber_Help: String { return self._s[2963]! } public func Checkout_LiabilityAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2933]!, self._r[2933]!, [_1, _1, _1, _2]) + return formatWithArgumentRanges(self._s[2964]!, self._r[2964]!, [_1, _1, _1, _2]) } - public var ChatList_UndoArchiveTitle: String { return self._s[2934]! } - public var Notification_Exceptions_Add: String { return self._s[2935]! } - public var DialogList_You: String { return self._s[2936]! } - public var MediaPicker_Send: String { return self._s[2939]! } - public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[2940]! } - public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[2941]! } - public var Call_AudioRouteSpeaker: String { return self._s[2942]! } - public var Watch_UserInfo_Title: String { return self._s[2943]! } - public var VoiceOver_Chat_PollFinalResults: String { return self._s[2944]! } - public var Appearance_AccentColor: String { return self._s[2946]! } + public var ChatList_UndoArchiveTitle: String { return self._s[2965]! } + public var Notification_Exceptions_Add: String { return self._s[2966]! } + public var DialogList_You: String { return self._s[2967]! } + public var MediaPicker_Send: String { return self._s[2970]! } + public var SettingsSearch_Synonyms_Stickers_Title: String { return self._s[2971]! } + public var Appearance_ThemePreview_ChatList_4_Text: String { return self._s[2972]! } + public var Call_AudioRouteSpeaker: String { return self._s[2973]! } + public var Watch_UserInfo_Title: String { return self._s[2974]! } + public var VoiceOver_Chat_PollFinalResults: String { return self._s[2975]! } + public var Appearance_AccentColor: String { return self._s[2977]! } public func Login_EmailPhoneSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2947]!, self._r[2947]!, [_0]) + return formatWithArgumentRanges(self._s[2978]!, self._r[2978]!, [_0]) } - public var Permissions_ContactsAllowInSettings_v0: String { return self._s[2948]! } + public var Permissions_ContactsAllowInSettings_v0: String { return self._s[2979]! } public func PUSH_CHANNEL_MESSAGE_GAME(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2949]!, self._r[2949]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2980]!, self._r[2980]!, [_1, _2]) } - public var Conversation_ClousStorageInfo_Description2: String { return self._s[2950]! } - public var WebSearch_RecentClearConfirmation: String { return self._s[2951]! } - public var Notification_CallOutgoing: String { return self._s[2952]! } - public var PrivacySettings_PasscodeAndFaceId: String { return self._s[2953]! } - public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[2954]! } - public var Call_RecordingDisabledMessage: String { return self._s[2955]! } - public var Message_Game: String { return self._s[2956]! } - public var Conversation_PressVolumeButtonForSound: String { return self._s[2957]! } - public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[2958]! } - public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[2959]! } - public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[2960]! } - public var Date_DialogDateFormat: String { return self._s[2961]! } - public var WallpaperColors_SetCustomColor: String { return self._s[2962]! } - public var Notifications_InAppNotifications: String { return self._s[2963]! } + public var Conversation_ClousStorageInfo_Description2: String { return self._s[2981]! } + public var WebSearch_RecentClearConfirmation: String { return self._s[2982]! } + public var Notification_CallOutgoing: String { return self._s[2983]! } + public var PrivacySettings_PasscodeAndFaceId: String { return self._s[2984]! } + public var Channel_DiscussionGroup_MakeHistoryPublic: String { return self._s[2985]! } + public var Call_RecordingDisabledMessage: String { return self._s[2986]! } + public var Message_Game: String { return self._s[2987]! } + public var Conversation_PressVolumeButtonForSound: String { return self._s[2988]! } + public var PrivacyLastSeenSettings_CustomHelp: String { return self._s[2989]! } + public var Channel_DiscussionGroup_PrivateGroup: String { return self._s[2990]! } + public var Channel_EditAdmin_PermissionAddAdmins: String { return self._s[2991]! } + public var Date_DialogDateFormat: String { return self._s[2992]! } + public var WallpaperColors_SetCustomColor: String { return self._s[2993]! } + public var Notifications_InAppNotifications: String { return self._s[2994]! } public func Channel_Management_RemovedBy(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2964]!, self._r[2964]!, [_0]) + return formatWithArgumentRanges(self._s[2995]!, self._r[2995]!, [_0]) } public func Settings_ApplyProxyAlert(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2965]!, self._r[2965]!, [_1, _2]) + return formatWithArgumentRanges(self._s[2996]!, self._r[2996]!, [_1, _2]) } - public var NewContact_Title: String { return self._s[2966]! } + public var NewContact_Title: String { return self._s[2997]! } public func AutoDownloadSettings_UpToForAll(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2967]!, self._r[2967]!, [_0]) + return formatWithArgumentRanges(self._s[2998]!, self._r[2998]!, [_0]) } - public var Conversation_ViewContactDetails: String { return self._s[2968]! } + public var Conversation_ViewContactDetails: String { return self._s[2999]! } public func PUSH_CHANNEL_MESSAGE_CONTACT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2970]!, self._r[2970]!, [_1]) + return formatWithArgumentRanges(self._s[3001]!, self._r[3001]!, [_1]) } - public var Checkout_NewCard_CardholderNameTitle: String { return self._s[2971]! } - public var Passport_Identity_ExpiryDateNone: String { return self._s[2972]! } - public var PrivacySettings_Title: String { return self._s[2973]! } - public var Conversation_SilentBroadcastTooltipOff: String { return self._s[2976]! } - public var GroupRemoved_UsersSectionTitle: String { return self._s[2977]! } - public var VoiceOver_Chat_ContactEmail: String { return self._s[2978]! } - public var Contacts_PhoneNumber: String { return self._s[2979]! } - public var Map_ShowPlaces: String { return self._s[2981]! } - public var ChatAdmins_Title: String { return self._s[2982]! } - public var InstantPage_Reference: String { return self._s[2984]! } - public var Wallet_Info_Updating: String { return self._s[2985]! } - public var ReportGroupLocation_Text: String { return self._s[2986]! } + public var Checkout_NewCard_CardholderNameTitle: String { return self._s[3002]! } + public var Passport_Identity_ExpiryDateNone: String { return self._s[3003]! } + public var PrivacySettings_Title: String { return self._s[3004]! } + public var Conversation_SilentBroadcastTooltipOff: String { return self._s[3007]! } + public var GroupRemoved_UsersSectionTitle: String { return self._s[3008]! } + public var VoiceOver_Chat_ContactEmail: String { return self._s[3009]! } + public var Contacts_PhoneNumber: String { return self._s[3010]! } + public var TwoFactorSetup_Password_PlaceholderConfirmPassword: String { return self._s[3012]! } + public var Map_ShowPlaces: String { return self._s[3013]! } + public var ChatAdmins_Title: String { return self._s[3014]! } + public var InstantPage_Reference: String { return self._s[3016]! } + public var Wallet_Info_Updating: String { return self._s[3017]! } + public var ReportGroupLocation_Text: String { return self._s[3018]! } public func PUSH_CHAT_MESSAGE_FWD(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2987]!, self._r[2987]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3019]!, self._r[3019]!, [_1, _2]) } - public var Camera_FlashOff: String { return self._s[2988]! } - public var Wallet_Intro_TermsUrl: String { return self._s[2989]! } - public var Watch_UserInfo_Block: String { return self._s[2990]! } - public var ChatSettings_Stickers: String { return self._s[2991]! } - public var ChatSettings_DownloadInBackground: String { return self._s[2992]! } - public var Appearance_ThemeCarouselTintedNight: String { return self._s[2993]! } + public var Camera_FlashOff: String { return self._s[3020]! } + public var Wallet_Intro_TermsUrl: String { return self._s[3021]! } + public var Watch_UserInfo_Block: String { return self._s[3022]! } + public var ChatSettings_Stickers: String { return self._s[3023]! } + public var ChatSettings_DownloadInBackground: String { return self._s[3024]! } + public var Appearance_ThemeCarouselTintedNight: String { return self._s[3025]! } public func UserInfo_BlockConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[2994]!, self._r[2994]!, [_0]) + return formatWithArgumentRanges(self._s[3026]!, self._r[3026]!, [_0]) } - public var Settings_ViewPhoto: String { return self._s[2995]! } - public var Login_CheckOtherSessionMessages: String { return self._s[2996]! } - public var AutoDownloadSettings_Cellular: String { return self._s[2997]! } - public var Wallet_Created_ExportErrorTitle: String { return self._s[2998]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[2999]! } - public var VoiceOver_MessageContextShare: String { return self._s[3000]! } + public var Settings_ViewPhoto: String { return self._s[3027]! } + public var Login_CheckOtherSessionMessages: String { return self._s[3028]! } + public var AutoDownloadSettings_Cellular: String { return self._s[3029]! } + public var Wallet_Created_ExportErrorTitle: String { return self._s[3030]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions: String { return self._s[3031]! } + public var VoiceOver_MessageContextShare: String { return self._s[3032]! } public func Target_InviteToGroupConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3002]!, self._r[3002]!, [_0]) + return formatWithArgumentRanges(self._s[3034]!, self._r[3034]!, [_0]) } - public var Privacy_DeleteDrafts: String { return self._s[3003]! } - public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3004]! } + public var Privacy_DeleteDrafts: String { return self._s[3035]! } + public var Wallpaper_SetCustomBackgroundInfo: String { return self._s[3036]! } public func LastSeen_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3005]!, self._r[3005]!, [_0]) + return formatWithArgumentRanges(self._s[3037]!, self._r[3037]!, [_0]) } - public var DialogList_SavedMessagesHelp: String { return self._s[3006]! } - public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3007]! } - public var DialogList_SavedMessages: String { return self._s[3008]! } - public var GroupInfo_UpgradeButton: String { return self._s[3009]! } - public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3011]! } - public var DialogList_Pin: String { return self._s[3012]! } + public var DialogList_SavedMessagesHelp: String { return self._s[3038]! } + public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[3039]! } + public var DialogList_SavedMessages: String { return self._s[3040]! } + public var GroupInfo_UpgradeButton: String { return self._s[3041]! } + public var Appearance_ThemePreview_ChatList_3_Text: String { return self._s[3043]! } + public var DialogList_Pin: String { return self._s[3044]! } public func ForwardedAuthors2(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3013]!, self._r[3013]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3045]!, self._r[3045]!, [_0, _1]) } public func Login_PhoneGenericEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3014]!, self._r[3014]!, [_0]) + return formatWithArgumentRanges(self._s[3046]!, self._r[3046]!, [_0]) } - public var Notification_Exceptions_AlwaysOn: String { return self._s[3015]! } - public var UserInfo_NotificationsDisable: String { return self._s[3016]! } - public var Paint_Outlined: String { return self._s[3017]! } - public var Activity_PlayingGame: String { return self._s[3018]! } - public var SearchImages_NoImagesFound: String { return self._s[3019]! } - public var SocksProxySetup_ProxyType: String { return self._s[3020]! } - public var AppleWatch_ReplyPresetsHelp: String { return self._s[3022]! } - public var Conversation_ContextMenuCancelSending: String { return self._s[3023]! } - public var Settings_AppLanguage: String { return self._s[3024]! } - public var TwoStepAuth_ResetAccountHelp: String { return self._s[3025]! } - public var Common_ChoosePhoto: String { return self._s[3026]! } - public var CallFeedback_ReasonEcho: String { return self._s[3027]! } + public var Notification_Exceptions_AlwaysOn: String { return self._s[3047]! } + public var UserInfo_NotificationsDisable: String { return self._s[3048]! } + public var Paint_Outlined: String { return self._s[3049]! } + public var Activity_PlayingGame: String { return self._s[3050]! } + public var SearchImages_NoImagesFound: String { return self._s[3051]! } + public var SocksProxySetup_ProxyType: String { return self._s[3052]! } + public var AppleWatch_ReplyPresetsHelp: String { return self._s[3054]! } + public var Conversation_ContextMenuCancelSending: String { return self._s[3055]! } + public var Settings_AppLanguage: String { return self._s[3056]! } + public var TwoStepAuth_ResetAccountHelp: String { return self._s[3057]! } + public var Common_ChoosePhoto: String { return self._s[3058]! } + public var CallFeedback_ReasonEcho: String { return self._s[3059]! } public func PUSH_PINNED_AUDIO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3028]!, self._r[3028]!, [_1]) + return formatWithArgumentRanges(self._s[3060]!, self._r[3060]!, [_1]) } - public var Privacy_Calls_AlwaysAllow: String { return self._s[3029]! } - public var Activity_UploadingVideo: String { return self._s[3030]! } - public var Conversation_WalletRequiredNotNow: String { return self._s[3031]! } - public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3032]! } - public var NetworkUsageSettings_Wifi: String { return self._s[3033]! } - public var VoiceOver_Editing_ClearText: String { return self._s[3034]! } - public var PUSH_SENDER_YOU: String { return self._s[3035]! } - public var Channel_BanUser_PermissionReadMessages: String { return self._s[3036]! } - public var Checkout_PayWithTouchId: String { return self._s[3037]! } - public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3038]! } + public var Privacy_Calls_AlwaysAllow: String { return self._s[3061]! } + public var Activity_UploadingVideo: String { return self._s[3062]! } + public var Conversation_WalletRequiredNotNow: String { return self._s[3063]! } + public var ChannelInfo_DeleteChannelConfirmation: String { return self._s[3064]! } + public var NetworkUsageSettings_Wifi: String { return self._s[3065]! } + public var VoiceOver_Editing_ClearText: String { return self._s[3066]! } + public var PUSH_SENDER_YOU: String { return self._s[3067]! } + public var Channel_BanUser_PermissionReadMessages: String { return self._s[3068]! } + public var Checkout_PayWithTouchId: String { return self._s[3069]! } + public var Wallpaper_ResetWallpapersConfirmation: String { return self._s[3070]! } public func PUSH_LOCKED_MESSAGE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3040]!, self._r[3040]!, [_1]) + return formatWithArgumentRanges(self._s[3072]!, self._r[3072]!, [_1]) } - public var Notifications_ExceptionsNone: String { return self._s[3041]! } + public var Notifications_ExceptionsNone: String { return self._s[3073]! } public func Message_ForwardedMessageShort(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3042]!, self._r[3042]!, [_0]) + return formatWithArgumentRanges(self._s[3074]!, self._r[3074]!, [_0]) } public func PUSH_PINNED_GEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3043]!, self._r[3043]!, [_1]) + return formatWithArgumentRanges(self._s[3075]!, self._r[3075]!, [_1]) } - public var AuthSessions_IncompleteAttempts: String { return self._s[3045]! } - public var Passport_Address_Region: String { return self._s[3048]! } - public var ChatList_DeleteChat: String { return self._s[3049]! } - public var LogoutOptions_ClearCacheTitle: String { return self._s[3050]! } - public var PhotoEditor_TiltShift: String { return self._s[3051]! } - public var Settings_FAQ_URL: String { return self._s[3052]! } - public var Passport_Language_sl: String { return self._s[3053]! } - public var Settings_PrivacySettings: String { return self._s[3055]! } - public var SharedMedia_TitleLink: String { return self._s[3056]! } - public var Passport_Identity_TypePassportUploadScan: String { return self._s[3057]! } - public var Settings_SetProfilePhoto: String { return self._s[3058]! } - public var Channel_About_Help: String { return self._s[3059]! } - public var Contacts_PermissionsEnable: String { return self._s[3060]! } - public var Wallet_Sending_Title: String { return self._s[3061]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3062]! } - public var AttachmentMenu_SendAsFiles: String { return self._s[3063]! } - public var CallFeedback_ReasonInterruption: String { return self._s[3065]! } - public var Passport_Address_AddTemporaryRegistration: String { return self._s[3066]! } - public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3067]! } - public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3068]! } - public var PrivacySettings_DeleteAccountTitle: String { return self._s[3069]! } - public var AccessDenied_VideoMessageCamera: String { return self._s[3071]! } - public var Map_OpenInYandexMaps: String { return self._s[3073]! } - public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3074]! } - public var VoiceOver_MessageContextReply: String { return self._s[3075]! } - public var PhotoEditor_SaturationTool: String { return self._s[3076]! } + public var AuthSessions_IncompleteAttempts: String { return self._s[3077]! } + public var Passport_Address_Region: String { return self._s[3080]! } + public var ChatList_DeleteChat: String { return self._s[3081]! } + public var LogoutOptions_ClearCacheTitle: String { return self._s[3082]! } + public var PhotoEditor_TiltShift: String { return self._s[3083]! } + public var Settings_FAQ_URL: String { return self._s[3084]! } + public var TwoFactorSetup_EmailVerification_ChangeAction: String { return self._s[3085]! } + public var Passport_Language_sl: String { return self._s[3086]! } + public var Settings_PrivacySettings: String { return self._s[3088]! } + public var SharedMedia_TitleLink: String { return self._s[3089]! } + public var Passport_Identity_TypePassportUploadScan: String { return self._s[3090]! } + public var Settings_SetProfilePhoto: String { return self._s[3091]! } + public var Channel_About_Help: String { return self._s[3092]! } + public var Contacts_PermissionsEnable: String { return self._s[3093]! } + public var Wallet_Sending_Title: String { return self._s[3094]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert: String { return self._s[3095]! } + public var AttachmentMenu_SendAsFiles: String { return self._s[3096]! } + public var CallFeedback_ReasonInterruption: String { return self._s[3098]! } + public var Passport_Address_AddTemporaryRegistration: String { return self._s[3099]! } + public var AutoDownloadSettings_AutodownloadVideos: String { return self._s[3100]! } + public var ChatSettings_AutoDownloadSettings_Delimeter: String { return self._s[3101]! } + public var PrivacySettings_DeleteAccountTitle: String { return self._s[3102]! } + public var AccessDenied_VideoMessageCamera: String { return self._s[3104]! } + public var Map_OpenInYandexMaps: String { return self._s[3106]! } + public var CreateGroup_ErrorLocatedGroupsTooMuch: String { return self._s[3107]! } + public var VoiceOver_MessageContextReply: String { return self._s[3108]! } + public var PhotoEditor_SaturationTool: String { return self._s[3109]! } public func PUSH_MESSAGE_STICKER(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3077]!, self._r[3077]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3110]!, self._r[3110]!, [_1, _2]) } - public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3078]! } - public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3079]! } - public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3080]! } - public var Appearance_TextSize: String { return self._s[3081]! } + public var PrivacyPhoneNumberSettings_CustomHelp: String { return self._s[3111]! } + public var Notification_Exceptions_NewException_NotificationHeader: String { return self._s[3112]! } + public var Group_OwnershipTransfer_ErrorLocatedGroupsTooMuch: String { return self._s[3113]! } + public var Appearance_TextSize: String { return self._s[3114]! } public func LOCAL_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3082]!, self._r[3082]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3115]!, self._r[3115]!, [_1, "\(_2)"]) } - public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3083]! } - public var Channel_Username_InvalidTooShort: String { return self._s[3085]! } + public var Appearance_ThemePreview_ChatList_2_Text: String { return self._s[3116]! } + public var Channel_Username_InvalidTooShort: String { return self._s[3118]! } public func Group_OwnershipTransfer_DescriptionInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3086]!, self._r[3086]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3119]!, self._r[3119]!, [_1, _2]) } public func PUSH_CHAT_MESSAGE_GAME(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3087]!, self._r[3087]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3120]!, self._r[3120]!, [_1, _2, _3]) } - public var GroupInfo_PublicLinkAdd: String { return self._s[3088]! } - public var Passport_PassportInformation: String { return self._s[3091]! } - public var Theme_Unsupported: String { return self._s[3092]! } - public var WatchRemote_AlertTitle: String { return self._s[3093]! } - public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3094]! } - public var ConvertToSupergroup_HelpText: String { return self._s[3096]! } + public var GroupInfo_PublicLinkAdd: String { return self._s[3121]! } + public var Passport_PassportInformation: String { return self._s[3124]! } + public var Theme_Unsupported: String { return self._s[3125]! } + public var WatchRemote_AlertTitle: String { return self._s[3126]! } + public var Privacy_GroupsAndChannels_NeverAllow: String { return self._s[3127]! } + public var ConvertToSupergroup_HelpText: String { return self._s[3129]! } public func Time_MonthOfYear_m7(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3097]!, self._r[3097]!, [_0]) + return formatWithArgumentRanges(self._s[3130]!, self._r[3130]!, [_0]) } public func PUSH_PHONE_CALL_REQUEST(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3098]!, self._r[3098]!, [_1]) + return formatWithArgumentRanges(self._s[3131]!, self._r[3131]!, [_1]) } - public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3099]! } - public var Wallet_Navigation_Done: String { return self._s[3101]! } - public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3102]! } - public var AccessDenied_CameraDisabled: String { return self._s[3103]! } + public var Privacy_GroupsAndChannels_CustomHelp: String { return self._s[3132]! } + public var Wallet_Navigation_Done: String { return self._s[3134]! } + public var TwoStepAuth_RecoveryCodeInvalid: String { return self._s[3135]! } + public var AccessDenied_CameraDisabled: String { return self._s[3136]! } public func Channel_Username_UsernameIsAvailable(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3104]!, self._r[3104]!, [_0]) + return formatWithArgumentRanges(self._s[3137]!, self._r[3137]!, [_0]) } - public var PhotoEditor_ContrastTool: String { return self._s[3107]! } + public var PhotoEditor_ContrastTool: String { return self._s[3140]! } public func PUSH_PINNED_DOC(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3108]!, self._r[3108]!, [_1]) + return formatWithArgumentRanges(self._s[3141]!, self._r[3141]!, [_1]) } - public var DialogList_Draft: String { return self._s[3109]! } - public var Privacy_TopPeersDelete: String { return self._s[3111]! } - public var LoginPassword_PasswordPlaceholder: String { return self._s[3112]! } - public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3113]! } - public var WebSearch_RecentSectionClear: String { return self._s[3114]! } - public var EditTheme_ErrorInvalidCharacters: String { return self._s[3115]! } - public var Watch_ChatList_NoConversationsTitle: String { return self._s[3117]! } - public var Common_Done: String { return self._s[3119]! } - public var AuthSessions_EmptyText: String { return self._s[3120]! } - public var Conversation_ShareBotContactConfirmation: String { return self._s[3121]! } - public var Tour_Title5: String { return self._s[3122]! } - public var Wallet_Settings_Title: String { return self._s[3123]! } + public var DialogList_Draft: String { return self._s[3142]! } + public var Privacy_TopPeersDelete: String { return self._s[3144]! } + public var LoginPassword_PasswordPlaceholder: String { return self._s[3145]! } + public var Passport_Identity_TypeIdentityCardUploadScan: String { return self._s[3146]! } + public var WebSearch_RecentSectionClear: String { return self._s[3147]! } + public var EditTheme_ErrorInvalidCharacters: String { return self._s[3148]! } + public var Watch_ChatList_NoConversationsTitle: String { return self._s[3150]! } + public var Common_Done: String { return self._s[3152]! } + public var AuthSessions_EmptyText: String { return self._s[3153]! } + public var Conversation_ShareBotContactConfirmation: String { return self._s[3154]! } + public var Tour_Title5: String { return self._s[3155]! } + public var Wallet_Settings_Title: String { return self._s[3156]! } public func Map_DirectionsDriveEta(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3124]!, self._r[3124]!, [_0]) + return formatWithArgumentRanges(self._s[3157]!, self._r[3157]!, [_0]) } - public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3125]! } - public var Conversation_LinkDialogSave: String { return self._s[3126]! } - public var GroupInfo_ActionRestrict: String { return self._s[3127]! } - public var Checkout_Title: String { return self._s[3128]! } - public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3130]! } - public var Channel_AdminLog_CanChangeInfo: String { return self._s[3132]! } - public var Notification_RenamedGroup: String { return self._s[3133]! } - public var PeopleNearby_Groups: String { return self._s[3134]! } - public var Checkout_PayWithFaceId: String { return self._s[3135]! } - public var Channel_BanList_BlockedTitle: String { return self._s[3136]! } - public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3138]! } - public var Checkout_WebConfirmation_Title: String { return self._s[3139]! } - public var Notifications_MessageNotificationsAlert: String { return self._s[3140]! } + public var ApplyLanguage_UnsufficientDataTitle: String { return self._s[3158]! } + public var Conversation_LinkDialogSave: String { return self._s[3159]! } + public var GroupInfo_ActionRestrict: String { return self._s[3160]! } + public var Checkout_Title: String { return self._s[3161]! } + public var Channel_DiscussionGroup_HeaderLabel: String { return self._s[3163]! } + public var Channel_AdminLog_CanChangeInfo: String { return self._s[3165]! } + public var Notification_RenamedGroup: String { return self._s[3166]! } + public var PeopleNearby_Groups: String { return self._s[3167]! } + public var Checkout_PayWithFaceId: String { return self._s[3168]! } + public var Channel_BanList_BlockedTitle: String { return self._s[3169]! } + public var SettingsSearch_Synonyms_Notifications_InAppNotificationsSound: String { return self._s[3171]! } + public var Checkout_WebConfirmation_Title: String { return self._s[3172]! } + public var Notifications_MessageNotificationsAlert: String { return self._s[3173]! } public func Activity_RemindAboutGroup(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3141]!, self._r[3141]!, [_0]) + return formatWithArgumentRanges(self._s[3174]!, self._r[3174]!, [_0]) } - public var Profile_AddToExisting: String { return self._s[3143]! } + public var Profile_AddToExisting: String { return self._s[3176]! } public func Profile_CreateEncryptedChatOutdatedError(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3144]!, self._r[3144]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3177]!, self._r[3177]!, [_0, _1]) } - public var Cache_Files: String { return self._s[3146]! } - public var Permissions_PrivacyPolicy: String { return self._s[3147]! } - public var SocksProxySetup_ConnectAndSave: String { return self._s[3148]! } - public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3149]! } - public var AutoDownloadSettings_TypeContacts: String { return self._s[3151]! } - public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3153]! } - public var Calls_NoCallsPlaceholder: String { return self._s[3154]! } + public var Cache_Files: String { return self._s[3179]! } + public var Permissions_PrivacyPolicy: String { return self._s[3180]! } + public var SocksProxySetup_ConnectAndSave: String { return self._s[3181]! } + public var UserInfo_NotificationsDefaultDisabled: String { return self._s[3182]! } + public var AutoDownloadSettings_TypeContacts: String { return self._s[3184]! } + public var Appearance_ThemePreview_ChatList_1_Text: String { return self._s[3186]! } + public var Calls_NoCallsPlaceholder: String { return self._s[3187]! } public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3155]!, self._r[3155]!, [_0]) + return formatWithArgumentRanges(self._s[3188]!, self._r[3188]!, [_0]) } - public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3156]! } - public var VoiceOver_AttachMedia: String { return self._s[3158]! } - public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3159]! } + public var Channel_Username_RevokeExistingUsernamesInfo: String { return self._s[3189]! } + public var VoiceOver_AttachMedia: String { return self._s[3191]! } + public var Notifications_ExceptionsGroupPlaceholder: String { return self._s[3192]! } public func PUSH_CHAT_MESSAGE_INVOICE(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3160]!, self._r[3160]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3193]!, self._r[3193]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3161]! } - public var Conversation_SetReminder_Title: String { return self._s[3162]! } - public var Passport_FieldAddressHelp: String { return self._s[3163]! } - public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3164]! } - public var PUSH_REMINDER_TITLE: String { return self._s[3165]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsSound: String { return self._s[3194]! } + public var Conversation_SetReminder_Title: String { return self._s[3195]! } + public var Passport_FieldAddressHelp: String { return self._s[3196]! } + public var Privacy_GroupsAndChannels_InviteToChannelMultipleError: String { return self._s[3197]! } + public var PUSH_REMINDER_TITLE: String { return self._s[3198]! } public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3166]!, self._r[3166]!, [_0]) + return formatWithArgumentRanges(self._s[3199]!, self._r[3199]!, [_0]) } - public var Channel_AdminLog_EmptyTitle: String { return self._s[3167]! } - public var Privacy_Calls_NeverAllow_Title: String { return self._s[3168]! } - public var Login_UnknownError: String { return self._s[3169]! } - public var Group_UpgradeNoticeText2: String { return self._s[3172]! } - public var Watch_Compose_AddContact: String { return self._s[3173]! } - public var Web_Error: String { return self._s[3174]! } - public var Gif_Search: String { return self._s[3175]! } - public var Profile_MessageLifetime1h: String { return self._s[3176]! } - public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3177]! } - public var Channel_Username_CheckingUsername: String { return self._s[3178]! } - public var CallFeedback_ReasonSilentRemote: String { return self._s[3179]! } - public var AutoDownloadSettings_TypeChannels: String { return self._s[3180]! } - public var Channel_AboutItem: String { return self._s[3181]! } - public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3183]! } - public var VoiceOver_Chat_VoiceMessage: String { return self._s[3184]! } - public var GroupInfo_SharedMedia: String { return self._s[3185]! } + public var Channel_AdminLog_EmptyTitle: String { return self._s[3200]! } + public var Privacy_Calls_NeverAllow_Title: String { return self._s[3201]! } + public var Login_UnknownError: String { return self._s[3202]! } + public var Group_UpgradeNoticeText2: String { return self._s[3205]! } + public var Watch_Compose_AddContact: String { return self._s[3206]! } + public var Web_Error: String { return self._s[3207]! } + public var Gif_Search: String { return self._s[3208]! } + public var Profile_MessageLifetime1h: String { return self._s[3209]! } + public var CheckoutInfo_ReceiverInfoEmailPlaceholder: String { return self._s[3210]! } + public var Channel_Username_CheckingUsername: String { return self._s[3211]! } + public var CallFeedback_ReasonSilentRemote: String { return self._s[3212]! } + public var AutoDownloadSettings_TypeChannels: String { return self._s[3213]! } + public var Channel_AboutItem: String { return self._s[3214]! } + public var Privacy_GroupsAndChannels_AlwaysAllow_Placeholder: String { return self._s[3216]! } + public var VoiceOver_Chat_VoiceMessage: String { return self._s[3217]! } + public var GroupInfo_SharedMedia: String { return self._s[3218]! } public func Channel_AdminLog_MessagePromotedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3186]!, self._r[3186]!, [_1]) + return formatWithArgumentRanges(self._s[3219]!, self._r[3219]!, [_1]) } - public var Call_PhoneCallInProgressMessage: String { return self._s[3187]! } + public var Call_PhoneCallInProgressMessage: String { return self._s[3220]! } public func PUSH_CHANNEL_ALBUM(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3188]!, self._r[3188]!, [_1]) + return formatWithArgumentRanges(self._s[3221]!, self._r[3221]!, [_1]) } - public var ChatList_UndoArchiveRevealedText: String { return self._s[3189]! } - public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3190]! } - public var Conversation_SearchByName_Placeholder: String { return self._s[3191]! } - public var CreatePoll_AddOption: String { return self._s[3192]! } - public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3193]! } - public var Group_UpgradeNoticeHeader: String { return self._s[3194]! } - public var Channel_Management_AddModerator: String { return self._s[3195]! } - public var AutoDownloadSettings_MaxFileSize: String { return self._s[3196]! } - public var StickerPacksSettings_ShowStickersButton: String { return self._s[3197]! } - public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3198]! } - public var NotificationsSound_Hello: String { return self._s[3200]! } - public var SocksProxySetup_SavedProxies: String { return self._s[3201]! } - public var Channel_Stickers_Placeholder: String { return self._s[3203]! } + public var ChatList_UndoArchiveRevealedText: String { return self._s[3222]! } + public var GroupInfo_InviteLink_RevokeAlert_Text: String { return self._s[3223]! } + public var Conversation_SearchByName_Placeholder: String { return self._s[3224]! } + public var CreatePoll_AddOption: String { return self._s[3225]! } + public var GroupInfo_Permissions_SearchPlaceholder: String { return self._s[3226]! } + public var Group_UpgradeNoticeHeader: String { return self._s[3227]! } + public var Channel_Management_AddModerator: String { return self._s[3228]! } + public var AutoDownloadSettings_MaxFileSize: String { return self._s[3229]! } + public var StickerPacksSettings_ShowStickersButton: String { return self._s[3230]! } + public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[3231]! } + public var NotificationsSound_Hello: String { return self._s[3233]! } + public var SocksProxySetup_SavedProxies: String { return self._s[3234]! } + public var Channel_Stickers_Placeholder: String { return self._s[3236]! } public func Login_EmailCodeBody(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3204]!, self._r[3204]!, [_0]) + return formatWithArgumentRanges(self._s[3237]!, self._r[3237]!, [_0]) } - public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3205]! } - public var Channel_Management_AddModeratorHelp: String { return self._s[3206]! } - public var ContactInfo_BirthdayLabel: String { return self._s[3207]! } - public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3208]! } - public var AutoDownloadSettings_Channels: String { return self._s[3209]! } - public var Passport_Language_mn: String { return self._s[3210]! } - public var Notifications_ResetAllNotificationsHelp: String { return self._s[3213]! } - public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3214]! } - public var Passport_Language_ja: String { return self._s[3216]! } - public var Settings_About_Title: String { return self._s[3217]! } - public var Settings_NotificationsAndSounds: String { return self._s[3218]! } - public var ChannelInfo_DeleteGroup: String { return self._s[3219]! } - public var Settings_BlockedUsers: String { return self._s[3220]! } + public var PrivacyPolicy_DeclineDeclineAndDelete: String { return self._s[3238]! } + public var Channel_Management_AddModeratorHelp: String { return self._s[3239]! } + public var ContactInfo_BirthdayLabel: String { return self._s[3240]! } + public var ChangePhoneNumberCode_RequestingACall: String { return self._s[3241]! } + public var AutoDownloadSettings_Channels: String { return self._s[3242]! } + public var Passport_Language_mn: String { return self._s[3243]! } + public var Notifications_ResetAllNotificationsHelp: String { return self._s[3246]! } + public var GroupInfo_Permissions_SlowmodeValue_Off: String { return self._s[3247]! } + public var Passport_Language_ja: String { return self._s[3249]! } + public var Settings_About_Title: String { return self._s[3250]! } + public var Settings_NotificationsAndSounds: String { return self._s[3251]! } + public var ChannelInfo_DeleteGroup: String { return self._s[3252]! } + public var Settings_BlockedUsers: String { return self._s[3253]! } public func Time_MonthOfYear_m4(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3221]!, self._r[3221]!, [_0]) + return formatWithArgumentRanges(self._s[3254]!, self._r[3254]!, [_0]) } - public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3222]! } - public var Wallet_Weekday_Today: String { return self._s[3223]! } - public var AutoDownloadSettings_PreloadVideo: String { return self._s[3224]! } - public var Passport_Address_AddResidentialAddress: String { return self._s[3225]! } - public var Channel_Username_Title: String { return self._s[3226]! } + public var EditTheme_Create_Preview_OutgoingText: String { return self._s[3255]! } + public var Wallet_Weekday_Today: String { return self._s[3256]! } + public var AutoDownloadSettings_PreloadVideo: String { return self._s[3257]! } + public var Passport_Address_AddResidentialAddress: String { return self._s[3258]! } + public var Channel_Username_Title: String { return self._s[3259]! } public func Notification_RemovedGroupPhoto(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3227]!, self._r[3227]!, [_0]) + return formatWithArgumentRanges(self._s[3260]!, self._r[3260]!, [_0]) } - public var AttachmentMenu_File: String { return self._s[3229]! } - public var AppleWatch_Title: String { return self._s[3230]! } - public var Activity_RecordingVideoMessage: String { return self._s[3231]! } + public var AttachmentMenu_File: String { return self._s[3262]! } + public var AppleWatch_Title: String { return self._s[3263]! } + public var Activity_RecordingVideoMessage: String { return self._s[3264]! } public func Channel_DiscussionGroup_PublicChannelLink(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3232]!, self._r[3232]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3265]!, self._r[3265]!, [_1, _2]) } - public var Weekday_Saturday: String { return self._s[3233]! } - public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3234]! } - public var Profile_CreateEncryptedChatError: String { return self._s[3235]! } - public var Common_Next: String { return self._s[3237]! } - public var Channel_Stickers_YourStickers: String { return self._s[3239]! } - public var Message_Theme: String { return self._s[3240]! } - public var Call_AudioRouteHeadphones: String { return self._s[3241]! } - public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3243]! } - public var Watch_Contacts_NoResults: String { return self._s[3245]! } - public var PhotoEditor_TintTool: String { return self._s[3248]! } - public var LoginPassword_ResetAccount: String { return self._s[3250]! } - public var Settings_SavedMessages: String { return self._s[3251]! } - public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3252]! } - public var Bot_GenericSupportStatus: String { return self._s[3253]! } - public var StickerPack_Add: String { return self._s[3254]! } - public var Checkout_TotalAmount: String { return self._s[3255]! } - public var Your_cards_number_is_invalid: String { return self._s[3256]! } - public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3257]! } - public var VoiceOver_Chat_VideoMessage: String { return self._s[3258]! } + public var Weekday_Saturday: String { return self._s[3266]! } + public var WallpaperPreview_SwipeColorsTopText: String { return self._s[3267]! } + public var Profile_CreateEncryptedChatError: String { return self._s[3268]! } + public var Common_Next: String { return self._s[3270]! } + public var Channel_Stickers_YourStickers: String { return self._s[3272]! } + public var Message_Theme: String { return self._s[3273]! } + public var Call_AudioRouteHeadphones: String { return self._s[3274]! } + public var TwoStepAuth_EnterPasswordForgot: String { return self._s[3276]! } + public var Watch_Contacts_NoResults: String { return self._s[3278]! } + public var PhotoEditor_TintTool: String { return self._s[3281]! } + public var LoginPassword_ResetAccount: String { return self._s[3283]! } + public var Settings_SavedMessages: String { return self._s[3284]! } + public var SettingsSearch_Synonyms_Appearance_Animations: String { return self._s[3285]! } + public var Bot_GenericSupportStatus: String { return self._s[3286]! } + public var StickerPack_Add: String { return self._s[3287]! } + public var Checkout_TotalAmount: String { return self._s[3288]! } + public var Your_cards_number_is_invalid: String { return self._s[3289]! } + public var SettingsSearch_Synonyms_Appearance_AutoNightTheme: String { return self._s[3290]! } + public var VoiceOver_Chat_VideoMessage: String { return self._s[3291]! } public func ChangePhoneNumberCode_CallTimer(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3259]!, self._r[3259]!, [_0]) + return formatWithArgumentRanges(self._s[3292]!, self._r[3292]!, [_0]) } public func GroupPermission_AddedInfo(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3260]!, self._r[3260]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3293]!, self._r[3293]!, [_1, _2]) } - public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3261]! } + public var ChatSettings_ConnectionType_UseSocks5: String { return self._s[3294]! } public func PUSH_CHAT_PHOTO_EDITED(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3263]!, self._r[3263]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3296]!, self._r[3296]!, [_1, _2]) } public func Conversation_RestrictedTextTimed(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3264]!, self._r[3264]!, [_0]) + return formatWithArgumentRanges(self._s[3297]!, self._r[3297]!, [_0]) } - public var GroupInfo_InviteLink_ShareLink: String { return self._s[3265]! } - public var StickerPack_Share: String { return self._s[3266]! } - public var Passport_DeleteAddress: String { return self._s[3267]! } - public var Settings_Passport: String { return self._s[3268]! } - public var SharedMedia_EmptyFilesText: String { return self._s[3269]! } - public var Conversation_DeleteMessagesForMe: String { return self._s[3270]! } - public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3271]! } - public var Contacts_PermissionsText: String { return self._s[3272]! } - public var Group_Setup_HistoryVisible: String { return self._s[3273]! } - public var Wallet_Month_ShortDecember: String { return self._s[3275]! } - public var Passport_Address_AddRentalAgreement: String { return self._s[3276]! } - public var SocksProxySetup_Title: String { return self._s[3277]! } - public var Notification_Mute1h: String { return self._s[3278]! } + public var GroupInfo_InviteLink_ShareLink: String { return self._s[3298]! } + public var StickerPack_Share: String { return self._s[3299]! } + public var Passport_DeleteAddress: String { return self._s[3300]! } + public var Settings_Passport: String { return self._s[3301]! } + public var SharedMedia_EmptyFilesText: String { return self._s[3302]! } + public var Conversation_DeleteMessagesForMe: String { return self._s[3303]! } + public var PasscodeSettings_AutoLock_IfAwayFor_1hour: String { return self._s[3304]! } + public var Contacts_PermissionsText: String { return self._s[3305]! } + public var Group_Setup_HistoryVisible: String { return self._s[3306]! } + public var Wallet_Month_ShortDecember: String { return self._s[3308]! } + public var Passport_Address_AddRentalAgreement: String { return self._s[3309]! } + public var SocksProxySetup_Title: String { return self._s[3310]! } + public var Notification_Mute1h: String { return self._s[3311]! } public func Passport_Email_CodeHelp(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3279]!, self._r[3279]!, [_0]) - } - public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3280]! } - public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3281]!, self._r[3281]!, [_1]) - } - public var FastTwoStepSetup_PasswordSection: String { return self._s[3282]! } - public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3285]! } - public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3287]! } - public var DialogList_NoMessagesText: String { return self._s[3288]! } - public var Privacy_ContactsResetConfirmation: String { return self._s[3289]! } - public var Privacy_Calls_P2PHelp: String { return self._s[3290]! } - public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3292]! } - public var Your_cards_expiration_year_is_invalid: String { return self._s[3293]! } - public var Common_TakePhotoOrVideo: String { return self._s[3294]! } - public var Wallet_Words_Text: String { return self._s[3295]! } - public var Call_StatusBusy: String { return self._s[3296]! } - public var Conversation_PinnedMessage: String { return self._s[3297]! } - public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3298]! } - public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3299]! } - public var Undo_ChatCleared: String { return self._s[3300]! } - public var AppleWatch_ReplyPresets: String { return self._s[3301]! } - public var Passport_DiscardMessageDescription: String { return self._s[3303]! } - public var Login_NetworkError: String { return self._s[3304]! } - public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3305]!, self._r[3305]!, [_0]) - } - public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3306]!, self._r[3306]!, [_0]) - } - public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3307]! } - public var Wallet_WordCheck_ViewWords: String { return self._s[3309]! } - public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3310]! } - public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3312]!, self._r[3312]!, [_0]) } - public var Call_ConnectionErrorMessage: String { return self._s[3313]! } - public var VoiceOver_Chat_Music: String { return self._s[3314]! } - public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3315]! } - public var Compose_GroupTokenListPlaceholder: String { return self._s[3317]! } - public var ConversationMedia_Title: String { return self._s[3318]! } - public var EncryptionKey_Title: String { return self._s[3320]! } - public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3321]! } - public var Notification_Exceptions_AddException: String { return self._s[3322]! } - public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3323]! } - public var Profile_MessageLifetime1m: String { return self._s[3324]! } + public var NotificationSettings_ShowNotificationsAllAccountsInfoOff: String { return self._s[3313]! } + public func PUSH_PINNED_GEOLIVE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3314]!, self._r[3314]!, [_1]) + } + public var FastTwoStepSetup_PasswordSection: String { return self._s[3315]! } + public var NetworkUsageSettings_ResetStatsConfirmation: String { return self._s[3318]! } + public var InfoPlist_NSFaceIDUsageDescription: String { return self._s[3320]! } + public var DialogList_NoMessagesText: String { return self._s[3321]! } + public var Privacy_ContactsResetConfirmation: String { return self._s[3322]! } + public var Privacy_Calls_P2PHelp: String { return self._s[3323]! } + public var Channel_DiscussionGroup_SearchPlaceholder: String { return self._s[3325]! } + public var Your_cards_expiration_year_is_invalid: String { return self._s[3326]! } + public var Common_TakePhotoOrVideo: String { return self._s[3327]! } + public var Wallet_Words_Text: String { return self._s[3328]! } + public var Call_StatusBusy: String { return self._s[3329]! } + public var Conversation_PinnedMessage: String { return self._s[3330]! } + public var AutoDownloadSettings_VoiceMessagesTitle: String { return self._s[3331]! } + public var TwoStepAuth_SetupPasswordConfirmFailed: String { return self._s[3332]! } + public var Undo_ChatCleared: String { return self._s[3333]! } + public var AppleWatch_ReplyPresets: String { return self._s[3334]! } + public var Passport_DiscardMessageDescription: String { return self._s[3336]! } + public var Login_NetworkError: String { return self._s[3337]! } + public func Notification_PinnedRoundMessage(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3338]!, self._r[3338]!, [_0]) + } + public func Channel_AdminLog_MessageRemovedChannelUsername(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3339]!, self._r[3339]!, [_0]) + } + public var SocksProxySetup_PasswordPlaceholder: String { return self._s[3340]! } + public var Wallet_WordCheck_ViewWords: String { return self._s[3342]! } + public var Login_ResetAccountProtected_LimitExceeded: String { return self._s[3343]! } + public func Watch_LastSeen_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3345]!, self._r[3345]!, [_0]) + } + public var Call_ConnectionErrorMessage: String { return self._s[3346]! } + public var VoiceOver_Chat_Music: String { return self._s[3347]! } + public var SettingsSearch_Synonyms_Notifications_MessageNotificationsSound: String { return self._s[3348]! } + public var Compose_GroupTokenListPlaceholder: String { return self._s[3350]! } + public var ConversationMedia_Title: String { return self._s[3351]! } + public var EncryptionKey_Title: String { return self._s[3353]! } + public var TwoStepAuth_EnterPasswordTitle: String { return self._s[3354]! } + public var Notification_Exceptions_AddException: String { return self._s[3355]! } + public var PrivacySettings_BlockedPeersEmpty: String { return self._s[3356]! } + public var Profile_MessageLifetime1m: String { return self._s[3357]! } public func Channel_AdminLog_MessageUnkickedName(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3325]!, self._r[3325]!, [_1]) + return formatWithArgumentRanges(self._s[3358]!, self._r[3358]!, [_1]) } - public var Month_GenMay: String { return self._s[3326]! } + public var Month_GenMay: String { return self._s[3359]! } public func LiveLocationUpdated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3327]!, self._r[3327]!, [_0]) + return formatWithArgumentRanges(self._s[3360]!, self._r[3360]!, [_0]) } - public var PeopleNearby_Users: String { return self._s[3328]! } - public var Wallet_Send_AddressInfo: String { return self._s[3329]! } - public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3330]! } - public var AutoDownloadSettings_ResetSettings: String { return self._s[3331]! } + public var PeopleNearby_Users: String { return self._s[3361]! } + public var Wallet_Send_AddressInfo: String { return self._s[3362]! } + public var ChannelMembers_WhoCanAddMembersAllHelp: String { return self._s[3363]! } + public var AutoDownloadSettings_ResetSettings: String { return self._s[3364]! } public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3333]!, self._r[3333]!, [_0]) + return formatWithArgumentRanges(self._s[3366]!, self._r[3366]!, [_0]) } - public var Conversation_EmptyPlaceholder: String { return self._s[3334]! } - public var Passport_Address_AddPassportRegistration: String { return self._s[3335]! } - public var Notifications_ChannelNotificationsAlert: String { return self._s[3336]! } - public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3337]! } - public var Camera_TapAndHoldForVideo: String { return self._s[3338]! } - public var Channel_JoinChannel: String { return self._s[3340]! } - public var Appearance_Animations: String { return self._s[3343]! } + public var Conversation_EmptyPlaceholder: String { return self._s[3367]! } + public var Passport_Address_AddPassportRegistration: String { return self._s[3368]! } + public var Notifications_ChannelNotificationsAlert: String { return self._s[3369]! } + public var ChatSettings_AutoDownloadUsingCellular: String { return self._s[3370]! } + public var Camera_TapAndHoldForVideo: String { return self._s[3371]! } + public var Channel_JoinChannel: String { return self._s[3373]! } + public var Appearance_Animations: String { return self._s[3376]! } public func Notification_MessageLifetimeChanged(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3344]!, self._r[3344]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3377]!, self._r[3377]!, [_1, _2]) } - public var Stickers_GroupStickers: String { return self._s[3346]! } - public var Appearance_ShareTheme: String { return self._s[3347]! } - public var ConvertToSupergroup_HelpTitle: String { return self._s[3349]! } - public var Passport_Address_Street: String { return self._s[3350]! } - public var Conversation_AddContact: String { return self._s[3351]! } - public var Login_PhonePlaceholder: String { return self._s[3352]! } - public var Channel_Members_InviteLink: String { return self._s[3354]! } - public var Bot_Stop: String { return self._s[3355]! } - public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3357]! } - public var Notification_PassportValueAddress: String { return self._s[3358]! } - public var Month_ShortJuly: String { return self._s[3359]! } - public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3360]! } - public var Channel_AdminLog_BanSendMedia: String { return self._s[3361]! } - public var Passport_Identity_ReverseSide: String { return self._s[3362]! } - public var Watch_Stickers_Recents: String { return self._s[3365]! } - public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3367]! } - public var Map_SendThisLocation: String { return self._s[3368]! } + public var Stickers_GroupStickers: String { return self._s[3379]! } + public var Appearance_ShareTheme: String { return self._s[3380]! } + public var TwoFactorSetup_Hint_Placeholder: String { return self._s[3381]! } + public var ConvertToSupergroup_HelpTitle: String { return self._s[3383]! } + public var Passport_Address_Street: String { return self._s[3384]! } + public var Conversation_AddContact: String { return self._s[3385]! } + public var Login_PhonePlaceholder: String { return self._s[3386]! } + public var Channel_Members_InviteLink: String { return self._s[3388]! } + public var Bot_Stop: String { return self._s[3389]! } + public var SettingsSearch_Synonyms_Proxy_UseForCalls: String { return self._s[3391]! } + public var Notification_PassportValueAddress: String { return self._s[3392]! } + public var Month_ShortJuly: String { return self._s[3393]! } + public var Passport_Address_TypeTemporaryRegistrationUploadScan: String { return self._s[3394]! } + public var Channel_AdminLog_BanSendMedia: String { return self._s[3395]! } + public var Passport_Identity_ReverseSide: String { return self._s[3396]! } + public var Watch_Stickers_Recents: String { return self._s[3399]! } + public var PrivacyLastSeenSettings_EmpryUsersPlaceholder: String { return self._s[3401]! } + public var Map_SendThisLocation: String { return self._s[3402]! } public func Time_MonthOfYear_m1(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3369]!, self._r[3369]!, [_0]) + return formatWithArgumentRanges(self._s[3403]!, self._r[3403]!, [_0]) } public func InviteText_SingleContact(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3370]!, self._r[3370]!, [_0]) - } - public var ConvertToSupergroup_Note: String { return self._s[3371]! } - public var Wallet_Intro_NotNow: String { return self._s[3372]! } - public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3373]!, self._r[3373]!, [_0]) - } - public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3374]! } - public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3375]!, self._r[3375]!, [_0, _1]) - } - public var Login_CallRequestState3: String { return self._s[3377]! } - public var Wallpaper_SearchShort: String { return self._s[3378]! } - public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3380]! } - public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3381]! } - public var Channel_BotDoesntSupportGroups: String { return self._s[3382]! } - public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3383]!, self._r[3383]!, [_1, _2]) - } - public var Channel_AdminLogFilter_Title: String { return self._s[3384]! } - public var Notifications_GroupNotificationsExceptions: String { return self._s[3388]! } - public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3389]!, self._r[3389]!, [_0]) - } - public var Passport_CorrectErrors: String { return self._s[3390]! } - public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3391]! } - public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3392]!, self._r[3392]!, [_0]) - } - public var Map_SendMyCurrentLocation: String { return self._s[3393]! } - public var Channel_DiscussionGroup: String { return self._s[3394]! } - public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3395]!, self._r[3395]!, [_1, _2]) - } - public var SharedMedia_SearchNoResults: String { return self._s[3396]! } - public var Permissions_NotificationsText_v0: String { return self._s[3397]! } - public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3398]! } - public var Appearance_AppIcon: String { return self._s[3399]! } - public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3400]! } - public var LoginPassword_FloodError: String { return self._s[3401]! } - public var Group_Setup_HistoryHiddenHelp: String { return self._s[3403]! } - public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3404]!, self._r[3404]!, [_0]) } - public var Passport_Language_bn: String { return self._s[3405]! } - public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3406]!, self._r[3406]!, [_0]) + public var ConvertToSupergroup_Note: String { return self._s[3405]! } + public var Wallet_Intro_NotNow: String { return self._s[3406]! } + public func FileSize_MB(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3407]!, self._r[3407]!, [_0]) } - public var ChatList_Context_Pin: String { return self._s[3407]! } + public var NetworkUsageSettings_GeneralDataSection: String { return self._s[3408]! } + public func Compatibility_SecretMediaVersionTooLow(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3409]!, self._r[3409]!, [_0, _1]) + } + public var Login_CallRequestState3: String { return self._s[3411]! } + public var Wallpaper_SearchShort: String { return self._s[3412]! } + public var SettingsSearch_Synonyms_Appearance_ColorTheme: String { return self._s[3414]! } + public var PasscodeSettings_UnlockWithFaceId: String { return self._s[3415]! } + public var Channel_BotDoesntSupportGroups: String { return self._s[3416]! } + public func PUSH_CHAT_MESSAGE_GEOLIVE(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3417]!, self._r[3417]!, [_1, _2]) + } + public var Channel_AdminLogFilter_Title: String { return self._s[3418]! } + public var Notifications_GroupNotificationsExceptions: String { return self._s[3422]! } + public func FileSize_B(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3423]!, self._r[3423]!, [_0]) + } + public var Passport_CorrectErrors: String { return self._s[3424]! } + public var VoiceOver_Chat_YourAnonymousPoll: String { return self._s[3425]! } + public func Channel_MessageTitleUpdated(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3426]!, self._r[3426]!, [_0]) + } + public var Map_SendMyCurrentLocation: String { return self._s[3427]! } + public var Channel_DiscussionGroup: String { return self._s[3428]! } + public var TwoFactorSetup_Email_SkipConfirmationSkip: String { return self._s[3429]! } + public func PUSH_PINNED_CONTACT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3430]!, self._r[3430]!, [_1, _2]) + } + public var SharedMedia_SearchNoResults: String { return self._s[3431]! } + public var Permissions_NotificationsText_v0: String { return self._s[3432]! } + public var Channel_EditAdmin_PermissionDeleteMessagesOfOthers: String { return self._s[3433]! } + public var Appearance_AppIcon: String { return self._s[3434]! } + public var Appearance_ThemePreview_ChatList_3_AuthorName: String { return self._s[3435]! } + public var LoginPassword_FloodError: String { return self._s[3436]! } + public var Group_Setup_HistoryHiddenHelp: String { return self._s[3438]! } + public func TwoStepAuth_PendingEmailHelp(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3439]!, self._r[3439]!, [_0]) + } + public var Passport_Language_bn: String { return self._s[3440]! } + public func DialogList_SingleUploadingPhotoSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3441]!, self._r[3441]!, [_0]) + } + public var ChatList_Context_Pin: String { return self._s[3442]! } public func Notification_PinnedAudioMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3408]!, self._r[3408]!, [_0]) + return formatWithArgumentRanges(self._s[3443]!, self._r[3443]!, [_0]) } public func Channel_AdminLog_MessageChangedGroupStickerPack(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3409]!, self._r[3409]!, [_0]) + return formatWithArgumentRanges(self._s[3444]!, self._r[3444]!, [_0]) } - public var Wallet_Navigation_Close: String { return self._s[3410]! } - public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3414]! } - public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3416]! } - public var Wallet_Month_GenDecember: String { return self._s[3417]! } - public var Contacts_PermissionsAllow: String { return self._s[3418]! } - public var ReportPeer_ReasonCopyright: String { return self._s[3419]! } - public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3420]! } - public var WallpaperPreview_Pattern: String { return self._s[3421]! } - public var Paint_Duplicate: String { return self._s[3422]! } - public var Passport_Address_Country: String { return self._s[3423]! } - public var Notification_RenamedChannel: String { return self._s[3425]! } - public var ChatList_Context_Unmute: String { return self._s[3426]! } - public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3427]! } - public var Group_MessagePhotoUpdated: String { return self._s[3428]! } - public var Channel_BanUser_PermissionSendMedia: String { return self._s[3429]! } - public var Conversation_ContextMenuBan: String { return self._s[3430]! } - public var TwoStepAuth_EmailSent: String { return self._s[3431]! } - public var MessagePoll_NoVotes: String { return self._s[3432]! } - public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3433]! } - public var Passport_Language_is: String { return self._s[3434]! } - public var PeopleNearby_UsersEmpty: String { return self._s[3436]! } - public var Tour_Text5: String { return self._s[3437]! } + public var Wallet_Navigation_Close: String { return self._s[3445]! } + public var GroupInfo_InvitationLinkGroupFull: String { return self._s[3449]! } + public var Group_EditAdmin_PermissionChangeInfo: String { return self._s[3451]! } + public var Wallet_Month_GenDecember: String { return self._s[3452]! } + public var Contacts_PermissionsAllow: String { return self._s[3453]! } + public var ReportPeer_ReasonCopyright: String { return self._s[3454]! } + public var Channel_EditAdmin_PermissinAddAdminOn: String { return self._s[3455]! } + public var WallpaperPreview_Pattern: String { return self._s[3456]! } + public var Paint_Duplicate: String { return self._s[3457]! } + public var Passport_Address_Country: String { return self._s[3458]! } + public var Notification_RenamedChannel: String { return self._s[3460]! } + public var ChatList_Context_Unmute: String { return self._s[3461]! } + public var CheckoutInfo_ErrorPostcodeInvalid: String { return self._s[3462]! } + public var Group_MessagePhotoUpdated: String { return self._s[3463]! } + public var Channel_BanUser_PermissionSendMedia: String { return self._s[3464]! } + public var Conversation_ContextMenuBan: String { return self._s[3465]! } + public var TwoStepAuth_EmailSent: String { return self._s[3466]! } + public var MessagePoll_NoVotes: String { return self._s[3467]! } + public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[3468]! } + public var Passport_Language_is: String { return self._s[3469]! } + public var PeopleNearby_UsersEmpty: String { return self._s[3471]! } + public var Tour_Text5: String { return self._s[3472]! } public func Call_GroupFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3439]!, self._r[3439]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3474]!, self._r[3474]!, [_1, _2]) } - public var Undo_SecretChatDeleted: String { return self._s[3440]! } - public var SocksProxySetup_ShareQRCode: String { return self._s[3441]! } + public var Undo_SecretChatDeleted: String { return self._s[3475]! } + public var SocksProxySetup_ShareQRCode: String { return self._s[3476]! } public func VoiceOver_Chat_Size(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3442]!, self._r[3442]!, [_0]) + return formatWithArgumentRanges(self._s[3477]!, self._r[3477]!, [_0]) } - public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3443]! } - public var Paint_Edit: String { return self._s[3445]! } - public var ScheduledMessages_ReminderNotification: String { return self._s[3447]! } - public var Undo_DeletedGroup: String { return self._s[3449]! } - public var LoginPassword_ForgotPassword: String { return self._s[3450]! } - public var Wallet_WordImport_IncorrectTitle: String { return self._s[3451]! } - public var GroupInfo_GroupNamePlaceholder: String { return self._s[3452]! } + public var LogoutOptions_ChangePhoneNumberText: String { return self._s[3478]! } + public var Paint_Edit: String { return self._s[3480]! } + public var ScheduledMessages_ReminderNotification: String { return self._s[3482]! } + public var Undo_DeletedGroup: String { return self._s[3484]! } + public var LoginPassword_ForgotPassword: String { return self._s[3485]! } + public var Wallet_WordImport_IncorrectTitle: String { return self._s[3486]! } + public var GroupInfo_GroupNamePlaceholder: String { return self._s[3487]! } public func Notification_Kicked(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3453]!, self._r[3453]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3488]!, self._r[3488]!, [_0, _1]) } - public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3454]! } - public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3455]! } - public var Passport_Language_uz: String { return self._s[3456]! } - public var Conversation_PinMessageAlertGroup: String { return self._s[3457]! } - public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3458]! } - public var Map_StopLiveLocation: String { return self._s[3460]! } - public var VoiceOver_MessageContextSend: String { return self._s[3462]! } - public var PasscodeSettings_Help: String { return self._s[3463]! } - public var NotificationsSound_Input: String { return self._s[3464]! } - public var Share_Title: String { return self._s[3467]! } - public var LogoutOptions_Title: String { return self._s[3468]! } - public var Wallet_Send_AddressText: String { return self._s[3469]! } - public var Login_TermsOfServiceAgree: String { return self._s[3470]! } - public var Compose_NewEncryptedChatTitle: String { return self._s[3471]! } - public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3472]! } - public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3473]! } - public var EnterPasscode_EnterTitle: String { return self._s[3474]! } + public var Conversation_InputTextCaptionPlaceholder: String { return self._s[3489]! } + public var AutoDownloadSettings_VideoMessagesTitle: String { return self._s[3490]! } + public var Passport_Language_uz: String { return self._s[3491]! } + public var Conversation_PinMessageAlertGroup: String { return self._s[3492]! } + public var SettingsSearch_Synonyms_Privacy_GroupsAndChannels: String { return self._s[3493]! } + public var Map_StopLiveLocation: String { return self._s[3495]! } + public var VoiceOver_MessageContextSend: String { return self._s[3497]! } + public var PasscodeSettings_Help: String { return self._s[3498]! } + public var NotificationsSound_Input: String { return self._s[3499]! } + public var Share_Title: String { return self._s[3502]! } + public var LogoutOptions_Title: String { return self._s[3503]! } + public var Wallet_Send_AddressText: String { return self._s[3504]! } + public var Login_TermsOfServiceAgree: String { return self._s[3505]! } + public var Compose_NewEncryptedChatTitle: String { return self._s[3506]! } + public var Channel_AdminLog_TitleSelectedEvents: String { return self._s[3507]! } + public var Channel_EditAdmin_PermissionEditMessages: String { return self._s[3508]! } + public var EnterPasscode_EnterTitle: String { return self._s[3509]! } public func Call_PrivacyErrorMessage(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3475]!, self._r[3475]!, [_0]) + return formatWithArgumentRanges(self._s[3510]!, self._r[3510]!, [_0]) } - public var Settings_CopyPhoneNumber: String { return self._s[3476]! } - public var Conversation_AddToContacts: String { return self._s[3477]! } + public var Settings_CopyPhoneNumber: String { return self._s[3511]! } + public var Conversation_AddToContacts: String { return self._s[3512]! } public func VoiceOver_Chat_ReplyFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3478]!, self._r[3478]!, [_0]) + return formatWithArgumentRanges(self._s[3513]!, self._r[3513]!, [_0]) } - public var NotificationsSound_Keys: String { return self._s[3479]! } + public var NotificationsSound_Keys: String { return self._s[3514]! } public func Call_ParticipantVersionOutdatedError(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3480]!, self._r[3480]!, [_0]) + return formatWithArgumentRanges(self._s[3515]!, self._r[3515]!, [_0]) } - public var Notification_MessageLifetime1w: String { return self._s[3481]! } - public var Message_Video: String { return self._s[3482]! } - public var AutoDownloadSettings_CellularTitle: String { return self._s[3483]! } + public var Notification_MessageLifetime1w: String { return self._s[3516]! } + public var Message_Video: String { return self._s[3517]! } + public var AutoDownloadSettings_CellularTitle: String { return self._s[3518]! } public func PUSH_CHANNEL_MESSAGE_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3484]!, self._r[3484]!, [_1]) + return formatWithArgumentRanges(self._s[3519]!, self._r[3519]!, [_1]) } - public var Wallet_Receive_AmountInfo: String { return self._s[3487]! } + public var Wallet_Receive_AmountInfo: String { return self._s[3522]! } public func Notification_JoinedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3488]!, self._r[3488]!, [_0]) + return formatWithArgumentRanges(self._s[3523]!, self._r[3523]!, [_0]) } public func PrivacySettings_LastSeenContactsPlus(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3489]!, self._r[3489]!, [_0]) + return formatWithArgumentRanges(self._s[3524]!, self._r[3524]!, [_0]) } - public var Passport_Language_mk: String { return self._s[3490]! } + public var Passport_Language_mk: String { return self._s[3525]! } public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3491]!, self._r[3491]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3526]!, self._r[3526]!, [_1, _2, _3]) } - public var CreatePoll_CancelConfirmation: String { return self._s[3492]! } - public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3494]! } - public var PrivacyPolicy_Decline: String { return self._s[3495]! } - public var Passport_Identity_DoesNotExpire: String { return self._s[3496]! } - public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3497]! } - public var Permissions_SiriAllow_v0: String { return self._s[3499]! } - public var Wallet_Month_ShortAugust: String { return self._s[3500]! } - public var Appearance_ThemeCarouselNight: String { return self._s[3501]! } + public var CreatePoll_CancelConfirmation: String { return self._s[3527]! } + public var Conversation_SilentBroadcastTooltipOn: String { return self._s[3529]! } + public var PrivacyPolicy_Decline: String { return self._s[3530]! } + public var Passport_Identity_DoesNotExpire: String { return self._s[3531]! } + public var Channel_AdminLogFilter_EventsRestrictions: String { return self._s[3532]! } + public var Permissions_SiriAllow_v0: String { return self._s[3534]! } + public var Wallet_Month_ShortAugust: String { return self._s[3535]! } + public var Appearance_ThemeCarouselNight: String { return self._s[3536]! } public func LOCAL_CHAT_MESSAGE_FWDS(_ _1: String, _ _2: Int) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3502]!, self._r[3502]!, [_1, "\(_2)"]) + return formatWithArgumentRanges(self._s[3537]!, self._r[3537]!, [_1, "\(_2)"]) } public func Notification_RenamedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3503]!, self._r[3503]!, [_0]) + return formatWithArgumentRanges(self._s[3538]!, self._r[3538]!, [_0]) } - public var Paint_Regular: String { return self._s[3504]! } - public var ChatSettings_AutoDownloadReset: String { return self._s[3505]! } - public var SocksProxySetup_ShareLink: String { return self._s[3506]! } - public var Wallet_Qr_Title: String { return self._s[3507]! } - public var BlockedUsers_SelectUserTitle: String { return self._s[3508]! } - public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3510]! } - public var Wallet_Settings_Configuration: String { return self._s[3511]! } - public var GroupInfo_InviteByLink: String { return self._s[3512]! } - public var MessageTimer_Custom: String { return self._s[3513]! } - public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3514]! } - public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3516]! } - public var Conversation_SendMessage_SetReminder: String { return self._s[3517]! } - public var VoiceOver_Chat_Selected: String { return self._s[3518]! } - public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3519]! } - public var Channel_Username_InvalidTaken: String { return self._s[3520]! } - public var Conversation_ClousStorageInfo_Description3: String { return self._s[3521]! } - public var Wallet_WordCheck_TryAgain: String { return self._s[3522]! } - public var Wallet_Info_TransactionPendingHeader: String { return self._s[3523]! } - public var Settings_ChatBackground: String { return self._s[3524]! } - public var Channel_Subscribers_Title: String { return self._s[3525]! } - public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3526]! } - public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3527]! } - public var Watch_ConnectionDescription: String { return self._s[3528]! } - public var ChatList_ArchivedChatsTitle: String { return self._s[3532]! } - public var Wallpaper_ResetWallpapers: String { return self._s[3533]! } - public var EditProfile_Title: String { return self._s[3534]! } - public var NotificationsSound_Bamboo: String { return self._s[3536]! } - public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3538]! } - public var Login_SmsRequestState2: String { return self._s[3539]! } - public var Passport_Language_ar: String { return self._s[3540]! } + public var Paint_Regular: String { return self._s[3539]! } + public var ChatSettings_AutoDownloadReset: String { return self._s[3540]! } + public var SocksProxySetup_ShareLink: String { return self._s[3541]! } + public var Wallet_Qr_Title: String { return self._s[3542]! } + public var BlockedUsers_SelectUserTitle: String { return self._s[3543]! } + public var VoiceOver_Chat_RecordModeVoiceMessage: String { return self._s[3545]! } + public var Wallet_Settings_Configuration: String { return self._s[3546]! } + public var GroupInfo_InviteByLink: String { return self._s[3547]! } + public var MessageTimer_Custom: String { return self._s[3548]! } + public var UserInfo_NotificationsDefaultEnabled: String { return self._s[3549]! } + public var Passport_Address_TypeTemporaryRegistration: String { return self._s[3551]! } + public var Conversation_SendMessage_SetReminder: String { return self._s[3552]! } + public var VoiceOver_Chat_Selected: String { return self._s[3553]! } + public var ChatSettings_AutoDownloadUsingWiFi: String { return self._s[3554]! } + public var Channel_Username_InvalidTaken: String { return self._s[3555]! } + public var Conversation_ClousStorageInfo_Description3: String { return self._s[3556]! } + public var Wallet_WordCheck_TryAgain: String { return self._s[3557]! } + public var Wallet_Info_TransactionPendingHeader: String { return self._s[3558]! } + public var Settings_ChatBackground: String { return self._s[3559]! } + public var Channel_Subscribers_Title: String { return self._s[3560]! } + public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[3561]! } + public var ApplyLanguage_ChangeLanguageTitle: String { return self._s[3562]! } + public var Watch_ConnectionDescription: String { return self._s[3563]! } + public var ChatList_ArchivedChatsTitle: String { return self._s[3567]! } + public var Wallpaper_ResetWallpapers: String { return self._s[3568]! } + public var EditProfile_Title: String { return self._s[3569]! } + public var NotificationsSound_Bamboo: String { return self._s[3571]! } + public var Channel_AdminLog_MessagePreviousMessage: String { return self._s[3573]! } + public var Login_SmsRequestState2: String { return self._s[3574]! } + public var Passport_Language_ar: String { return self._s[3575]! } public func Message_AuthorPinnedGame(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3541]!, self._r[3541]!, [_0]) + return formatWithArgumentRanges(self._s[3576]!, self._r[3576]!, [_0]) } - public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3542]! } - public var Wallet_Created_Text: String { return self._s[3543]! } - public var Conversation_MessageDialogEdit: String { return self._s[3544]! } - public var Wallet_Created_Proceed: String { return self._s[3545]! } - public var Wallet_Words_Done: String { return self._s[3546]! } - public var VoiceOver_Media_PlaybackPause: String { return self._s[3547]! } + public var SettingsSearch_Synonyms_EditProfile_Title: String { return self._s[3577]! } + public var Wallet_Created_Text: String { return self._s[3578]! } + public var Conversation_MessageDialogEdit: String { return self._s[3579]! } + public var Wallet_Created_Proceed: String { return self._s[3580]! } + public var Wallet_Words_Done: String { return self._s[3581]! } + public var VoiceOver_Media_PlaybackPause: String { return self._s[3582]! } public func PUSH_AUTH_UNKNOWN(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3548]!, self._r[3548]!, [_1]) + return formatWithArgumentRanges(self._s[3583]!, self._r[3583]!, [_1]) } - public var Common_Close: String { return self._s[3549]! } - public var GroupInfo_PublicLink: String { return self._s[3550]! } - public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3551]! } - public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3552]! } + public var Common_Close: String { return self._s[3584]! } + public var GroupInfo_PublicLink: String { return self._s[3585]! } + public var Channel_OwnershipTransfer_ErrorPrivacyRestricted: String { return self._s[3586]! } + public var SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview: String { return self._s[3587]! } public func Channel_AdminLog_MessageToggleInvitesOff(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3556]!, self._r[3556]!, [_0]) + return formatWithArgumentRanges(self._s[3591]!, self._r[3591]!, [_0]) } - public var UserInfo_About_Placeholder: String { return self._s[3557]! } + public var UserInfo_About_Placeholder: String { return self._s[3592]! } public func Conversation_FileHowToText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3558]!, self._r[3558]!, [_0]) + return formatWithArgumentRanges(self._s[3593]!, self._r[3593]!, [_0]) } - public var GroupInfo_Permissions_SectionTitle: String { return self._s[3559]! } - public var Channel_Info_Banned: String { return self._s[3561]! } + public var GroupInfo_Permissions_SectionTitle: String { return self._s[3594]! } + public var Channel_Info_Banned: String { return self._s[3596]! } public func Time_MonthOfYear_m11(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3562]!, self._r[3562]!, [_0]) + return formatWithArgumentRanges(self._s[3597]!, self._r[3597]!, [_0]) } - public var Appearance_Other: String { return self._s[3563]! } - public var Passport_Language_my: String { return self._s[3564]! } - public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3565]! } + public var Appearance_Other: String { return self._s[3598]! } + public var Passport_Language_my: String { return self._s[3599]! } + public var Group_Setup_BasicHistoryHiddenHelp: String { return self._s[3600]! } public func Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3566]!, self._r[3566]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3601]!, self._r[3601]!, [_1, _2, _3]) } - public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3567]! } - public var Preview_CopyAddress: String { return self._s[3568]! } + public var SettingsSearch_Synonyms_Privacy_PasscodeAndFaceId: String { return self._s[3602]! } + public var Preview_CopyAddress: String { return self._s[3603]! } public func DialogList_SinglePlayingGameSuffix(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3569]!, self._r[3569]!, [_0]) - } - public var KeyCommand_JumpToPreviousChat: String { return self._s[3570]! } - public var UserInfo_BotSettings: String { return self._s[3571]! } - public var LiveLocation_MenuStopAll: String { return self._s[3573]! } - public var Passport_PasswordCreate: String { return self._s[3574]! } - public var StickerSettings_MaskContextInfo: String { return self._s[3575]! } - public var Message_PinnedLocationMessage: String { return self._s[3576]! } - public var Map_Satellite: String { return self._s[3577]! } - public var Watch_Message_Unsupported: String { return self._s[3578]! } - public var Username_TooManyPublicUsernamesError: String { return self._s[3579]! } - public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3580]! } - public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3581]!, self._r[3581]!, [_0, _1]) - } - public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3582]!, self._r[3582]!, [_0]) - } - public var Wallet_WordImport_Continue: String { return self._s[3583]! } - public var Notifications_ChannelNotificationsHelp: String { return self._s[3584]! } - public var Privacy_Calls_P2PContacts: String { return self._s[3585]! } - public var NotificationsSound_None: String { return self._s[3586]! } - public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3587]! } - public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3589]! } - public var AccessDenied_VoiceMicrophone: String { return self._s[3590]! } - public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3591]!, self._r[3591]!, [_1]) - } - public var Cache_Indexing: String { return self._s[3592]! } - public var DialogList_RecentTitlePeople: String { return self._s[3594]! } - public var DialogList_EncryptionRejected: String { return self._s[3595]! } - public var GroupInfo_Administrators: String { return self._s[3596]! } - public var Passport_ScanPassportHelp: String { return self._s[3597]! } - public var Application_Name: String { return self._s[3598]! } - public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3599]! } - public var Appearance_ThemeCarouselDay: String { return self._s[3601]! } - public var Passport_Identity_TranslationHelp: String { return self._s[3602]! } - public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3603]!, self._r[3603]!, [_0]) - } - public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3604]!, self._r[3604]!, [_0]) } + public var KeyCommand_JumpToPreviousChat: String { return self._s[3605]! } + public var UserInfo_BotSettings: String { return self._s[3606]! } + public var LiveLocation_MenuStopAll: String { return self._s[3608]! } + public var Passport_PasswordCreate: String { return self._s[3609]! } + public var StickerSettings_MaskContextInfo: String { return self._s[3610]! } + public var Message_PinnedLocationMessage: String { return self._s[3611]! } + public var Map_Satellite: String { return self._s[3612]! } + public var Watch_Message_Unsupported: String { return self._s[3613]! } + public var Username_TooManyPublicUsernamesError: String { return self._s[3614]! } + public var TwoStepAuth_EnterPasswordInvalid: String { return self._s[3615]! } + public func Notification_PinnedTextMessage(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3616]!, self._r[3616]!, [_0, _1]) + } + public func Conversation_OpenBotLinkText(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3617]!, self._r[3617]!, [_0]) + } + public var Wallet_WordImport_Continue: String { return self._s[3618]! } + public func TwoFactorSetup_EmailVerification_Text(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3619]!, self._r[3619]!, [_0]) + } + public var Notifications_ChannelNotificationsHelp: String { return self._s[3620]! } + public var Privacy_Calls_P2PContacts: String { return self._s[3621]! } + public var NotificationsSound_None: String { return self._s[3622]! } + public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[3623]! } + public var Channel_DiscussionGroup_UnlinkGroup: String { return self._s[3625]! } + public var AccessDenied_VoiceMicrophone: String { return self._s[3626]! } + public func ApplyLanguage_ChangeLanguageAlreadyActive(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3627]!, self._r[3627]!, [_1]) + } + public var Cache_Indexing: String { return self._s[3628]! } + public var DialogList_RecentTitlePeople: String { return self._s[3630]! } + public var DialogList_EncryptionRejected: String { return self._s[3631]! } + public var GroupInfo_Administrators: String { return self._s[3632]! } + public var Passport_ScanPassportHelp: String { return self._s[3633]! } + public var Application_Name: String { return self._s[3634]! } + public var Channel_AdminLogFilter_ChannelEventsInfo: String { return self._s[3635]! } + public var Appearance_ThemeCarouselDay: String { return self._s[3637]! } + public var Passport_Identity_TranslationHelp: String { return self._s[3638]! } + public func VoiceOver_Chat_VideoMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3639]!, self._r[3639]!, [_0]) + } + public func Notification_JoinedGroupByLink(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3640]!, self._r[3640]!, [_0]) + } public func DialogList_EncryptedChatStartedOutgoing(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3605]!, self._r[3605]!, [_0]) + return formatWithArgumentRanges(self._s[3641]!, self._r[3641]!, [_0]) } - public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3606]! } - public var Privacy_ChatsTitle: String { return self._s[3607]! } - public var DialogList_ClearHistoryConfirmation: String { return self._s[3608]! } - public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3609]! } - public var Watch_Suggestion_HoldOn: String { return self._s[3610]! } - public var Group_EditAdmin_TransferOwnership: String { return self._s[3611]! } - public var Group_LinkedChannel: String { return self._s[3612]! } - public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3613]! } - public var SocksProxySetup_RequiredCredentials: String { return self._s[3614]! } - public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3615]! } - public var TwoStepAuth_EmailSkipAlert: String { return self._s[3616]! } - public var ScheduledMessages_RemindersTitle: String { return self._s[3618]! } - public var Channel_Setup_TypePublic: String { return self._s[3620]! } + public var Channel_EditAdmin_PermissionDeleteMessages: String { return self._s[3642]! } + public var Privacy_ChatsTitle: String { return self._s[3643]! } + public var DialogList_ClearHistoryConfirmation: String { return self._s[3644]! } + public var SettingsSearch_Synonyms_Data_Storage_ClearCache: String { return self._s[3645]! } + public var Watch_Suggestion_HoldOn: String { return self._s[3646]! } + public var Group_EditAdmin_TransferOwnership: String { return self._s[3647]! } + public var Group_LinkedChannel: String { return self._s[3648]! } + public var VoiceOver_Chat_SeenByRecipient: String { return self._s[3649]! } + public var SocksProxySetup_RequiredCredentials: String { return self._s[3650]! } + public var Passport_Address_TypeRentalAgreementUploadScan: String { return self._s[3651]! } + public var TwoStepAuth_EmailSkipAlert: String { return self._s[3652]! } + public var ScheduledMessages_RemindersTitle: String { return self._s[3654]! } + public var Channel_Setup_TypePublic: String { return self._s[3656]! } public func Channel_AdminLog_MessageToggleInvitesOn(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3621]!, self._r[3621]!, [_0]) + return formatWithArgumentRanges(self._s[3657]!, self._r[3657]!, [_0]) } - public var Channel_TypeSetup_Title: String { return self._s[3623]! } - public var Map_OpenInMaps: String { return self._s[3625]! } + public var Channel_TypeSetup_Title: String { return self._s[3659]! } + public var Map_OpenInMaps: String { return self._s[3661]! } public func PUSH_PINNED_NOTEXT(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3626]!, self._r[3626]!, [_1]) + return formatWithArgumentRanges(self._s[3662]!, self._r[3662]!, [_1]) } - public var NotificationsSound_Tremolo: String { return self._s[3628]! } + public var NotificationsSound_Tremolo: String { return self._s[3664]! } public func Date_ChatDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3629]!, self._r[3629]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3665]!, self._r[3665]!, [_1, _2, _3]) } - public var ConversationProfile_UnknownAddMemberError: String { return self._s[3630]! } - public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3631]! } - public var Passport_PasswordHelp: String { return self._s[3632]! } - public var Login_CodeExpiredError: String { return self._s[3633]! } - public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3634]! } - public var Conversation_TitleUnmute: String { return self._s[3635]! } - public var Passport_Identity_ScansHelp: String { return self._s[3636]! } - public var Passport_Language_lo: String { return self._s[3637]! } - public var Camera_FlashAuto: String { return self._s[3638]! } - public var Conversation_OpenBotLinkOpen: String { return self._s[3639]! } - public var Common_Cancel: String { return self._s[3640]! } - public var DialogList_SavedMessagesTooltip: String { return self._s[3641]! } - public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3642]! } - public var Appearance_TintAllColors: String { return self._s[3643]! } + public var ConversationProfile_UnknownAddMemberError: String { return self._s[3666]! } + public var Channel_OwnershipTransfer_PasswordPlaceholder: String { return self._s[3667]! } + public var Passport_PasswordHelp: String { return self._s[3668]! } + public var Login_CodeExpiredError: String { return self._s[3669]! } + public var Channel_EditAdmin_PermissionChangeInfo: String { return self._s[3670]! } + public var Conversation_TitleUnmute: String { return self._s[3671]! } + public var Passport_Identity_ScansHelp: String { return self._s[3672]! } + public var Passport_Language_lo: String { return self._s[3673]! } + public var Camera_FlashAuto: String { return self._s[3674]! } + public var Conversation_OpenBotLinkOpen: String { return self._s[3675]! } + public var Common_Cancel: String { return self._s[3676]! } + public var DialogList_SavedMessagesTooltip: String { return self._s[3677]! } + public var TwoStepAuth_SetupPasswordTitle: String { return self._s[3678]! } + public var Appearance_TintAllColors: String { return self._s[3679]! } public func PUSH_MESSAGE_FWD(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3644]!, self._r[3644]!, [_1]) + return formatWithArgumentRanges(self._s[3680]!, self._r[3680]!, [_1]) } - public var Conversation_ReportSpamConfirmation: String { return self._s[3645]! } - public var ChatSettings_Title: String { return self._s[3647]! } - public var Passport_PasswordReset: String { return self._s[3648]! } - public var SocksProxySetup_TypeNone: String { return self._s[3649]! } - public var EditTheme_Title: String { return self._s[3651]! } - public var PhoneNumberHelp_Help: String { return self._s[3652]! } - public var Checkout_EnterPassword: String { return self._s[3653]! } - public var Share_AuthTitle: String { return self._s[3655]! } - public var Activity_UploadingDocument: String { return self._s[3656]! } - public var State_Connecting: String { return self._s[3657]! } - public var Profile_MessageLifetime1w: String { return self._s[3658]! } - public var Conversation_ContextMenuReport: String { return self._s[3659]! } - public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3660]! } - public var AutoNightTheme_ScheduledTo: String { return self._s[3661]! } + public var Conversation_ReportSpamConfirmation: String { return self._s[3681]! } + public var ChatSettings_Title: String { return self._s[3683]! } + public var Passport_PasswordReset: String { return self._s[3684]! } + public var SocksProxySetup_TypeNone: String { return self._s[3685]! } + public var EditTheme_Title: String { return self._s[3687]! } + public var PhoneNumberHelp_Help: String { return self._s[3688]! } + public var Checkout_EnterPassword: String { return self._s[3689]! } + public var Share_AuthTitle: String { return self._s[3691]! } + public var Activity_UploadingDocument: String { return self._s[3692]! } + public var State_Connecting: String { return self._s[3693]! } + public var Profile_MessageLifetime1w: String { return self._s[3694]! } + public var Conversation_ContextMenuReport: String { return self._s[3695]! } + public var CheckoutInfo_ReceiverInfoPhone: String { return self._s[3696]! } + public var AutoNightTheme_ScheduledTo: String { return self._s[3697]! } public func VoiceOver_Chat_AnonymousPollFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3662]!, self._r[3662]!, [_0]) + return formatWithArgumentRanges(self._s[3698]!, self._r[3698]!, [_0]) } - public var AuthSessions_Terminate: String { return self._s[3663]! } - public var Wallet_WordImport_CanNotRemember: String { return self._s[3664]! } - public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3665]! } - public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3666]! } - public var PhotoEditor_Set: String { return self._s[3667]! } - public var EmptyGroupInfo_Title: String { return self._s[3668]! } - public var Login_PadPhoneHelp: String { return self._s[3669]! } - public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3671]! } - public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3673]! } - public var NotificationsSound_Complete: String { return self._s[3674]! } - public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3675]! } - public var Group_Info_AdminLog: String { return self._s[3676]! } - public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3677]! } + public var AuthSessions_Terminate: String { return self._s[3699]! } + public var Wallet_WordImport_CanNotRemember: String { return self._s[3700]! } + public var Checkout_NewCard_CardholderNamePlaceholder: String { return self._s[3701]! } + public var KeyCommand_JumpToPreviousUnreadChat: String { return self._s[3702]! } + public var PhotoEditor_Set: String { return self._s[3703]! } + public var EmptyGroupInfo_Title: String { return self._s[3704]! } + public var Login_PadPhoneHelp: String { return self._s[3705]! } + public var AutoDownloadSettings_TypeGroupChats: String { return self._s[3707]! } + public var PrivacyPolicy_DeclineLastWarning: String { return self._s[3709]! } + public var NotificationsSound_Complete: String { return self._s[3710]! } + public var SettingsSearch_Synonyms_Privacy_Data_Title: String { return self._s[3711]! } + public var Group_Info_AdminLog: String { return self._s[3712]! } + public var GroupPermission_NotAvailableInPublicGroups: String { return self._s[3713]! } public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3678]!, self._r[3678]!, [_1, _2, _3]) + return formatWithArgumentRanges(self._s[3714]!, self._r[3714]!, [_1, _2, _3]) } - public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3679]! } - public var Conversation_Admin: String { return self._s[3681]! } - public var Conversation_GifTooltip: String { return self._s[3682]! } - public var Passport_NotLoggedInMessage: String { return self._s[3683]! } + public var Channel_AdminLog_InfoPanelAlertText: String { return self._s[3715]! } + public var Conversation_Admin: String { return self._s[3717]! } + public var Conversation_GifTooltip: String { return self._s[3718]! } + public var Passport_NotLoggedInMessage: String { return self._s[3719]! } public func AutoDownloadSettings_OnFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3685]!, self._r[3685]!, [_0]) + return formatWithArgumentRanges(self._s[3721]!, self._r[3721]!, [_0]) } - public var Profile_MessageLifetimeForever: String { return self._s[3686]! } - public var SharedMedia_EmptyTitle: String { return self._s[3688]! } - public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3690]! } - public var Username_Help: String { return self._s[3691]! } - public var DialogList_LanguageTooltip: String { return self._s[3693]! } - public var Map_LoadError: String { return self._s[3694]! } - public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3695]! } - public var Channel_AdminLog_AddMembers: String { return self._s[3696]! } - public var ArchivedChats_IntroTitle2: String { return self._s[3697]! } - public var Notification_Exceptions_NewException: String { return self._s[3698]! } - public var TwoStepAuth_EmailTitle: String { return self._s[3699]! } - public var WatchRemote_AlertText: String { return self._s[3700]! } - public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3701]!, self._r[3701]!, [_1, _2]) + public var Profile_MessageLifetimeForever: String { return self._s[3722]! } + public var SharedMedia_EmptyTitle: String { return self._s[3724]! } + public var Channel_Edit_PrivatePublicLinkAlert: String { return self._s[3726]! } + public var Username_Help: String { return self._s[3727]! } + public var DialogList_LanguageTooltip: String { return self._s[3729]! } + public var Map_LoadError: String { return self._s[3730]! } + public var Login_PhoneNumberAlreadyAuthorized: String { return self._s[3731]! } + public var Channel_AdminLog_AddMembers: String { return self._s[3732]! } + public var ArchivedChats_IntroTitle2: String { return self._s[3733]! } + public var Notification_Exceptions_NewException: String { return self._s[3734]! } + public var TwoStepAuth_EmailTitle: String { return self._s[3735]! } + public var WatchRemote_AlertText: String { return self._s[3736]! } + public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3737]!, self._r[3737]!, [_1, _2, _3]) } - public var ChatSettings_ConnectionType_Title: String { return self._s[3705]! } + public var ChatSettings_ConnectionType_Title: String { return self._s[3741]! } public func Settings_CheckPhoneNumberTitle(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3706]!, self._r[3706]!, [_0]) + return formatWithArgumentRanges(self._s[3742]!, self._r[3742]!, [_0]) } - public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3707]! } - public var Passport_Address_CountryPlaceholder: String { return self._s[3708]! } + public var SettingsSearch_Synonyms_Calls_CallTab: String { return self._s[3743]! } + public var Passport_Address_CountryPlaceholder: String { return self._s[3744]! } public func DialogList_AwaitingEncryption(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3709]!, self._r[3709]!, [_0]) - } - public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3710]!, self._r[3710]!, [_1, _2, _3]) - } - public var Group_AdminLog_EmptyText: String { return self._s[3711]! } - public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3712]! } - public var Conversation_PrivateChannelTooltip: String { return self._s[3714]! } - public var Wallet_Created_ExportErrorText: String { return self._s[3715]! } - public var ChatList_UndoArchiveText1: String { return self._s[3716]! } - public var AccessDenied_VideoMicrophone: String { return self._s[3717]! } - public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3718]! } - public var Cache_ClearNone: String { return self._s[3719]! } - public var SocksProxySetup_FailedToConnect: String { return self._s[3720]! } - public var Permissions_NotificationsTitle_v0: String { return self._s[3721]! } - public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3722]!, self._r[3722]!, [_0]) - } - public var Passport_Identity_Country: String { return self._s[3723]! } - public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3724]!, self._r[3724]!, [_0]) - } - public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3725]!, self._r[3725]!, [_0]) - } - public var Exceptions_AddToExceptions: String { return self._s[3726]! } - public var AccessDenied_Settings: String { return self._s[3727]! } - public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3728]! } - public var Month_ShortMay: String { return self._s[3729]! } - public var Compose_NewGroup: String { return self._s[3731]! } - public var Group_Setup_TypePrivate: String { return self._s[3733]! } - public var Login_PadPhoneHelpTitle: String { return self._s[3735]! } - public var Appearance_ThemeDayClassic: String { return self._s[3736]! } - public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3737]! } - public var AutoDownloadSettings_OffForAll: String { return self._s[3738]! } - public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3739]! } - public var Conversation_typing: String { return self._s[3741]! } - public var Undo_ScheduledMessagesCleared: String { return self._s[3742]! } - public var Paint_Masks: String { return self._s[3743]! } - public var Contacts_DeselectAll: String { return self._s[3744]! } - public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3745]!, self._r[3745]!, [_0]) } - public var Username_InvalidTaken: String { return self._s[3746]! } - public var Call_StatusNoAnswer: String { return self._s[3747]! } - public var TwoStepAuth_EmailAddSuccess: String { return self._s[3748]! } - public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3749]! } - public var Passport_Identity_Selfie: String { return self._s[3750]! } - public var Login_InfoLastNamePlaceholder: String { return self._s[3751]! } - public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3752]! } - public var Conversation_ClearSecretHistory: String { return self._s[3753]! } - public var PeopleNearby_Description: String { return self._s[3755]! } - public var NetworkUsageSettings_Title: String { return self._s[3756]! } - public var Your_cards_security_code_is_invalid: String { return self._s[3758]! } - public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { + public func Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3746]!, self._r[3746]!, [_1, _2, _3]) + } + public var Group_AdminLog_EmptyText: String { return self._s[3747]! } + public var SettingsSearch_Synonyms_Appearance_Title: String { return self._s[3748]! } + public var Conversation_PrivateChannelTooltip: String { return self._s[3750]! } + public var Wallet_Created_ExportErrorText: String { return self._s[3751]! } + public var ChatList_UndoArchiveText1: String { return self._s[3752]! } + public var AccessDenied_VideoMicrophone: String { return self._s[3753]! } + public var Conversation_ContextMenuStickerPackAdd: String { return self._s[3754]! } + public var Cache_ClearNone: String { return self._s[3755]! } + public var SocksProxySetup_FailedToConnect: String { return self._s[3756]! } + public var Permissions_NotificationsTitle_v0: String { return self._s[3757]! } + public func Channel_AdminLog_MessageEdited(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3758]!, self._r[3758]!, [_0]) + } + public var Passport_Identity_Country: String { return self._s[3759]! } + public func ChatSettings_AutoDownloadSettings_TypeFile(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3760]!, self._r[3760]!, [_0]) } + public func Notification_CreatedChat(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3761]!, self._r[3761]!, [_0]) + } + public var Exceptions_AddToExceptions: String { return self._s[3762]! } + public var AccessDenied_Settings: String { return self._s[3763]! } + public var Passport_Address_TypeUtilityBillUploadScan: String { return self._s[3764]! } + public var Month_ShortMay: String { return self._s[3765]! } + public var Compose_NewGroup: String { return self._s[3767]! } + public var Group_Setup_TypePrivate: String { return self._s[3769]! } + public var Login_PadPhoneHelpTitle: String { return self._s[3771]! } + public var Appearance_ThemeDayClassic: String { return self._s[3772]! } + public var Channel_AdminLog_MessagePreviousCaption: String { return self._s[3773]! } + public var AutoDownloadSettings_OffForAll: String { return self._s[3774]! } + public var Privacy_GroupsAndChannels_WhoCanAddMe: String { return self._s[3775]! } + public var Conversation_typing: String { return self._s[3777]! } + public var Undo_ScheduledMessagesCleared: String { return self._s[3778]! } + public var Paint_Masks: String { return self._s[3779]! } + public var Contacts_DeselectAll: String { return self._s[3780]! } + public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3781]!, self._r[3781]!, [_0]) + } + public var Username_InvalidTaken: String { return self._s[3782]! } + public var Call_StatusNoAnswer: String { return self._s[3783]! } + public var TwoStepAuth_EmailAddSuccess: String { return self._s[3784]! } + public var SettingsSearch_Synonyms_Privacy_BlockedUsers: String { return self._s[3785]! } + public var Passport_Identity_Selfie: String { return self._s[3786]! } + public var Login_InfoLastNamePlaceholder: String { return self._s[3787]! } + public var Privacy_SecretChatsLinkPreviewsHelp: String { return self._s[3788]! } + public var Conversation_ClearSecretHistory: String { return self._s[3789]! } + public var PeopleNearby_Description: String { return self._s[3791]! } + public var NetworkUsageSettings_Title: String { return self._s[3792]! } + public var Your_cards_security_code_is_invalid: String { return self._s[3794]! } + public func Notification_LeftChannel(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3796]!, self._r[3796]!, [_0]) + } public func Call_CallInProgressMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3761]!, self._r[3761]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3797]!, self._r[3797]!, [_1, _2]) } - public var SaveIncomingPhotosSettings_From: String { return self._s[3763]! } - public var VoiceOver_Navigation_Search: String { return self._s[3764]! } - public var Map_LiveLocationTitle: String { return self._s[3765]! } - public var Login_InfoAvatarAdd: String { return self._s[3766]! } - public var Passport_Identity_FilesView: String { return self._s[3767]! } - public var UserInfo_GenericPhoneLabel: String { return self._s[3768]! } - public var Privacy_Calls_NeverAllow: String { return self._s[3769]! } - public var VoiceOver_Chat_File: String { return self._s[3770]! } - public var Wallet_Settings_DeleteWalletInfo: String { return self._s[3771]! } + public var SaveIncomingPhotosSettings_From: String { return self._s[3799]! } + public var VoiceOver_Navigation_Search: String { return self._s[3800]! } + public var Map_LiveLocationTitle: String { return self._s[3801]! } + public var Login_InfoAvatarAdd: String { return self._s[3802]! } + public var Passport_Identity_FilesView: String { return self._s[3803]! } + public var UserInfo_GenericPhoneLabel: String { return self._s[3804]! } + public var Privacy_Calls_NeverAllow: String { return self._s[3805]! } + public var VoiceOver_Chat_File: String { return self._s[3806]! } + public var Wallet_Settings_DeleteWalletInfo: String { return self._s[3807]! } public func Contacts_AddPhoneNumber(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3772]!, self._r[3772]!, [_0]) - } - public var ContactInfo_PhoneNumberHidden: String { return self._s[3773]! } - public var TwoStepAuth_ConfirmationText: String { return self._s[3774]! } - public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[3775]! } - public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3776]!, self._r[3776]!, [_1, _2, _3]) - } - public var Channel_AdminLogFilter_AdminsAll: String { return self._s[3777]! } - public var Wallet_Intro_CreateErrorText: String { return self._s[3778]! } - public var Tour_Title2: String { return self._s[3779]! } - public var Wallet_Sent_ViewWallet: String { return self._s[3780]! } - public var Conversation_FileOpenIn: String { return self._s[3781]! } - public var Checkout_ErrorPrecheckoutFailed: String { return self._s[3782]! } - public var Wallet_Send_ErrorInvalidAddress: String { return self._s[3783]! } - public var Wallpaper_Set: String { return self._s[3784]! } - public var Passport_Identity_Translations: String { return self._s[3786]! } - public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3787]!, self._r[3787]!, [_0]) - } - public var Channel_LeaveChannel: String { return self._s[3788]! } - public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3789]!, self._r[3789]!, [_1]) - } - public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[3791]! } - public var PhotoEditor_HighlightsTint: String { return self._s[3792]! } - public var Passport_Email_Delete: String { return self._s[3793]! } - public var Conversation_Mute: String { return self._s[3795]! } - public var Channel_AddBotAsAdmin: String { return self._s[3796]! } - public var Channel_AdminLog_CanSendMessages: String { return self._s[3798]! } - public var Channel_Management_LabelOwner: String { return self._s[3800]! } - public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3801]!, self._r[3801]!, [_1, _2]) - } - public var Calls_CallTabDescription: String { return self._s[3802]! } - public var Passport_Identity_NativeNameHelp: String { return self._s[3803]! } - public var Common_No: String { return self._s[3804]! } - public var Weekday_Sunday: String { return self._s[3805]! } - public var Notification_Reply: String { return self._s[3806]! } - public var Conversation_ViewMessage: String { return self._s[3807]! } - public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3808]!, self._r[3808]!, [_0]) } + public var ContactInfo_PhoneNumberHidden: String { return self._s[3809]! } + public var TwoStepAuth_ConfirmationText: String { return self._s[3810]! } + public var ChatSettings_AutomaticVideoMessageDownload: String { return self._s[3811]! } + public func PUSH_CHAT_MESSAGE_VIDEOS(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3812]!, self._r[3812]!, [_1, _2, _3]) + } + public var Channel_AdminLogFilter_AdminsAll: String { return self._s[3813]! } + public var Wallet_Intro_CreateErrorText: String { return self._s[3814]! } + public var Tour_Title2: String { return self._s[3815]! } + public var Wallet_Sent_ViewWallet: String { return self._s[3816]! } + public var Conversation_FileOpenIn: String { return self._s[3817]! } + public var Checkout_ErrorPrecheckoutFailed: String { return self._s[3818]! } + public var Wallet_Send_ErrorInvalidAddress: String { return self._s[3819]! } + public var Wallpaper_Set: String { return self._s[3820]! } + public var Passport_Identity_Translations: String { return self._s[3822]! } + public func Channel_AdminLog_MessageChangedChannelAbout(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3823]!, self._r[3823]!, [_0]) + } + public var Channel_LeaveChannel: String { return self._s[3824]! } + public func PINNED_INVOICE(_ _1: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3825]!, self._r[3825]!, [_1]) + } + public var SettingsSearch_Synonyms_Proxy_AddProxy: String { return self._s[3827]! } + public var PhotoEditor_HighlightsTint: String { return self._s[3828]! } + public var Passport_Email_Delete: String { return self._s[3829]! } + public var Conversation_Mute: String { return self._s[3831]! } + public var Channel_AddBotAsAdmin: String { return self._s[3832]! } + public var Channel_AdminLog_CanSendMessages: String { return self._s[3834]! } + public var Channel_Management_LabelOwner: String { return self._s[3836]! } + public func Notification_PassportValuesSentMessage(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3837]!, self._r[3837]!, [_1, _2]) + } + public var Calls_CallTabDescription: String { return self._s[3838]! } + public var Passport_Identity_NativeNameHelp: String { return self._s[3839]! } + public var Common_No: String { return self._s[3840]! } + public var Weekday_Sunday: String { return self._s[3841]! } + public var Notification_Reply: String { return self._s[3842]! } + public var Conversation_ViewMessage: String { return self._s[3843]! } + public func Checkout_SavePasswordTimeoutAndFaceId(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3844]!, self._r[3844]!, [_0]) + } public func Map_LiveLocationPrivateDescription(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3809]!, self._r[3809]!, [_0]) - } - public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3810]!, self._r[3810]!, [_1, _2, _3]) - } - public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[3811]! } - public var Wallet_Send_Title: String { return self._s[3812]! } - public var Message_PinnedDocumentMessage: String { return self._s[3813]! } - public var Wallet_Info_RefreshErrorText: String { return self._s[3814]! } - public var DialogList_TabTitle: String { return self._s[3816]! } - public var ChatSettings_AutoPlayTitle: String { return self._s[3817]! } - public var Passport_FieldEmail: String { return self._s[3818]! } - public var Conversation_UnpinMessageAlert: String { return self._s[3819]! } - public var Passport_Address_TypeBankStatement: String { return self._s[3820]! } - public var Wallet_SecureStorageReset_Title: String { return self._s[3821]! } - public var Passport_Identity_ExpiryDate: String { return self._s[3822]! } - public var Privacy_Calls_P2P: String { return self._s[3823]! } - public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3825]!, self._r[3825]!, [_0]) - } - public var SocksProxySetup_UseForCallsHelp: String { return self._s[3826]! } - public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3827]!, self._r[3827]!, [_1, _2]) - } - public var Stickers_ClearRecent: String { return self._s[3828]! } - public var EnterPasscode_ChangeTitle: String { return self._s[3829]! } - public var Passport_InfoText: String { return self._s[3830]! } - public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[3831]! } - public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3832]!, self._r[3832]!, [_0]) - } - public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3833]!, self._r[3833]!, [_1, _2, _3]) - } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[3834]! } - public var ScheduledMessages_PollUnavailable: String { return self._s[3835]! } - public var VoiceOver_Navigation_Compose: String { return self._s[3836]! } - public var Passport_Identity_EditDriversLicense: String { return self._s[3837]! } - public var Conversation_TapAndHoldToRecord: String { return self._s[3839]! } - public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[3840]! } - public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3841]!, self._r[3841]!, [_1, _2]) - } - public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[3843]! } - public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[3845]!, self._r[3845]!, [_0]) } - public var DialogList_Unread: String { return self._s[3846]! } + public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3846]!, self._r[3846]!, [_1, _2, _3]) + } + public var SettingsSearch_Synonyms_EditProfile_AddAccount: String { return self._s[3847]! } + public var Wallet_Send_Title: String { return self._s[3848]! } + public var Message_PinnedDocumentMessage: String { return self._s[3849]! } + public var Wallet_Info_RefreshErrorText: String { return self._s[3850]! } + public var DialogList_TabTitle: String { return self._s[3852]! } + public var ChatSettings_AutoPlayTitle: String { return self._s[3853]! } + public var Passport_FieldEmail: String { return self._s[3854]! } + public var Conversation_UnpinMessageAlert: String { return self._s[3855]! } + public var Passport_Address_TypeBankStatement: String { return self._s[3856]! } + public var Wallet_SecureStorageReset_Title: String { return self._s[3857]! } + public var Passport_Identity_ExpiryDate: String { return self._s[3858]! } + public var Privacy_Calls_P2P: String { return self._s[3859]! } + public func CancelResetAccount_Success(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3861]!, self._r[3861]!, [_0]) + } + public var SocksProxySetup_UseForCallsHelp: String { return self._s[3862]! } + public func PUSH_CHAT_ALBUM(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3863]!, self._r[3863]!, [_1, _2]) + } + public var Stickers_ClearRecent: String { return self._s[3864]! } + public var EnterPasscode_ChangeTitle: String { return self._s[3865]! } + public var TwoFactorSetup_Email_Title: String { return self._s[3866]! } + public var Passport_InfoText: String { return self._s[3867]! } + public var Checkout_NewCard_SaveInfoEnableHelp: String { return self._s[3868]! } + public func Login_InvalidPhoneEmailSubject(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3869]!, self._r[3869]!, [_0]) + } + public func Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3870]!, self._r[3870]!, [_1, _2, _3]) + } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChannels: String { return self._s[3871]! } + public var ScheduledMessages_PollUnavailable: String { return self._s[3872]! } + public var VoiceOver_Navigation_Compose: String { return self._s[3873]! } + public var Passport_Identity_EditDriversLicense: String { return self._s[3874]! } + public var Conversation_TapAndHoldToRecord: String { return self._s[3876]! } + public var SettingsSearch_Synonyms_Notifications_BadgeIncludeMutedChats: String { return self._s[3877]! } + public func Notification_CallTimeFormat(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3878]!, self._r[3878]!, [_1, _2]) + } + public var Channel_EditAdmin_PermissionInviteViaLink: String { return self._s[3880]! } + public func Generic_OpenHiddenLinkAlert(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[3882]!, self._r[3882]!, [_0]) + } + public var DialogList_Unread: String { return self._s[3883]! } public func PUSH_CHAT_MESSAGE_GIF(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3847]!, self._r[3847]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3884]!, self._r[3884]!, [_1, _2]) } - public var User_DeletedAccount: String { return self._s[3848]! } - public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[3849]! } + public var User_DeletedAccount: String { return self._s[3885]! } + public var OwnershipTransfer_SetupTwoStepAuth: String { return self._s[3886]! } public func Watch_Time_ShortYesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3850]!, self._r[3850]!, [_0]) + return formatWithArgumentRanges(self._s[3887]!, self._r[3887]!, [_0]) } - public var UserInfo_NotificationsDefault: String { return self._s[3851]! } - public var SharedMedia_CategoryMedia: String { return self._s[3852]! } - public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[3853]! } - public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[3854]! } - public var Watch_ChatList_Compose: String { return self._s[3855]! } - public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[3856]! } - public var AutoDownloadSettings_Delimeter: String { return self._s[3857]! } - public var Watch_Microphone_Access: String { return self._s[3858]! } - public var Group_Setup_HistoryHeader: String { return self._s[3859]! } - public var Map_SetThisLocation: String { return self._s[3860]! } - public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[3861]! } - public var Activity_UploadingPhoto: String { return self._s[3862]! } - public var Conversation_Edit: String { return self._s[3864]! } - public var Group_ErrorSendRestrictedMedia: String { return self._s[3865]! } - public var Login_TermsOfServiceDecline: String { return self._s[3866]! } - public var Message_PinnedContactMessage: String { return self._s[3867]! } + public var UserInfo_NotificationsDefault: String { return self._s[3888]! } + public var SharedMedia_CategoryMedia: String { return self._s[3889]! } + public var SocksProxySetup_ProxyStatusUnavailable: String { return self._s[3890]! } + public var Channel_AdminLog_MessageRestrictedForever: String { return self._s[3891]! } + public var Watch_ChatList_Compose: String { return self._s[3892]! } + public var Notifications_MessageNotificationsExceptionsHelp: String { return self._s[3893]! } + public var AutoDownloadSettings_Delimeter: String { return self._s[3894]! } + public var Watch_Microphone_Access: String { return self._s[3895]! } + public var Group_Setup_HistoryHeader: String { return self._s[3896]! } + public var Map_SetThisLocation: String { return self._s[3897]! } + public var Appearance_ThemePreview_Chat_2_ReplyName: String { return self._s[3898]! } + public var Activity_UploadingPhoto: String { return self._s[3899]! } + public var Conversation_Edit: String { return self._s[3901]! } + public var Group_ErrorSendRestrictedMedia: String { return self._s[3902]! } + public var Login_TermsOfServiceDecline: String { return self._s[3903]! } + public var Message_PinnedContactMessage: String { return self._s[3904]! } public func Channel_AdminLog_MessageRestrictedNameUsername(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3868]!, self._r[3868]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3905]!, self._r[3905]!, [_1, _2]) } public func Login_PhoneBannedEmailBody(_ _1: String, _ _2: String, _ _3: String, _ _4: String, _ _5: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3869]!, self._r[3869]!, [_1, _2, _3, _4, _5]) + return formatWithArgumentRanges(self._s[3906]!, self._r[3906]!, [_1, _2, _3, _4, _5]) } - public var Appearance_LargeEmoji: String { return self._s[3870]! } - public var TwoStepAuth_AdditionalPassword: String { return self._s[3872]! } - public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[3873]! } + public var Appearance_LargeEmoji: String { return self._s[3907]! } + public var TwoStepAuth_AdditionalPassword: String { return self._s[3909]! } + public var EditTheme_Edit_Preview_IncomingReplyText: String { return self._s[3910]! } public func PUSH_CHAT_DELETE_YOU(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3874]!, self._r[3874]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3911]!, self._r[3911]!, [_1, _2]) } - public var Passport_Phone_EnterOtherNumber: String { return self._s[3875]! } - public var Message_PinnedPhotoMessage: String { return self._s[3876]! } - public var Passport_FieldPhone: String { return self._s[3877]! } - public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[3878]! } - public var ChatSettings_AutoPlayGifs: String { return self._s[3879]! } - public var InfoPlist_NSCameraUsageDescription: String { return self._s[3881]! } - public var Conversation_Call: String { return self._s[3882]! } - public var Common_TakePhoto: String { return self._s[3884]! } - public var Group_EditAdmin_RankTitle: String { return self._s[3885]! } - public var Wallet_Receive_CommentHeader: String { return self._s[3886]! } - public var Channel_NotificationLoading: String { return self._s[3887]! } + public var Passport_Phone_EnterOtherNumber: String { return self._s[3912]! } + public var Message_PinnedPhotoMessage: String { return self._s[3913]! } + public var Passport_FieldPhone: String { return self._s[3914]! } + public var TwoStepAuth_RecoveryEmailAddDescription: String { return self._s[3915]! } + public var ChatSettings_AutoPlayGifs: String { return self._s[3916]! } + public var InfoPlist_NSCameraUsageDescription: String { return self._s[3918]! } + public var Conversation_Call: String { return self._s[3919]! } + public var Common_TakePhoto: String { return self._s[3921]! } + public var Group_EditAdmin_RankTitle: String { return self._s[3922]! } + public var Wallet_Receive_CommentHeader: String { return self._s[3923]! } + public var Channel_NotificationLoading: String { return self._s[3924]! } public func Notification_Exceptions_Sound(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3888]!, self._r[3888]!, [_0]) + return formatWithArgumentRanges(self._s[3925]!, self._r[3925]!, [_0]) } public func ScheduledMessages_ScheduledDate(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3889]!, self._r[3889]!, [_0]) + return formatWithArgumentRanges(self._s[3926]!, self._r[3926]!, [_0]) } public func PUSH_CHANNEL_MESSAGE_VIDEO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3890]!, self._r[3890]!, [_1]) + return formatWithArgumentRanges(self._s[3927]!, self._r[3927]!, [_1]) } - public var Permissions_SiriTitle_v0: String { return self._s[3891]! } + public var Permissions_SiriTitle_v0: String { return self._s[3928]! } public func VoiceOver_Chat_VoiceMessageFrom(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3892]!, self._r[3892]!, [_0]) + return formatWithArgumentRanges(self._s[3929]!, self._r[3929]!, [_0]) } public func Login_ResetAccountProtected_Text(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3893]!, self._r[3893]!, [_0]) + return formatWithArgumentRanges(self._s[3930]!, self._r[3930]!, [_0]) } - public var Channel_MessagePhotoRemoved: String { return self._s[3894]! } - public var Wallet_Info_ReceiveGrams: String { return self._s[3895]! } - public var Common_edit: String { return self._s[3896]! } - public var PrivacySettings_AuthSessions: String { return self._s[3897]! } - public var Month_ShortJune: String { return self._s[3898]! } - public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[3899]! } - public var Call_ReportSend: String { return self._s[3900]! } - public var Watch_LastSeen_JustNow: String { return self._s[3901]! } - public var Notifications_MessageNotifications: String { return self._s[3902]! } - public var WallpaperSearch_ColorGreen: String { return self._s[3903]! } - public var BroadcastListInfo_AddRecipient: String { return self._s[3905]! } - public var Group_Status: String { return self._s[3906]! } + public var Channel_MessagePhotoRemoved: String { return self._s[3931]! } + public var Wallet_Info_ReceiveGrams: String { return self._s[3932]! } + public var ClearCache_FreeSpace: String { return self._s[3933]! } + public var Common_edit: String { return self._s[3934]! } + public var PrivacySettings_AuthSessions: String { return self._s[3935]! } + public var Month_ShortJune: String { return self._s[3936]! } + public var PrivacyLastSeenSettings_AlwaysShareWith_Placeholder: String { return self._s[3937]! } + public var Call_ReportSend: String { return self._s[3938]! } + public var Watch_LastSeen_JustNow: String { return self._s[3939]! } + public var Notifications_MessageNotifications: String { return self._s[3940]! } + public var WallpaperSearch_ColorGreen: String { return self._s[3941]! } + public var BroadcastListInfo_AddRecipient: String { return self._s[3943]! } + public var Group_Status: String { return self._s[3944]! } public func AutoNightTheme_LocationHelp(_ _0: String, _ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3907]!, self._r[3907]!, [_0, _1]) + return formatWithArgumentRanges(self._s[3945]!, self._r[3945]!, [_0, _1]) } - public var TextFormat_AddLinkTitle: String { return self._s[3908]! } - public var ShareMenu_ShareTo: String { return self._s[3909]! } - public var Conversation_Moderate_Ban: String { return self._s[3910]! } + public var TextFormat_AddLinkTitle: String { return self._s[3946]! } + public var ShareMenu_ShareTo: String { return self._s[3947]! } + public var Conversation_Moderate_Ban: String { return self._s[3948]! } public func Conversation_DeleteMessagesFor(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3911]!, self._r[3911]!, [_0]) + return formatWithArgumentRanges(self._s[3949]!, self._r[3949]!, [_0]) } - public var SharedMedia_ViewInChat: String { return self._s[3912]! } - public var Map_LiveLocationFor8Hours: String { return self._s[3913]! } + public var SharedMedia_ViewInChat: String { return self._s[3950]! } + public var Map_LiveLocationFor8Hours: String { return self._s[3951]! } public func PUSH_PINNED_PHOTO(_ _1: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3914]!, self._r[3914]!, [_1]) + return formatWithArgumentRanges(self._s[3952]!, self._r[3952]!, [_1]) } public func PUSH_PINNED_POLL(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3915]!, self._r[3915]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3953]!, self._r[3953]!, [_1, _2]) } public func Map_AccurateTo(_ _0: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3917]!, self._r[3917]!, [_0]) + return formatWithArgumentRanges(self._s[3955]!, self._r[3955]!, [_0]) } - public var Map_OpenInHereMaps: String { return self._s[3918]! } - public var Appearance_ReduceMotion: String { return self._s[3919]! } + public var Map_OpenInHereMaps: String { return self._s[3956]! } + public var Appearance_ReduceMotion: String { return self._s[3957]! } public func PUSH_MESSAGE_TEXT(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[3920]!, self._r[3920]!, [_1, _2]) + return formatWithArgumentRanges(self._s[3958]!, self._r[3958]!, [_1, _2]) } - public var Channel_Setup_TypePublicHelp: String { return self._s[3921]! } - public var Passport_Identity_EditInternalPassport: String { return self._s[3922]! } - public var PhotoEditor_Skip: String { return self._s[3923]! } - public func MuteFor_Hours(_ value: Int32) -> String { + public var Channel_Setup_TypePublicHelp: String { return self._s[3959]! } + public var Passport_Identity_EditInternalPassport: String { return self._s[3960]! } + public var PhotoEditor_Skip: String { return self._s[3961]! } + public func ForwardedStickers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessagePoll_VotedCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue) + public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, _1, _2) } - public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { + public func MessageTimer_ShortSeconds(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[2 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_Weeks(_ value: Int32) -> String { + public func InviteText_ContactsCountText(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[3 * 6 + Int(form.rawValue)]!, stringValue) } - public func Passport_Scans(_ value: Int32) -> String { + public func Map_ETAMinutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[4 * 6 + Int(form.rawValue)]!, stringValue) } - public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { + public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[5 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_AddStickerCount(_ value: Int32) -> String { + public func ForwardedGifs(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[6 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { + public func UserCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[7 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, _1, _2) + public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[8 * 6 + Int(form.rawValue)]!, stringValue) } - public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { + public func SharedMedia_Link(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[9 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_SelectedMessages(_ value: Int32) -> String { + public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[10 * 6 + Int(form.rawValue)]!, stringValue) } - public func Map_ETAMinutes(_ value: Int32) -> String { + public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[11 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedFiles(_ value: Int32) -> String { + public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[12 * 6 + Int(form.rawValue)]!, stringValue) } - public func InviteText_ContactsCountText(_ value: Int32) -> String { + public func ForwardedFiles(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[13 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + public func Call_ShortSeconds(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[14 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedStickers(_ value: Int32) -> String { + public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[15 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, _1, _2) + return String(format: self._ps[16 * 6 + Int(form.rawValue)]!, _2, _1, _3) } - public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func ChatList_SelectedChats(_ value: Int32) -> String { + public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAudios(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollOptionCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Months(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) - } - public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_Exceptions(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Contacts_ImportersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) - } - public func GroupInfo_ParticipantCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedPhotos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) - } - public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[17 * 6 + Int(form.rawValue)]!, stringValue) } public func ForwardedVideoMessages(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[18 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedPolls(_ value: Int32) -> String { + public func Media_ShareItem(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[19 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_Generic(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Days(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[20 * 6 + Int(form.rawValue)]!, stringValue) } - public func Call_ShortMinutes(_ value: Int32) -> String { + public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[21 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Notification_GameScoreExtended(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[22 * 6 + Int(form.rawValue)]!, stringValue) } - public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[23 * 6 + Int(form.rawValue)]!, stringValue) } - public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { + public func MessageTimer_ShortDays(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[24 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + public func Notifications_Exceptions(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PrivacyLastSeenSettings_AddUsers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) - } - public func UserCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Call_Seconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[25 * 6 + Int(form.rawValue)]!, stringValue) } public func Notification_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[26 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[27 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[28 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MuteExpires_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[29 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[30 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func ForwardedLocations(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[31 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[32 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[33 * 6 + Int(form.rawValue)]!, stringValue) + } + public func AttachmentMenu_SendItem(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[34 * 6 + Int(form.rawValue)]!, stringValue) + } + public func GroupInfo_ParticipantCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[35 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessagePoll_VotedCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[36 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Media_ShareVideo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[37 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[38 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_UserInfo_Mute(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[39 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[40 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Map_ETAHours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[41 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Weeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[42 * 6 + Int(form.rawValue)]!, stringValue) + } + public func LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[43 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_ContactPhoneNumberCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[44 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_AddMaskCount(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[45 * 6 + Int(form.rawValue)]!, stringValue) } - public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + public func MessageTimer_Years(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[46 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + public func MuteFor_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[47 * 6 + Int(form.rawValue)]!, stringValue) @@ -4702,319 +4741,322 @@ public final class PresentationStrings: Equatable { let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[48 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { + public func ForwardedVideos(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[49 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_File(_ value: Int32) -> String { + public func Wallpaper_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[50 * 6 + Int(form.rawValue)]!, stringValue) } - public func Watch_UserInfo_Mute(_ value: Int32) -> String { + public func ForwardedAudios(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[51 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortDays(_ value: Int32) -> String { + public func SharedMedia_File(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[52 * 6 + Int(form.rawValue)]!, stringValue) } - public func LastSeen_HoursAgo(_ value: Int32) -> String { + public func MuteExpires_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[53 * 6 + Int(form.rawValue)]!, stringValue) } - public func ForwardedVideos(_ value: Int32) -> String { + public func SharedMedia_DeleteItemsConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[54 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteFor_Days(_ value: Int32) -> String { + public func MessageTimer_Minutes(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[55 * 6 + Int(form.rawValue)]!, stringValue) } - public func SharedMedia_Link(_ value: Int32) -> String { + public func Conversation_StatusMembers(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[56 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendVideo(_ value: Int32) -> String { + public func ChatList_DeleteConfirmation(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[57 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notification_GameScoreExtended(_ value: Int32) -> String { + public func AttachmentMenu_SendGif(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[58 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + public func ForwardedPhotos(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendGif(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) - } - public func SharedMedia_Video(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Call_Minutes(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Forward_ConfirmMultipleFiles(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Seconds(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Map_ETAHours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) - } - public func AttachmentMenu_SendPhoto(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[59 * 6 + Int(form.rawValue)]!, stringValue) } public func Conversation_StatusOnline(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[60 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_RemoveStickerCount(_ value: Int32) -> String { + public func Contacts_ImportersCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[61 * 6 + Int(form.rawValue)]!, stringValue) } - public func StickerPack_RemoveMaskCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { + public func PUSH_CHANNEL_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, _0, _1) + return String(format: self._ps[62 * 6 + Int(form.rawValue)]!, _1, _2) } - public func PUSH_CHAT_MESSAGE_PHOTOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func PUSH_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Conversation_StatusMembers(_ value: Int32) -> String { + public func StickerPack_AddMaskCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[63 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func MessageTimer_ShortSeconds(_ value: Int32) -> String { + public func LiveLocationUpdated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[64 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func MuteExpires_Minutes(_ value: Int32) -> String { + public func ServiceMessage_GameScoreSelfSimple(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MessageTimer_Years(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notification_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_SharePhoto(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreExtended(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ServiceMessage_GameScoreSimple(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedLocations(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Media_ShareItem(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func Theme_UsersCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) - } - public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) - } - public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_CHAT_MESSAGES(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, _2, _1, _3) - } - public func Conversation_StatusSubscribers(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func Media_ShareVideo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) - } - public func MuteExpires_Days(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedMessages(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PUSH_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { - let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, _1, _2) - } - public func LastSeen_MinutesAgo(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedGifs(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) - } - public func QuickSend_Photos(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, stringValue) - } - public func PasscodeSettings_FailedAttempts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ForwardedContacts(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[65 * 6 + Int(form.rawValue)]!, stringValue) } public func SharedMedia_Photo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[66 * 6 + Int(form.rawValue)]!, stringValue) } - public func Invitation_Members(_ value: Int32) -> String { + public func Notifications_ExceptionMuteExpires_Hours(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[67 * 6 + Int(form.rawValue)]!, stringValue) } - public func Notification_GameScoreSelfSimple(_ value: Int32) -> String { + public func Media_SharePhoto(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) - } - public func ChatList_DeleteConfirmation(_ value: Int32) -> String { - let form = getPluralizationForm(self.lc, value) - let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[68 * 6 + Int(form.rawValue)]!, stringValue) } public func PUSH_CHAT_MESSAGE_VIDEOS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, _2, _1, _3) + return String(format: self._ps[69 * 6 + Int(form.rawValue)]!, _2, _1, _3) } - public func Call_ShortSeconds(_ value: Int32) -> String { + public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[70 * 6 + Int(form.rawValue)]!, stringValue) } - public func AttachmentMenu_SendItem(_ value: Int32) -> String { + public func ForwardedContacts(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[71 * 6 + Int(form.rawValue)]!, stringValue) } - public func MuteExpires_Hours(_ value: Int32) -> String { + public func Call_Seconds(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) - return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + return String(format: self._ps[72 * 6 + Int(form.rawValue)]!, stringValue) } - public func PUSH_CHANNEL_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + public func LastSeen_MinutesAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[73 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[74 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_LiveLocationMembersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[75 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedAuthorsOthers(_ selector: Int32, _ _0: String, _ _1: String) -> String { let form = getPluralizationForm(self.lc, selector) - return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, _1, _2) + return String(format: self._ps[76 * 6 + Int(form.rawValue)]!, _0, _1) + } + public func PUSH_MESSAGE_FWDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[77 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Theme_UsersCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[78 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGES(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[79 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func SharedMedia_Generic(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[80 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Call_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[81 * 6 + Int(form.rawValue)]!, stringValue) + } + public func VoiceOver_Chat_PollVotes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[82 * 6 + Int(form.rawValue)]!, stringValue) } public func Notifications_ExceptionMuteExpires_Minutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[83 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteFor_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[84 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ChatList_SelectedChats(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[85 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_VIDEOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[86 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func LiveLocation_MenuChatsCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[87 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Wallet_Updated_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[88 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Passport_Scans(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[89 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Months(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[90 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_FWDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[91 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func QuickSend_Photos(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[92 * 6 + Int(form.rawValue)]!, stringValue) + } + public func SharedMedia_Video(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[93 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_MESSAGE_PHOTOS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[94 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func MessageTimer_ShortMinutes(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[95 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MuteExpires_Hours(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[96 * 6 + Int(form.rawValue)]!, stringValue) + } + public func StickerPack_AddStickerCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[97 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Seconds(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[98 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_ShortWeeks(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[99 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Invitation_Members(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[100 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHANNEL_MESSAGE_ROUNDS(_ selector: Int32, _ _1: String, _ _2: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[101 * 6 + Int(form.rawValue)]!, _1, _2) + } + public func Conversation_StatusSubscribers(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[102 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Watch_LastSeen_HoursAgo(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[103 * 6 + Int(form.rawValue)]!, stringValue) + } + public func MessageTimer_Days(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[104 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[105 * 6 + Int(form.rawValue)]!, stringValue) + } + public func CreatePoll_AddMoreOptions(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[106 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Conversation_SelectedMessages(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[107 * 6 + Int(form.rawValue)]!, stringValue) + } + public func PUSH_CHAT_MESSAGE_ROUNDS(_ selector: Int32, _ _2: String, _ _1: String, _ _3: Int32) -> String { + let form = getPluralizationForm(self.lc, selector) + return String(format: self._ps[108 * 6 + Int(form.rawValue)]!, _2, _1, _3) + } + public func VoiceOver_Chat_ContactEmailCount(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[109 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Notification_GameScoreSimple(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[110 * 6 + Int(form.rawValue)]!, stringValue) + } + public func Chat_DeleteMessagesConfirmation(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[111 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ServiceMessage_GameScoreSelfExtended(_ value: Int32) -> String { + let form = getPluralizationForm(self.lc, value) + let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) + return String(format: self._ps[112 * 6 + Int(form.rawValue)]!, stringValue) + } + public func ForwardedPolls(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[113 * 6 + Int(form.rawValue)]!, stringValue) } - public func MessageTimer_ShortHours(_ value: Int32) -> String { + public func DialogList_LiveLocationChatsCount(_ value: Int32) -> String { let form = getPluralizationForm(self.lc, value) let stringValue = presentationStringsFormattedNumber(value, self.groupingSeparator) return String(format: self._ps[114 * 6 + Int(form.rawValue)]!, stringValue) diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index 521d63511f..7077f85d56 100644 Binary files a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping and b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping differ diff --git a/submodules/TonBinding/Sources/TON.h b/submodules/TonBinding/Sources/TON.h index ae8eaa5da3..08bd5c0c8d 100644 --- a/submodules/TonBinding/Sources/TON.h +++ b/submodules/TonBinding/Sources/TON.h @@ -74,6 +74,36 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface TONFees : NSObject + +@property (nonatomic, readonly) int64_t inFwdFee; +@property (nonatomic, readonly) int64_t storageFee; +@property (nonatomic, readonly) int64_t gasFee; +@property (nonatomic, readonly) int64_t fwdFee; + +- (instancetype)initWithInFwdFee:(int64_t)inFwdFee storageFee:(int64_t)storageFee gasFee:(int64_t)gasFee fwdFee:(int64_t)fwdFee; + +@end + +@interface TONSendGramsQueryFees : NSObject + +@property (nonatomic, strong, readonly) TONFees *sourceFees; +@property (nonatomic, strong, readonly) TONFees *destinationFees; + +- (instancetype)initWithSourceFees:(TONFees *)sourceFees destinationFees:(TONFees *)destinationFees; + +@end + +@interface TONPreparedSendGramsQuery : NSObject + +@property (nonatomic, readonly) int64_t queryId; +@property (nonatomic, readonly) int64_t validUntil; +@property (nonatomic, strong, readonly) NSData * _Nonnull bodyHash; + +- (instancetype)initWithQueryId:(int64_t)queryId validUntil:(int64_t)validUntil bodyHash:(NSData *)bodyHash; + +@end + @interface TONSendGramsResult : NSObject @property (nonatomic, readonly) int64_t sentUntil; @@ -92,7 +122,10 @@ NS_ASSUME_NONNULL_BEGIN - (SSignal *)createKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword; - (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey; - (SSignal *)getAccountStateWithAddress:(NSString *)accountAddress; -- (SSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId; +- (SSignal *)generateSendGramsQueryFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId; +- (SSignal *)generateFakeSendGramsQueryFromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout; +- (SSignal *)estimateSendGramsQueryFees:(TONPreparedSendGramsQuery *)preparedQuery; +- (SSignal *)commitPreparedSendGramsQuery:(TONPreparedSendGramsQuery *)preparedQuery; - (SSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword; - (SSignal *)importKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword wordList:(NSArray *)wordList; - (SSignal *)deleteKey:(TONKey *)key; diff --git a/submodules/TonBinding/Sources/TON.mm b/submodules/TonBinding/Sources/TON.mm index dd49dc88e6..e7559cca81 100644 --- a/submodules/TonBinding/Sources/TON.mm +++ b/submodules/TonBinding/Sources/TON.mm @@ -147,6 +147,48 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj @end +@implementation TONFees + +- (instancetype)initWithInFwdFee:(int64_t)inFwdFee storageFee:(int64_t)storageFee gasFee:(int64_t)gasFee fwdFee:(int64_t)fwdFee { + self = [super init]; + if (self != nil) { + _inFwdFee = inFwdFee; + _storageFee = storageFee; + _gasFee = gasFee; + _fwdFee = fwdFee; + } + return self; +} + +@end + +@implementation TONSendGramsQueryFees + +- (instancetype)initWithSourceFees:(TONFees *)sourceFees destinationFees:(TONFees *)destinationFees { + self = [super init]; + if (self != nil) { + _sourceFees = sourceFees; + _destinationFees = destinationFees; + } + return self; +} + +@end + +@implementation TONPreparedSendGramsQuery + +- (instancetype)initWithQueryId:(int64_t)queryId validUntil:(int64_t)validUntil bodyHash:(NSData *)bodyHash { + self = [super init]; + if (self != nil) { + _queryId = queryId; + _validUntil = validUntil; + _bodyHash = bodyHash; + } + return self; +} + +@end + @implementation TONSendGramsResult - (instancetype)initWithSentUntil:(int64_t)sentUntil bodyHash:(NSData *)bodyHash { @@ -540,7 +582,7 @@ typedef enum { }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; } -- (SSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId { +- (SSignal *)generateSendGramsQueryFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId { return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { if ([_sendGramRandomIds containsObject:@(randomId)]) { [_sendGramRandomIds addObject:@(randomId)]; @@ -570,17 +612,17 @@ typedef enum { }]; auto error = tonlib_api::move_object_as(object); [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::sendGramsResult::ID) { - auto result = tonlib_api::move_object_as(object); - TONSendGramsResult *sendResult = [[TONSendGramsResult alloc] initWithSentUntil:result->sent_until_ bodyHash:makeData(result->body_hash_)]; - [subscriber putNext:sendResult]; + } else if (object->get_id() == tonlib_api::query_info::ID) { + auto result = tonlib_api::move_object_as(object); + TONPreparedSendGramsQuery *preparedQuery = [[TONPreparedSendGramsQuery alloc] initWithQueryId:result->id_ validUntil:result->valid_until_ bodyHash:makeData(result->body_hash_)]; + [subscriber putNext:preparedQuery]; [subscriber putCompletion]; } else { [subscriber putCompletion]; } }]; - auto query = make_object( + auto query = make_object( make_object( make_object( makeString(publicKeyData), @@ -602,6 +644,101 @@ typedef enum { }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; } +- (SSignal *)generateFakeSendGramsQueryFromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout { + return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { + + uint64_t requestId = _nextRequestId; + _nextRequestId += 1; + + __weak TON *weakSelf = self; + SQueue *queue = _queue; + _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { + if (object->get_id() == tonlib_api::error::ID) { + auto error = tonlib_api::move_object_as(object); + [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; + } else if (object->get_id() == tonlib_api::query_info::ID) { + auto result = tonlib_api::move_object_as(object); + TONPreparedSendGramsQuery *preparedQuery = [[TONPreparedSendGramsQuery alloc] initWithQueryId:result->id_ validUntil:result->valid_until_ bodyHash:makeData(result->body_hash_)]; + [subscriber putNext:preparedQuery]; + [subscriber putCompletion]; + } else { + [subscriber putCompletion]; + } + }]; + + auto query = make_object( + make_object(), + make_object(fromAddress.UTF8String), + make_object(address.UTF8String), + amount, + timeout, + forceIfDestinationNotInitialized, + makeString(textMessage) + ); + _client->send({ requestId, std::move(query) }); + + return [[SBlockDisposable alloc] initWithBlock:^{ + }]; + }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; +} + +- (SSignal *)estimateSendGramsQueryFees:(TONPreparedSendGramsQuery *)preparedQuery { + return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { + uint64_t requestId = _nextRequestId; + _nextRequestId += 1; + + _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { + if (object->get_id() == tonlib_api::error::ID) { + auto error = tonlib_api::move_object_as(object); + [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; + } else if (object->get_id() == tonlib_api::query_fees::ID) { + auto result = tonlib_api::move_object_as(object); + TONFees *sourceFees = [[TONFees alloc] initWithInFwdFee:result->source_fees_->in_fwd_fee_ storageFee:result->source_fees_->storage_fee_ gasFee:result->source_fees_->gas_fee_ fwdFee:result->source_fees_->fwd_fee_]; + TONFees *destinationFees = [[TONFees alloc] initWithInFwdFee:result->destination_fees_->in_fwd_fee_ storageFee:result->destination_fees_->storage_fee_ gasFee:result->destination_fees_->gas_fee_ fwdFee:result->destination_fees_->fwd_fee_]; + [subscriber putNext:[[TONSendGramsQueryFees alloc] initWithSourceFees:sourceFees destinationFees:destinationFees]]; + [subscriber putCompletion]; + } else { + assert(false); + } + }]; + + auto query = make_object( + preparedQuery.queryId, + true + ); + _client->send({ requestId, std::move(query) }); + + return [[SBlockDisposable alloc] initWithBlock:^{ + }]; + }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; +} + +- (SSignal *)commitPreparedSendGramsQuery:(TONPreparedSendGramsQuery *)preparedQuery { + return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { + uint64_t requestId = _nextRequestId; + _nextRequestId += 1; + + _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { + if (object->get_id() == tonlib_api::error::ID) { + auto error = tonlib_api::move_object_as(object); + [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; + } else if (object->get_id() == tonlib_api::ok::ID) { + [subscriber putCompletion]; + } else { + assert(false); + } + }]; + + auto query = make_object( + preparedQuery.queryId + ); + _client->send({ requestId, std::move(query) }); + + return [[SBlockDisposable alloc] initWithBlock:^{ + }]; + }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; +} + - (SSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword { return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding]; diff --git a/submodules/WalletCore/Sources/WalletCore.swift b/submodules/WalletCore/Sources/WalletCore.swift index ab26eba8dc..79cf219086 100644 --- a/submodules/WalletCore/Sources/WalletCore.swift +++ b/submodules/WalletCore/Sources/WalletCore.swift @@ -350,19 +350,19 @@ public final class TonInstance { } } - fileprivate func sendGramsFromWallet(decryptedSecret: Data, localPassword: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: Data, forceIfDestinationNotInitialized: Bool, timeout: Int32, randomId: Int64) -> Signal { + fileprivate func prepareSendGramsFromWalletQuery(decryptedSecret: Data, localPassword: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: Data, forceIfDestinationNotInitialized: Bool, timeout: Int32, randomId: Int64) -> Signal { let key = TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret) return Signal { subscriber in let disposable = MetaDisposable() self.impl.with { impl in impl.withInstance { ton in - let cancel = ton.sendGrams(from: key, localPassword: localPassword, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId).start(next: { result in - guard let result = result as? TONSendGramsResult else { + let cancel = ton.generateSendGramsQuery(from: key, localPassword: localPassword, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId).start(next: { result in + guard let result = result as? TONPreparedSendGramsQuery else { subscriber.putError(.generic) return } - subscriber.putNext(PendingWalletTransaction(timestamp: Int64(Date().timeIntervalSince1970), validUntilTimestamp: result.sentUntil, bodyHash: result.bodyHash, address: toAddress, value: amount, comment: textMessage)) + subscriber.putNext(result) subscriber.putCompletion() }, error: { error in if let error = error as? TONError { @@ -395,6 +395,131 @@ public final class TonInstance { } } + fileprivate func prepareFakeSendGramsFromWalletQuery(walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: Data, timeout: Int32) -> Signal { + return Signal { subscriber in + let disposable = MetaDisposable() + + self.impl.with { impl in + impl.withInstance { ton in + let cancel = ton.generateFakeSendGramsQuery(fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: true, timeout: timeout).start(next: { result in + guard let result = result as? TONPreparedSendGramsQuery else { + subscriber.putError(.generic) + return + } + subscriber.putNext(result) + subscriber.putCompletion() + }, error: { error in + if let error = error as? TONError { + if error.text.hasPrefix("INVALID_ACCOUNT_ADDRESS") { + subscriber.putError(.invalidAddress) + } else if error.text.hasPrefix("DANGEROUS_TRANSACTION") { + subscriber.putError(.destinationIsNotInitialized) + } else if error.text.hasPrefix("MESSAGE_TOO_LONG") { + subscriber.putError(.messageTooLong) + } else if error.text.hasPrefix("NOT_ENOUGH_FUNDS") { + subscriber.putError(.notEnoughFunds) + } else if error.text.hasPrefix("LITE_SERVER_") { + subscriber.putError(.network) + } else { + subscriber.putError(.generic) + } + } else { + subscriber.putError(.generic) + } + }, completed: { + subscriber.putCompletion() + }) + disposable.set(ActionDisposable { + cancel?.dispose() + }) + } + } + + return disposable + } + } + + fileprivate func estimateSendGramsQueryFees(preparedQuery: TONPreparedSendGramsQuery) -> Signal { + return Signal { subscriber in + let disposable = MetaDisposable() + + self.impl.with { impl in + impl.withInstance { ton in + let cancel = ton.estimateSendGramsQueryFees(preparedQuery).start(next: { result in + guard let result = result as? TONSendGramsQueryFees else { + subscriber.putError(.generic) + return + } + subscriber.putNext(result) + subscriber.putCompletion() + }, error: { error in + if let error = error as? TONError { + if error.text.hasPrefix("INVALID_ACCOUNT_ADDRESS") { + subscriber.putError(.invalidAddress) + } else if error.text.hasPrefix("DANGEROUS_TRANSACTION") { + subscriber.putError(.destinationIsNotInitialized) + } else if error.text.hasPrefix("MESSAGE_TOO_LONG") { + subscriber.putError(.messageTooLong) + } else if error.text.hasPrefix("NOT_ENOUGH_FUNDS") { + subscriber.putError(.notEnoughFunds) + } else if error.text.hasPrefix("LITE_SERVER_") { + subscriber.putError(.network) + } else { + subscriber.putError(.generic) + } + } else { + subscriber.putError(.generic) + } + }, completed: nil) + disposable.set(ActionDisposable { + cancel?.dispose() + }) + } + } + + return disposable + } + } + + fileprivate func commitPreparedSendGramsQuery(_ preparedQuery: TONPreparedSendGramsQuery) -> Signal { + return Signal { subscriber in + let disposable = MetaDisposable() + + self.impl.with { impl in + impl.withInstance { ton in + let cancel = ton.commit(preparedQuery).start(next: { result in + preconditionFailure() + }, error: { error in + if let error = error as? TONError { + if error.text.hasPrefix("INVALID_ACCOUNT_ADDRESS") { + subscriber.putError(.invalidAddress) + } else if error.text.hasPrefix("DANGEROUS_TRANSACTION") { + subscriber.putError(.destinationIsNotInitialized) + } else if error.text.hasPrefix("MESSAGE_TOO_LONG") { + subscriber.putError(.messageTooLong) + } else if error.text.hasPrefix("NOT_ENOUGH_FUNDS") { + subscriber.putError(.notEnoughFunds) + } else if error.text.hasPrefix("LITE_SERVER_") { + subscriber.putError(.network) + } else { + subscriber.putError(.generic) + } + } else { + subscriber.putError(.generic) + } + }, completed: { + subscriber.putCompletion() + }) + disposable.set(ActionDisposable { + cancel?.dispose() + }) + } + } + + return disposable + } + } + fileprivate func walletRestoreWords(publicKey: WalletPublicKey, decryptedSecret: Data, localPassword: Data) -> Signal<[String], WalletRestoreWordsError> { return Signal { subscriber in let disposable = MetaDisposable() @@ -769,28 +894,63 @@ public enum SendGramsFromWalletError { case network } +public struct EstimatedSendGramsFees { + public let inFwdFee: Int64 + public let storageFee: Int64 + public let gasFee: Int64 + public let fwdFee: Int64 +} + +public func verifySendGramsRequestAndEstimateFees(tonInstance: TonInstance, walletInfo: WalletInfo, toAddress: String, amount: Int64, textMessage: Data, timeout: Int32) -> Signal { + return walletAddress(publicKey: walletInfo.publicKey, tonInstance: tonInstance) + |> castError(SendGramsFromWalletError.self) + |> mapToSignal { fromAddress -> Signal in + return tonInstance.prepareFakeSendGramsFromWalletQuery(walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, timeout: timeout) + |> mapToSignal { preparedQuery -> Signal in + return tonInstance.estimateSendGramsQueryFees(preparedQuery: preparedQuery) + |> map { result -> EstimatedSendGramsFees in + return EstimatedSendGramsFees(inFwdFee: result.sourceFees.inFwdFee, storageFee: result.sourceFees.storageFee, gasFee: result.sourceFees.gasFee, fwdFee: result.sourceFees.fwdFee) + } + } + } +} + public func sendGramsFromWallet(storage: WalletStorageInterface, tonInstance: TonInstance, walletInfo: WalletInfo, decryptedSecret: Data, localPassword: Data, toAddress: String, amount: Int64, textMessage: Data, forceIfDestinationNotInitialized: Bool, timeout: Int32, randomId: Int64) -> Signal { return walletAddress(publicKey: walletInfo.publicKey, tonInstance: tonInstance) |> castError(SendGramsFromWalletError.self) |> mapToSignal { fromAddress -> Signal in - return tonInstance.sendGramsFromWallet(decryptedSecret: decryptedSecret, localPassword: localPassword, walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId) - |> mapToSignal { result -> Signal in - return storage.updateWalletRecords { records in - var records = records - for i in 0 ..< records.count { - if records[i].info.publicKey == walletInfo.publicKey { - if var state = records[i].state { - state.pendingTransactions.insert(result, at: 0) - records[i].state = state + return tonInstance.prepareSendGramsFromWalletQuery(decryptedSecret: decryptedSecret, localPassword: localPassword, walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId) + |> mapToSignal { preparedQuery -> Signal in + return tonInstance.commitPreparedSendGramsQuery(preparedQuery) + |> retryTonRequest(isNetworkError: { error in + if case .network = error { + return true + } else { + return false + } + }) + |> mapToSignal { _ -> Signal in + return .complete() + } + |> then(.single(PendingWalletTransaction(timestamp: Int64(Date().timeIntervalSince1970), validUntilTimestamp: preparedQuery.validUntil, bodyHash: preparedQuery.bodyHash, address: toAddress, value: amount, comment: textMessage))) + |> mapToSignal { result in + return storage.updateWalletRecords { records in + var records = records + for i in 0 ..< records.count { + if records[i].info.publicKey == walletInfo.publicKey { + if var state = records[i].state { + state.pendingTransactions.insert(result, at: 0) + records[i].state = state + } } } + return records } - return records + |> map { _ -> PendingWalletTransaction in + return result + } + |> castError(SendGramsFromWalletError.self) } - |> map { _ -> PendingWalletTransaction in - return result - } - |> castError(SendGramsFromWalletError.self) } } } diff --git a/submodules/WalletUI/Sources/WalletSendScreen.swift b/submodules/WalletUI/Sources/WalletSendScreen.swift index b46dc0152a..42076c9eac 100644 --- a/submodules/WalletUI/Sources/WalletSendScreen.swift +++ b/submodules/WalletUI/Sources/WalletSendScreen.swift @@ -347,6 +347,9 @@ public func walletSendScreen(context: WalletContext, randomId: Int64, walletInfo let presentationData = context.presentationData let state = stateValue.with { $0 } let amount = amountValue(state.amount) + let commentData = state.comment.data(using: .utf8) + let formattedAddress = String(state.address[state.address.startIndex.. Void)? - let theme = context.presentationData.theme - let controller = richTextAlertController(alertContext: AlertControllerContext(theme: theme.alert, themeSignal: .single(theme.alert)), title: title, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Wallet_Navigation_Cancel, action: { - dismissAlertImpl?(true) - }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Wallet_Send_ConfirmationConfirm, action: { - dismissAlertImpl?(false) - dismissInputImpl?() + let _ = (verifySendGramsRequestAndEstimateFees(tonInstance: context.tonInstance, walletInfo: walletInfo, toAddress: destinationAddress, amount: amount, textMessage: commentData ?? Data(), timeout: 0) + |> deliverOnMainQueue).start(next: { [weak controller] fees in + controller?.dismiss() let presentationData = context.presentationData - let progressSignal = Signal { subscriber in - let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) - presentControllerImpl?(controller, nil) - return ActionDisposable { [weak controller] in - Queue.mainQueue().async() { - controller?.dismiss() + + let title = NSAttributedString(string: presentationData.strings.Wallet_Send_Confirmation, font: Font.semibold(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + + let feeAmount = fees.inFwdFee + fees.storageFee + fees.gasFee + fees.fwdFee + + let (text, ranges) = presentationData.strings.Wallet_Send_ConfirmationText(formatBalanceText(amount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator), formattedAddress, "\(formatBalanceText(feeAmount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))") + let bodyAttributes = MarkdownAttributeSet(font: Font.regular(13.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + let boldAttributes = MarkdownAttributeSet(font: Font.semibold(13.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + let attributedText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: bodyAttributes, bold: boldAttributes, link: bodyAttributes, linkAttribute: { _ in return nil }), textAlignment: .center)) + for (index, range) in ranges { + if index == 1 { + attributedText.addAttribute(.font, value: Font.monospace(14.0), range: range) + } + } + + var dismissAlertImpl: ((Bool) -> Void)? + let theme = context.presentationData.theme + let controller = richTextAlertController(alertContext: AlertControllerContext(theme: theme.alert, themeSignal: .single(theme.alert)), title: title, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Wallet_Navigation_Cancel, action: { + dismissAlertImpl?(true) + }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Wallet_Send_ConfirmationConfirm, action: { + dismissAlertImpl?(false) + dismissInputImpl?() + + let presentationData = context.presentationData + let progressSignal = Signal { subscriber in + let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) + presentControllerImpl?(controller, nil) + return ActionDisposable { [weak controller] in + Queue.mainQueue().async() { + controller?.dismiss() + } } } - } - |> runOn(Queue.mainQueue()) - |> delay(0.15, queue: Queue.mainQueue()) - let progressDisposable = progressSignal.start() - - var serverSaltSignal = serverSaltValue.get() - |> take(1) - - serverSaltSignal = serverSaltSignal - |> afterDisposed { - Queue.mainQueue().async { - progressDisposable.dispose() + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + var serverSaltSignal = serverSaltValue.get() + |> take(1) + + serverSaltSignal = serverSaltSignal + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() + } } - } - - let _ = (serverSaltSignal - |> deliverOnMainQueue).start(next: { serverSalt in - if let serverSalt = serverSalt { - if let commentData = state.comment.data(using: .utf8) { - pushImpl?(WalletSplashScreen(context: context, mode: .sending(walletInfo, state.address, amount, commentData, randomId, serverSalt), walletCreatedPreloadState: nil)) + + let _ = (serverSaltSignal + |> deliverOnMainQueue).start(next: { serverSalt in + if let serverSalt = serverSalt { + if let commentData = state.comment.data(using: .utf8) { + pushImpl?(WalletSplashScreen(context: context, mode: .sending(walletInfo, state.address, amount, commentData, randomId, serverSalt), walletCreatedPreloadState: nil)) + } } + }) + })], allowInputInset: false, dismissAutomatically: false) + presentInGlobalOverlayImpl?(controller, nil) + + dismissAlertImpl = { [weak controller] animated in + if animated { + controller?.dismissAnimated() + } else { + controller?.dismiss() } - }) - })], allowInputInset: false, dismissAutomatically: false) - presentInGlobalOverlayImpl?(controller, nil) - - dismissAlertImpl = { [weak controller] animated in - if animated { - controller?.dismissAnimated() - } else { - controller?.dismiss() } - } + }, error: { [weak controller] error in + controller?.dismiss() + + let presentationData = context.presentationData + + var title: String? + let text: String + switch error { + case .generic: + text = presentationData.strings.Wallet_UnknownError + case .network: + title = presentationData.strings.Wallet_Send_NetworkErrorTitle + text = presentationData.strings.Wallet_Send_NetworkErrorText + case .notEnoughFunds: + title = presentationData.strings.Wallet_Send_ErrorNotEnoughFundsTitle + text = presentationData.strings.Wallet_Send_ErrorNotEnoughFundsText + case .messageTooLong: + text = presentationData.strings.Wallet_UnknownError + case .invalidAddress: + text = presentationData.strings.Wallet_Send_ErrorInvalidAddress + case .secretDecryptionFailed: + text = presentationData.strings.Wallet_Send_ErrorDecryptionFailed + case .destinationIsNotInitialized: + text = presentationData.strings.Wallet_UnknownError + } + let theme = presentationData.theme + let controller = textAlertController(alertContext: AlertControllerContext(theme: theme.alert, themeSignal: .single(theme.alert)), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Wallet_Alert_OK, action: { + })]) + presentControllerImpl?(controller, nil) + }) }) let walletState: Signal = getCombinedWalletState(storage: context.storage, subject: .wallet(walletInfo), tonInstance: context.tonInstance, onlyCached: true) diff --git a/submodules/WalletUI/Sources/WalletStrings.swift b/submodules/WalletUI/Sources/WalletStrings.swift index 41a556fa55..70a334e27e 100644 --- a/submodules/WalletUI/Sources/WalletStrings.swift +++ b/submodules/WalletUI/Sources/WalletStrings.swift @@ -403,8 +403,8 @@ public final class WalletStrings: Equatable { public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(self._s[182]!, self._r[182]!, [_1, _2, _3]) } - public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) { - return formatWithArgumentRanges(self._s[183]!, self._r[183]!, [_1, _2]) + public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(self._s[183]!, self._r[183]!, [_1, _2, _3]) } public var Wallet_Created_ExportErrorText: String { return self._s[185]! } public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) { diff --git a/submodules/WalletUI/Sources/WalletWordCheckScreen.swift b/submodules/WalletUI/Sources/WalletWordCheckScreen.swift index 5058ae767d..86152a7da9 100644 --- a/submodules/WalletUI/Sources/WalletWordCheckScreen.swift +++ b/submodules/WalletUI/Sources/WalletWordCheckScreen.swift @@ -2283,7 +2283,7 @@ private final class WordCheckInputNode: ASDisplayNode, UITextFieldDelegate { self.backgroundNode = ASImageNode() self.backgroundNode.displaysAsynchronously = false self.backgroundNode.displayWithoutProcessing = true - self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 10.0, color: theme.setup.inputBackgroundColor) + self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: theme.setup.inputBackgroundColor) self.labelNode = ImmediateTextNode() self.labelNode.attributedText = NSAttributedString(string: "\(index + 1):", font: Font.regular(17.0), textColor: theme.setup.inputPlaceholderColor) diff --git a/submodules/ton/BUCK b/submodules/ton/BUCK index 9ddff5e11f..1829fad04f 100644 --- a/submodules/ton/BUCK +++ b/submodules/ton/BUCK @@ -22,6 +22,7 @@ ton_lib_names = [ "crc32c", "keys", "lite-client-common", + "smc-envelope", "tdactor", "tddb", "tdnet", diff --git a/submodules/ton/tonlib-src/CMakeLists.txt b/submodules/ton/tonlib-src/CMakeLists.txt index a2bb0676cb..3727df784f 100644 --- a/submodules/ton/tonlib-src/CMakeLists.txt +++ b/submodules/ton/tonlib-src/CMakeLists.txt @@ -179,6 +179,7 @@ endif() set(CMAKE_THREAD_PREFER_PTHREAD ON) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) +find_package(ZLIB REQUIRED) if (TON_ARCH AND NOT MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${TON_ARCH}") @@ -350,6 +351,9 @@ target_link_libraries(test-ed25519 PRIVATE ton_crypto) add_executable(test-vm test/test-td-main.cpp ${TONVM_TEST_SOURCE}) target_link_libraries(test-vm PRIVATE ton_crypto fift-lib) +add_executable(test-smartcont test/test-td-main.cpp ${SMARTCONT_TEST_SOURCE}) +target_link_libraries(test-smartcont PRIVATE smc-envelope fift-lib ton_db) + add_executable(test-cells test/test-td-main.cpp ${CELLS_TEST_SOURCE}) target_link_libraries(test-cells PRIVATE ton_crypto) @@ -385,10 +389,12 @@ endif() enable_testing() set(TEST_OPTIONS "--regression ${CMAKE_CURRENT_SOURCE_DIR}/test/regression-tests.ans --filter -Bench") separate_arguments(TEST_OPTIONS) +add_test(test-ed25519-crypto crypto/test-ed25519-crypto) add_test(test-ed25519 test-ed25519) add_test(test-vm test-vm ${TEST_OPTIONS}) add_test(test-fift test-fift ${TEST_OPTIONS}) add_test(test-cells test-cells ${TEST_OPTIONS}) +add_test(test-smartcont test-smartcont) add_test(test-net test-net) add_test(test-actors test-tdactor) diff --git a/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp b/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp index d7a39d417e..1d10283b22 100644 --- a/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp +++ b/submodules/ton/tonlib-src/adnl/adnl-ext-client.cpp @@ -62,6 +62,9 @@ void AdnlExtClientImpl::hangup() { conn_ = {}; is_closing_ = true; ref_cnt_--; + for (auto &it : out_queries_) { + td::actor::ActorOwn<>(it.second); // send hangup + } try_stop(); } diff --git a/submodules/ton/tonlib-src/adnl/adnl-query.h b/submodules/ton/tonlib-src/adnl/adnl-query.h index e900c69987..3c0ebf065f 100644 --- a/submodules/ton/tonlib-src/adnl/adnl-query.h +++ b/submodules/ton/tonlib-src/adnl/adnl-query.h @@ -20,6 +20,7 @@ #include "td/actor/actor.h" #include "common/bitstring.h" +#include "common/errorcode.h" #include "td/utils/buffer.h" #include @@ -52,6 +53,9 @@ class AdnlQuery : public td::actor::Actor { } void tear_down() override { destroy_(id_); + if (promise_) { + promise_.set_error(td::Status::Error(ErrorCode::cancelled, "Cancelled")); + } } private: diff --git a/submodules/ton/tonlib-src/common/int-to-string.hpp b/submodules/ton/tonlib-src/common/int-to-string.hpp new file mode 100644 index 0000000000..414342cd0f --- /dev/null +++ b/submodules/ton/tonlib-src/common/int-to-string.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "td/utils/int_types.h" +#include "td/utils/Slice.h" + +namespace ton { + +template +typename std::enable_if_t::value, td::MutableSlice> store_int_to_slice(td::MutableSlice S, + const T &v) { + CHECK(S.size() >= sizeof(T)); + S.copy_from(td::Slice(reinterpret_cast(&v), sizeof(T))); + return S.remove_prefix(sizeof(T)); +} + +template +typename std::enable_if_t::value, T> fetch_int_from_slice(td::Slice S) { + CHECK(S.size() >= sizeof(T)); + T v; + td::MutableSlice(reinterpret_cast(&v), sizeof(T)).copy_from(S.truncate(sizeof(T))); + return v; +} + +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/CMakeLists.txt b/submodules/ton/tonlib-src/crypto/CMakeLists.txt index acf88eeef6..f2cb5cbb93 100644 --- a/submodules/ton/tonlib-src/crypto/CMakeLists.txt +++ b/submodules/ton/tonlib-src/crypto/CMakeLists.txt @@ -88,6 +88,7 @@ set(TON_CRYPTO_SOURCE vm/cells/CellBuilder.cpp vm/cells/CellHash.cpp vm/cells/CellSlice.cpp + vm/cells/CellString.cpp vm/cells/CellTraits.cpp vm/cells/CellUsageTree.cpp vm/cells/DataCell.cpp @@ -99,6 +100,7 @@ set(TON_CRYPTO_SOURCE vm/cells/CellBuilder.h vm/cells/CellHash.h vm/cells/CellSlice.h + vm/cells/CellString.h vm/cells/CellTraits.h vm/cells/CellUsageTree.h vm/cells/CellWithStorage.h @@ -197,6 +199,24 @@ set(BLOCK_SOURCE block/transaction.h ) +set(SMC_ENVELOPE_SOURCE + smc-envelope/GenericAccount.cpp + smc-envelope/MultisigWallet.cpp + smc-envelope/SmartContract.cpp + smc-envelope/SmartContractCode.cpp + smc-envelope/TestGiver.cpp + smc-envelope/TestWallet.cpp + smc-envelope/Wallet.cpp + + smc-envelope/GenericAccount.h + smc-envelope/MultisigWallet.h + smc-envelope/SmartContract.h + smc-envelope/SmartContractCode.h + smc-envelope/TestGiver.h + smc-envelope/TestWallet.h + smc-envelope/Wallet.h +) + set(ED25519_TEST_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/test/Ed25519.cpp PARENT_SCOPE @@ -217,6 +237,11 @@ set(TONVM_TEST_SOURCE PARENT_SCOPE ) +set(SMARTCONT_TEST_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/test/test-smartcont.cpp + PARENT_SCOPE +) + set(FIFT_TEST_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/test/fift.cpp PARENT_SCOPE @@ -279,6 +304,7 @@ if (TON_USE_ASAN AND NOT WIN32) set(TURN_OFF_LSAN export LSAN_OPTIONS=detect_leaks=0) endif() +file(MAKE_DIRECTORY smartcont/auto) if (NOT CMAKE_CROSSCOMPILING) set(GENERATE_TLB_CMD tlbc) add_custom_command( @@ -295,29 +321,51 @@ if (NOT CMAKE_CROSSCOMPILING) add_custom_target(gen_fif ALL) function(GenFif) set(options ) - set(oneValueArgs DEST) + set(oneValueArgs DEST NAME) set(multiValueArgs SOURCE) set(FUNC_LIB_SOURCE smartcont/stdlib.fc) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) string(REGEX REPLACE "[^a-zA-Z_]" "_" ID ${ARG_DEST}) + set(ARG_DEST_FIF "${ARG_DEST}.fif") add_custom_command( - COMMENT "Generate ${ARG_DEST}" + COMMENT "Generate ${ARG_DEST_FIF}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND func -PS -o ${ARG_DEST} ${FUNC_LIB_SOURCE} ${ARG_SOURCE} + COMMAND func -PS -o ${ARG_DEST_FIF} ${FUNC_LIB_SOURCE} ${ARG_SOURCE} MAIN_DEPENDENCY ${ARG_SOURCE} DEPENDS func ${FUNC_LIB_SOURCE} - OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST} + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_FIF} ) - add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST}) + set(ARG_DEST_CPP "${ARG_DEST}.cpp") + add_custom_command( + COMMENT "Generate ${ARG_DEST_CPP}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND fift -Ifift/lib:smartcont -s asm-to-cpp.fif ${ARG_DEST_FIF} ${ARG_DEST_CPP} ${ARG_NAME} + MAIN_DEPENDENCY ${ARG_SOURCE} + DEPENDS fift ${ARG_DEST_FIF} smartcont/asm-to-cpp.fif + OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_CPP} + ) + add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST_FIF} ${ARG_DEST_CPP}) add_dependencies(gen_fif gen_fif_${ID}) endfunction() - GenFif(DEST smartcont/config-code.fif SOURCE smartcont/config-code.fc) - GenFif(DEST smartcont/wallet-code.fif SOURCE smartcont/wallet-code.fc) - GenFif(DEST smartcont/simple-wallet-code.fif SOURCE smartcont/simple-wallet-code.fc) - GenFif(DEST smartcont/highload-wallet-code.fif SOURCE smartcont/highload-wallet-code.fc) - GenFif(DEST smartcont/highload-wallet-v2-code.fif SOURCE smartcont/highload-wallet-v2-code.fc) - GenFif(DEST smartcont/elector-code.fif SOURCE smartcont/elector-code.fc) + GenFif(DEST smartcont/auto/config-code SOURCE smartcont/config-code.fc NAME config) + GenFif(DEST smartcont/auto/wallet-code SOURCE smartcont/wallet-code.fc NAME wallet) + GenFif(DEST smartcont/auto/simple-wallet-code SOURCE smartcont/simple-wallet-code.fc NAME simple-wallet) + GenFif(DEST smartcont/auto/highload-wallet-code SOURCE smartcont/highload-wallet-code.fc NAME highload-wallet) + GenFif(DEST smartcont/auto/highload-wallet-v2-code SOURCE smartcont/highload-wallet-v2-code.fc NAME highoad-wallet-v2) + GenFif(DEST smartcont/auto/elector-code SOURCE smartcont/elector-code.fc NAME elector-code) + GenFif(DEST smartcont/auto/multisig-code SOURCE smartcont/multisig-code.fc NAME multisig) + GenFif(DEST smartcont/auto/restricted-wallet-code SOURCE smartcont/restricted-wallet-code.fc NAME restricted-wallet) + GenFif(DEST smartcont/auto/restricted-wallet2-code SOURCE smartcont/restricted-wallet2-code.fc NAME restricted-wallet2) + + GenFif(DEST smartcont/auto/simple-wallet-ext-code SOURCE smartcont/simple-wallet-ext-code.fc NAME simple-wallet-ext) +endif() + +add_library(smc-envelope ${SMC_ENVELOPE_SOURCE}) +target_include_directories(smc-envelope PUBLIC $) +target_link_libraries(smc-envelope PUBLIC ton_crypto PRIVATE tdutils ton_block) +if (NOT CMAKE_CROSSCOMPILING) + add_dependencies(smc-envelope gen_fif) endif() add_executable(create-state block/create-state.cpp) diff --git a/submodules/ton/tonlib-src/crypto/block/block-auto.cpp b/submodules/ton/tonlib-src/crypto/block/block-auto.cpp index 75dd9f659e..98ca0888bb 100644 --- a/submodules/ton/tonlib-src/crypto/block/block-auto.cpp +++ b/submodules/ton/tonlib-src/crypto/block/block-auto.cpp @@ -10481,7 +10481,7 @@ bool BlockInfo::skip(vm::CellSlice& cs) const { && cs.advance(392) && (!not_master || cs.advance_refs(1)) && cs.advance_refs(1) - && (!vert_seq_no || cs.advance_refs(1)); + && (!vert_seqno_incr || cs.advance_refs(1)); } bool BlockInfo::validate_skip(vm::CellSlice& cs, bool weak) const { @@ -10501,7 +10501,7 @@ bool BlockInfo::validate_skip(vm::CellSlice& cs, bool weak) const { && cs.advance(288) && (!not_master || t_BlkMasterInfo.validate_skip_ref(cs, weak)) && BlkPrevInfo{after_merge}.validate_skip_ref(cs, weak) - && (!vert_seq_no || t_BlkPrevInfo_0.validate_skip_ref(cs, weak)); + && (!vert_seqno_incr || t_BlkPrevInfo_0.validate_skip_ref(cs, weak)); } bool BlockInfo::unpack(vm::CellSlice& cs, BlockInfo::Record& data) const { @@ -10531,7 +10531,7 @@ bool BlockInfo::unpack(vm::CellSlice& cs, BlockInfo::Record& data) const { && cs.fetch_uint_to(32, data.prev_key_block_seqno) && (!data.not_master || cs.fetch_ref_to(data.master_ref)) && cs.fetch_ref_to(data.prev_ref) - && (!data.vert_seq_no || cs.fetch_ref_to(data.prev_vert_ref)); + && (!data.vert_seqno_incr || cs.fetch_ref_to(data.prev_vert_ref)); } bool BlockInfo::cell_unpack(Ref cell_ref, BlockInfo::Record& data) const { @@ -10567,7 +10567,7 @@ bool BlockInfo::pack(vm::CellBuilder& cb, const BlockInfo::Record& data) const { && cb.store_ulong_rchk_bool(data.prev_key_block_seqno, 32) && (!data.not_master || cb.store_ref_bool(data.master_ref)) && cb.store_ref_bool(data.prev_ref) - && (!data.vert_seq_no || cb.store_ref_bool(data.prev_vert_ref)); + && (!data.vert_seqno_incr || cb.store_ref_bool(data.prev_vert_ref)); } bool BlockInfo::cell_pack(Ref& cell_ref, const BlockInfo::Record& data) const { @@ -10613,7 +10613,7 @@ bool BlockInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const { && (!not_master || (pp.field("master_ref") && t_BlkMasterInfo.print_ref(pp, cs.fetch_ref()))) && pp.field("prev_ref") && BlkPrevInfo{after_merge}.print_ref(pp, cs.fetch_ref()) - && (!vert_seq_no || (pp.field("prev_vert_ref") && t_BlkPrevInfo_0.print_ref(pp, cs.fetch_ref()))) + && (!vert_seqno_incr || (pp.field("prev_vert_ref") && t_BlkPrevInfo_0.print_ref(pp, cs.fetch_ref()))) && pp.close(); } diff --git a/submodules/ton/tonlib-src/crypto/block/block-auto.h b/submodules/ton/tonlib-src/crypto/block/block-auto.h index fb9e1770d6..9c8c9c3724 100644 --- a/submodules/ton/tonlib-src/crypto/block/block-auto.h +++ b/submodules/ton/tonlib-src/crypto/block/block-auto.h @@ -4466,7 +4466,7 @@ struct BlockInfo::Record { unsigned prev_key_block_seqno; // prev_key_block_seqno : uint32 Ref master_ref; // master_ref : not_master?^BlkMasterInfo Ref prev_ref; // prev_ref : ^(BlkPrevInfo after_merge) - Ref prev_vert_ref; // prev_vert_ref : vert_seq_no?^(BlkPrevInfo 0) + Ref prev_vert_ref; // prev_vert_ref : vert_seqno_incr?^(BlkPrevInfo 0) Record() = default; Record(unsigned _version, bool _not_master, bool _after_merge, bool _before_split, bool _after_split, bool _want_split, bool _want_merge, bool _key_block, bool _vert_seqno_incr, int _flags, int _seq_no, int _vert_seq_no, Ref _shard, unsigned _gen_utime, unsigned long long _start_lt, unsigned long long _end_lt, unsigned _gen_validator_list_hash_short, unsigned _gen_catchain_seqno, unsigned _min_ref_mc_seqno, unsigned _prev_key_block_seqno, Ref _master_ref, Ref _prev_ref, Ref _prev_vert_ref) : version(_version), not_master(_not_master), after_merge(_after_merge), before_split(_before_split), after_split(_after_split), want_split(_want_split), want_merge(_want_merge), key_block(_key_block), vert_seqno_incr(_vert_seqno_incr), flags(_flags), seq_no(_seq_no), vert_seq_no(_vert_seq_no), shard(std::move(_shard)), gen_utime(_gen_utime), start_lt(_start_lt), end_lt(_end_lt), gen_validator_list_hash_short(_gen_validator_list_hash_short), gen_catchain_seqno(_gen_catchain_seqno), min_ref_mc_seqno(_min_ref_mc_seqno), prev_key_block_seqno(_prev_key_block_seqno), master_ref(std::move(_master_ref)), prev_ref(std::move(_prev_ref)), prev_vert_ref(std::move(_prev_vert_ref)) {} }; diff --git a/submodules/ton/tonlib-src/crypto/block/block.cpp b/submodules/ton/tonlib-src/crypto/block/block.cpp index 7b8074bfbc..80723b5856 100644 --- a/submodules/ton/tonlib-src/crypto/block/block.cpp +++ b/submodules/ton/tonlib-src/crypto/block/block.cpp @@ -718,12 +718,9 @@ td::Status ShardState::unpack_state(ton::BlockIdExt blkid, Ref prev_st return td::Status::Error(-666, "shardchain state for "s + blkid.to_str() + " corresponds to incorrect workchain or shard " + shard1.to_str()); } - if (state.vert_seq_no) { - return td::Status::Error( - -666, "shardchain state for "s + blkid.to_str() + " has non-zero vert_seq_no, which is unsupported"); - } id_ = blkid; root_ = std::move(prev_state_root); + vert_seqno_ = state.vert_seq_no; before_split_ = state.before_split; account_dict_ = std::make_unique( vm::load_cell_slice(std::move(state.accounts)).prefetch_ref(), 256, block::tlb::aug_ShardAccounts); @@ -811,7 +808,7 @@ td::Status ShardState::unpack_out_msg_queue_info(Ref out_msg_queue_inf } out_msg_queue_ = std::make_unique(std::move(qinfo.out_queue), 352, block::tlb::aug_OutMsgQueue); - if (verbosity >= 3 * 0) { + if (verbosity >= 3 * 1) { LOG(DEBUG) << "unpacking ProcessedUpto of our previous block " << id_.to_str(); block::gen::t_ProcessedInfo.print(std::cerr, qinfo.proc_info); } @@ -953,14 +950,16 @@ td::Status ShardState::merge_with(ShardState& sib) { lt_ = std::max(lt_, sib.lt_); // 9. compute underload & overload history underload_history_ = overload_history_ = 0; + // 10. compute vert_seqno + vert_seqno_ = std::max(vert_seqno_, sib.vert_seqno_); // Anything else? add here // ... - // 10. compute new root + // 100. compute new root if (!block::gen::t_ShardState.cell_pack_split_state(root_, std::move(root_), std::move(sib.root_))) { return td::Status::Error(-667, "cannot construct a virtual split_state after a merge"); } - // 11. invalidate sibling, change id_ to the (virtual) common parent + // 101. invalidate sibling, change id_ to the (virtual) common parent sib.invalidate(); id_.id.shard = shard.shard; id_.file_hash.set_zero(); diff --git a/submodules/ton/tonlib-src/crypto/block/block.h b/submodules/ton/tonlib-src/crypto/block/block.h index 9fbeedf29f..fd9a724f26 100644 --- a/submodules/ton/tonlib-src/crypto/block/block.h +++ b/submodules/ton/tonlib-src/crypto/block/block.h @@ -26,6 +26,7 @@ #include #include "tl/tlblib.hpp" #include "td/utils/bits.h" +#include "td/utils/CancellationToken.h" #include "td/utils/StringBuilder.h" #include "ton/ton-types.h" @@ -162,12 +163,12 @@ struct MsgProcessedUpto { MsgProcessedUpto(ton::ShardId _shard, ton::BlockSeqno _mcseqno, ton::LogicalTime _lt, td::ConstBitPtr _hash) : shard(_shard), mc_seqno(_mcseqno), last_inmsg_lt(_lt), last_inmsg_hash(_hash) { } - bool operator<(const MsgProcessedUpto& other) const & { + bool operator<(const MsgProcessedUpto& other) const& { return shard < other.shard || (shard == other.shard && mc_seqno < other.mc_seqno); } - bool contains(const MsgProcessedUpto& other) const &; + bool contains(const MsgProcessedUpto& other) const&; bool contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash, - ton::BlockSeqno other_mc_seqno) const &; + ton::BlockSeqno other_mc_seqno) const&; // NB: this is for checking whether we have already imported an internal message bool already_processed(const EnqueuedMsgDescr& msg) const; }; @@ -384,7 +385,7 @@ struct ShardState { int global_id_; ton::UnixTime utime_; ton::LogicalTime lt_; - ton::BlockSeqno mc_blk_seqno_, min_ref_mc_seqno_; + ton::BlockSeqno mc_blk_seqno_, min_ref_mc_seqno_, vert_seqno_; ton::BlockIdExt mc_blk_ref_; ton::LogicalTime mc_blk_lt_; bool before_split_{false}; @@ -573,7 +574,7 @@ struct BlockProofChain { bool last_link_incomplete() const { return !links.empty() && last_link().incomplete(); } - td::Status validate(); + td::Status validate(td::CancellationToken cancellation_token = {}); }; int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull old_shard, ton::ShardIdFull subshard); diff --git a/submodules/ton/tonlib-src/crypto/block/block.tlb b/submodules/ton/tonlib-src/crypto/block/block.tlb index 5108294770..d4bba1a182 100644 --- a/submodules/ton/tonlib-src/crypto/block/block.tlb +++ b/submodules/ton/tonlib-src/crypto/block/block.tlb @@ -421,7 +421,7 @@ block_info#9bc7a987 version:uint32 prev_key_block_seqno:uint32 master_ref:not_master?^BlkMasterInfo prev_ref:^(BlkPrevInfo after_merge) - prev_vert_ref:vert_seq_no?^(BlkPrevInfo 0) + prev_vert_ref:vert_seqno_incr?^(BlkPrevInfo 0) = BlockInfo; prev_blk_info$_ prev:ExtBlkRef = BlkPrevInfo 0; diff --git a/submodules/ton/tonlib-src/crypto/block/check-proof.cpp b/submodules/ton/tonlib-src/crypto/block/check-proof.cpp index c459b1b458..7db7a97c6c 100644 --- a/submodules/ton/tonlib-src/crypto/block/check-proof.cpp +++ b/submodules/ton/tonlib-src/crypto/block/check-proof.cpp @@ -32,7 +32,7 @@ namespace block { using namespace std::literals::string_literals; td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blkid, ton::Bits256* store_shard_hash_to, - bool check_state_hash, td::uint32* save_utime) { + bool check_state_hash, td::uint32* save_utime, ton::LogicalTime* save_lt) { ton::RootHash vhash{root->get_hash().bits()}; if (vhash != blkid.root_hash) { return td::Status::Error(PSTRING() << " block header for block " << blkid.to_str() << " has incorrect root hash " @@ -50,6 +50,9 @@ td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blki if (save_utime) { *save_utime = info.gen_utime; } + if (save_lt) { + *save_lt = info.end_lt; + } if (store_shard_hash_to) { vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update}; if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update @@ -157,7 +160,7 @@ td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td: td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr, td::Ref root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash, - td::uint32* save_utime) { + td::uint32* save_utime, ton::LogicalTime* save_lt) { TRY_RESULT_PREFIX(Q_roots, vm::std_boc_deserialize_multi(std::move(proof)), "cannot deserialize account proof"); if (Q_roots.size() != 2) { return td::Status::Error(PSLICE() << "account state proof must have exactly two roots"); @@ -174,7 +177,7 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const } ton::Bits256 state_hash = state_root->get_hash().bits(); TRY_STATUS_PREFIX(check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk, - &state_hash, true, save_utime), + &state_hash, true, save_utime, save_lt), "error in account shard block header proof : "); block::gen::ShardStateUnsplit::Record sstate; if (!(tlb::unpack_cell(std::move(state_root), sstate))) { @@ -218,8 +221,6 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const td::Result AccountState::validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const { TRY_RESULT_PREFIX(root, vm::std_boc_deserialize(state.as_slice(), true), "cannot deserialize account state"); - LOG(INFO) << "got account state for " << addr << " with respect to blocks " << blk.to_str() - << (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str()); if (blk != ref_blk && ref_blk.id.seqno != ~0U) { return td::Status::Error(PSLICE() << "obtained getAccountState() for a different reference block " << blk.to_str() << " instead of requested " << ref_blk.to_str()); @@ -238,7 +239,7 @@ td::Result AccountState::validate(ton::BlockIdExt ref_blk, b Info res; TRY_STATUS(block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt, - &res.last_trans_hash, &res.gen_utime)); + &res.last_trans_hash, &res.gen_utime, &res.gen_lt)); res.root = std::move(root); return res; @@ -424,7 +425,7 @@ td::Status BlockProofLink::validate(td::uint32* save_utime) const { } } -td::Status BlockProofChain::validate() { +td::Status BlockProofChain::validate(td::CancellationToken cancellation_token) { valid = false; has_key_block = false; has_utime = false; @@ -450,6 +451,9 @@ td::Status BlockProofChain::validate() { << link.from.to_str() << " but the previous link ends at different block " << cur.to_str()); } + if (cancellation_token) { + return td::Status::Error("Cancelled"); + } auto err = link.validate(&last_utime); if (err.is_error()) { return td::Status::Error(PSTRING() << "link #" << i << " in BlockProofChain is invalid: " << err.to_string()); diff --git a/submodules/ton/tonlib-src/crypto/block/check-proof.h b/submodules/ton/tonlib-src/crypto/block/check-proof.h index 87d6b442b7..173ae9e475 100644 --- a/submodules/ton/tonlib-src/crypto/block/check-proof.h +++ b/submodules/ton/tonlib-src/crypto/block/check-proof.h @@ -26,11 +26,12 @@ using td::Ref; td::Status check_block_header_proof(td::Ref root, ton::BlockIdExt blkid, ton::Bits256* store_shard_hash_to = nullptr, bool check_state_hash = false, - td::uint32* save_utime = nullptr); + td::uint32* save_utime = nullptr, ton::LogicalTime* save_lt = nullptr); td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::Slice shard_proof); td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr, td::Ref root, ton::LogicalTime* last_trans_lt = nullptr, - ton::Bits256* last_trans_hash = nullptr, td::uint32* save_utime = nullptr); + ton::Bits256* last_trans_hash = nullptr, td::uint32* save_utime = nullptr, + ton::LogicalTime* save_lt = nullptr); td::Result check_state_proof(ton::BlockIdExt blkid, td::Slice proof); td::Result> check_extract_state_proof(ton::BlockIdExt blkid, td::Slice proof, td::Slice data); @@ -48,6 +49,7 @@ struct AccountState { td::Ref root; ton::LogicalTime last_trans_lt = 0; ton::Bits256 last_trans_hash; + ton::LogicalTime gen_lt{0}; td::uint32 gen_utime{0}; }; diff --git a/submodules/ton/tonlib-src/crypto/block/mc-config.cpp b/submodules/ton/tonlib-src/crypto/block/mc-config.cpp index ceefca79e5..2b3fdb44b0 100644 --- a/submodules/ton/tonlib-src/crypto/block/mc-config.cpp +++ b/submodules/ton/tonlib-src/crypto/block/mc-config.cpp @@ -517,6 +517,58 @@ td::Result> Config::get_storage_prices() const { return std::move(res); } +td::Result Config::get_gas_limits_prices(bool is_masterchain) const { + GasLimitsPrices res; + auto id = is_masterchain ? 20 : 21; + auto cell = get_config_param(id); + if (cell.is_null()) { + return td::Status::Error(PSLICE() << "configuration parameter " << id << " with gas prices is absent"); + } + auto cs = vm::load_cell_slice(std::move(cell)); + block::gen::GasLimitsPrices::Record_gas_flat_pfx flat; + if (tlb::unpack(cs, flat)) { + cs = *flat.other; + res.flat_gas_limit = flat.flat_gas_limit; + res.flat_gas_price = flat.flat_gas_price; + } + auto f = [&](const auto& r, td::uint64 spec_limit) { + res.gas_limit = r.gas_limit; + res.special_gas_limit = spec_limit; + res.gas_credit = r.gas_credit; + res.gas_price = r.gas_price; + res.freeze_due_limit = r.freeze_due_limit; + res.delete_due_limit = r.delete_due_limit; + }; + block::gen::GasLimitsPrices::Record_gas_prices_ext rec; + if (tlb::unpack(cs, rec)) { + f(rec, rec.special_gas_limit); + } else { + block::gen::GasLimitsPrices::Record_gas_prices rec0; + if (tlb::unpack(cs, rec0)) { + f(rec0, rec0.gas_limit); + } else { + return td::Status::Error(PSLICE() << "configuration parameter " << id + << " with gas prices is invalid - can't parse"); + } + } + return res; +} + +td::Result Config::get_msg_prices(bool is_masterchain) const { + auto id = is_masterchain ? 24 : 25; + auto cell = get_config_param(id); + if (cell.is_null()) { + return td::Status::Error(PSLICE() << "configuration parameter " << id << " with msg prices is absent"); + } + auto cs = vm::load_cell_slice(std::move(cell)); + block::gen::MsgForwardPrices::Record rec; + if (!tlb::unpack(cs, rec)) { + return td::Status::Error(PSLICE() << "configuration parameter " << id + << " with msg prices is invalid - can't parse"); + } + return MsgPrices(rec.lump_price, rec.bit_price, rec.cell_price, rec.ihr_price_factor, rec.first_frac, rec.next_frac); +} + CatchainValidatorsConfig Config::unpack_catchain_validators_config(Ref cell) { block::gen::CatchainConfig::Record cfg; if (cell.is_null() || !tlb::unpack_cell(std::move(cell), cfg)) { @@ -1019,47 +1071,47 @@ std::vector ShardConfig::get_shard_hash_ids( std::vector res; bool mcout = mc_shard_hash_.is_null() || !mc_shard_hash_->seqno(); // include masterchain as a shard if seqno > 0 bool ok = shard_hashes_dict_->check_for_each( - [&res, &mcout, mc_shard_hash_ = mc_shard_hash_, &filter ](Ref cs_ref, td::ConstBitPtr key, int n) - ->bool { - int workchain = (int)key.get_int(n); - if (workchain >= 0 && !mcout) { - if (filter(ton::ShardIdFull{ton::masterchainId}, true)) { - res.emplace_back(mc_shard_hash_->blk_.id); - } - mcout = true; - } - if (!cs_ref->have_refs()) { + [&res, &mcout, mc_shard_hash_ = mc_shard_hash_, &filter](Ref cs_ref, td::ConstBitPtr key, + int n) -> bool { + int workchain = (int)key.get_int(n); + if (workchain >= 0 && !mcout) { + if (filter(ton::ShardIdFull{ton::masterchainId}, true)) { + res.emplace_back(mc_shard_hash_->blk_.id); + } + mcout = true; + } + if (!cs_ref->have_refs()) { + return false; + } + std::stack, unsigned long long>> stack; + stack.emplace(cs_ref->prefetch_ref(), ton::shardIdAll); + while (!stack.empty()) { + vm::CellSlice cs{vm::NoVm{}, std::move(stack.top().first)}; + unsigned long long shard = stack.top().second; + stack.pop(); + int t = (int)cs.fetch_ulong(1); + if (t < 0) { + return false; + } + if (!filter(ton::ShardIdFull{workchain, shard}, !t)) { + continue; + } + if (!t) { + if (!(cs.advance(4) && cs.have(32))) { return false; } - std::stack, unsigned long long>> stack; - stack.emplace(cs_ref->prefetch_ref(), ton::shardIdAll); - while (!stack.empty()) { - vm::CellSlice cs{vm::NoVm{}, std::move(stack.top().first)}; - unsigned long long shard = stack.top().second; - stack.pop(); - int t = (int)cs.fetch_ulong(1); - if (t < 0) { - return false; - } - if (!filter(ton::ShardIdFull{workchain, shard}, !t)) { - continue; - } - if (!t) { - if (!(cs.advance(4) && cs.have(32))) { - return false; - } - res.emplace_back(workchain, shard, (int)cs.prefetch_ulong(32)); - continue; - } - unsigned long long delta = (td::lower_bit64(shard) >> 1); - if (!delta || cs.size_ext() != 0x20000) { - return false; - } - stack.emplace(cs.prefetch_ref(1), shard + delta); - stack.emplace(cs.prefetch_ref(0), shard - delta); - } - return true; - }, + res.emplace_back(workchain, shard, (int)cs.prefetch_ulong(32)); + continue; + } + unsigned long long delta = (td::lower_bit64(shard) >> 1); + if (!delta || cs.size_ext() != 0x20000) { + return false; + } + stack.emplace(cs.prefetch_ref(1), shard + delta); + stack.emplace(cs.prefetch_ref(0), shard - delta); + } + return true; + }, true); if (!ok) { return {}; @@ -1415,8 +1467,8 @@ td::Result> Config::get_special_smartcontracts(b return td::Status::Error(-666, "configuration loaded without fundamental smart contract list"); } std::vector res; - if (!special_smc_dict->check_for_each([&res, &without_config, conf_addr = config_addr.bits() ]( - Ref cs_ref, td::ConstBitPtr key, int n) { + if (!special_smc_dict->check_for_each([&res, &without_config, conf_addr = config_addr.bits()]( + Ref cs_ref, td::ConstBitPtr key, int n) { if (cs_ref->size_ext() || n != 256) { return false; } diff --git a/submodules/ton/tonlib-src/crypto/block/mc-config.h b/submodules/ton/tonlib-src/crypto/block/mc-config.h index dc48ec0256..018a47adbe 100644 --- a/submodules/ton/tonlib-src/crypto/block/mc-config.h +++ b/submodules/ton/tonlib-src/crypto/block/mc-config.h @@ -50,7 +50,7 @@ struct ValidatorDescr { : pubkey(_pubkey), weight(_weight), cum_weight(_cum_weight) { adnl_addr.set_zero(); } - bool operator<(td::uint64 wt_pos) const & { + bool operator<(td::uint64 wt_pos) const& { return cum_weight < wt_pos; } }; @@ -327,6 +327,46 @@ struct StoragePrices { , mc_bit_price(_mc_bprice) , mc_cell_price(_mc_cprice) { } + static td::RefInt256 compute_storage_fees(ton::UnixTime now, const std::vector& pricing, + const vm::CellStorageStat& storage_stat, ton::UnixTime last_paid, + bool is_special, bool is_masterchain); +}; + +struct GasLimitsPrices { + td::uint64 flat_gas_limit{0}; + td::uint64 flat_gas_price{0}; + td::uint64 gas_price{0}; + td::uint64 special_gas_limit{0}; + td::uint64 gas_limit{0}; + td::uint64 gas_credit{0}; + td::uint64 block_gas_limit{0}; + td::uint64 freeze_due_limit{0}; + td::uint64 delete_due_limit{0}; + + td::RefInt256 compute_gas_price(td::uint64 gas_used) const; +}; + +// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms +// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms +// bits in the root cell of a message are not included in msg.bits (lump_price pays for them) + +struct MsgPrices { + td::uint64 lump_price; + td::uint64 bit_price; + td::uint64 cell_price; + td::uint32 ihr_factor; + td::uint32 first_frac; + td::uint32 next_frac; + td::uint64 compute_fwd_fees(td::uint64 cells, td::uint64 bits) const; + std::pair compute_fwd_ihr_fees(td::uint64 cells, td::uint64 bits, + bool ihr_disabled = false) const; + MsgPrices() = default; + MsgPrices(td::uint64 lump, td::uint64 bitp, td::uint64 cellp, td::uint32 ihrf, td::uint32 firstf, td::uint32 nextf) + : lump_price(lump), bit_price(bitp), cell_price(cellp), ihr_factor(ihrf), first_frac(firstf), next_frac(nextf) { + } + td::RefInt256 get_first_part(td::RefInt256 total) const; + td::uint64 get_first_part(td::uint64 total) const; + td::RefInt256 get_next_part(td::RefInt256 total) const; }; struct CatchainValidatorsConfig { @@ -499,6 +539,8 @@ class Config { bool is_special_smartcontract(const ton::StdSmcAddress& addr) const; static td::Result> unpack_validator_set(Ref valset_root); td::Result> get_storage_prices() const; + td::Result get_gas_limits_prices(bool is_masterchain = false) const; + td::Result get_msg_prices(bool is_masterchain = false) const; static CatchainValidatorsConfig unpack_catchain_validators_config(Ref cell); CatchainValidatorsConfig get_catchain_validators_config() const; td::Status visit_validator_params() const; @@ -556,7 +598,7 @@ class ConfigInfo : public Config, public ShardConfig { needAccountsRoot = 64, needPrevBlocks = 128 }; - int vert_seqno{-1}; + ton::BlockSeqno vert_seqno{~0U}; int global_id_{0}; ton::UnixTime utime{0}; ton::LogicalTime lt{0}; @@ -604,6 +646,9 @@ class ConfigInfo : public Config, public ShardConfig { Ref get_state_extra_root() const { return state_extra_root_; } + ton::BlockSeqno get_vert_seqno() const { + return vert_seqno; + } ton::CatchainSeqno get_shard_cc_seqno(ton::ShardIdFull shard) const; bool get_last_key_block(ton::BlockIdExt& blkid, ton::LogicalTime& blklt, bool strict = false) const; bool get_old_mc_block_id(ton::BlockSeqno seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const; diff --git a/submodules/ton/tonlib-src/crypto/block/transaction.cpp b/submodules/ton/tonlib-src/crypto/block/transaction.cpp index 24fc731ee4..6667cf8774 100644 --- a/submodules/ton/tonlib-src/crypto/block/transaction.cpp +++ b/submodules/ton/tonlib-src/crypto/block/transaction.cpp @@ -421,7 +421,9 @@ void add_partial_storage_payment(td::BigInt256& payment, ton::UnixTime delta, co payment += b; } -td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector& pricing) const { +td::RefInt256 StoragePrices::compute_storage_fees(ton::UnixTime now, const std::vector& pricing, + const vm::CellStorageStat& storage_stat, ton::UnixTime last_paid, + bool is_special, bool is_masterchain) { if (now <= last_paid || !last_paid || is_special || pricing.empty() || now <= pricing[0].valid_since) { return {}; } @@ -438,7 +440,7 @@ td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector ton::UnixTime valid_until = (i < n - 1 ? std::min(now, pricing[i + 1].valid_since) : now); if (upto < valid_until) { assert(upto >= pricing[i].valid_since); - add_partial_storage_payment(total.unique_write(), valid_until - upto, pricing[i], storage_stat, is_masterchain()); + add_partial_storage_payment(total.unique_write(), valid_until - upto, pricing[i], storage_stat, is_masterchain); } upto = valid_until; } @@ -446,6 +448,10 @@ td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector return total; } +td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector& pricing) const { + return StoragePrices::compute_storage_fees(now, pricing, storage_stat, last_paid, is_special, is_masterchain()); +} + Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime req_start_lt, ton::UnixTime _now, Ref _inmsg) : trans_type(ttype) @@ -739,7 +745,8 @@ td::uint64 ComputePhaseConfig::gas_bought_for(td::RefInt256 nanograms) const { } td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const { - return td::rshift(gas_price256 * gas_used, 16, 1); + return gas_used <= flat_gas_limit ? td::make_refint(flat_gas_price) + : td::rshift(gas_price256 * (gas_used - flat_gas_limit), 16, 1) + flat_gas_price; } bool Transaction::compute_gas_limits(ComputePhase& cp, const ComputePhaseConfig& cfg) { @@ -805,7 +812,6 @@ bool Transaction::prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputeP } Ref Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const { - // TODO: fix initialization of c7 td::BitArray<256> rand_seed; td::RefInt256 rand_seed_int{true}; if (!(prepare_rand_seed(rand_seed, cfg) && rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false))) { @@ -969,7 +975,7 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { gas = vm.get_gas_limits(); cp.gas_used = std::min(gas.gas_consumed(), gas.gas_limit); cp.accepted = (gas.gas_credit == 0); - cp.success = (cp.accepted && (unsigned)cp.exit_code <= 1); + cp.success = (cp.accepted && vm.committed()); if (cp.accepted & use_msg_state) { was_activated = true; acc_status = Account::acc_active; @@ -978,8 +984,8 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { << ", limit=" << gas.gas_limit << ", credit=" << gas.gas_credit; LOG(INFO) << "out_of_gas=" << cp.out_of_gas << ", accepted=" << cp.accepted << ", success=" << cp.success; if (cp.success) { - cp.new_data = vm.get_c4(); // c4 -> persistent data - cp.actions = vm.get_d(5); // c5 -> action list + cp.new_data = vm.get_committed_state().c4; // c4 -> persistent data + cp.actions = vm.get_committed_state().c5; // c5 -> action list int out_act_num = output_actions_count(cp.actions); if (verbosity > 2) { std::cerr << "new smart contract data: "; @@ -1304,9 +1310,9 @@ bool Transaction::check_rewrite_dest_addr(Ref& dest_addr, const A int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap, const ActionPhaseConfig& cfg, int redoing) { block::gen::OutAction::Record_action_send_msg act_rec; - // mode: +128 = attach all remaining balance, +64 = attach all remaining balance of the inbound message, +1 = pay message fees, +2 = skip if message cannot be sent + // mode: +128 = attach all remaining balance, +64 = attach all remaining balance of the inbound message, +32 = delete smart contract if balance becomes zero, +1 = pay message fees, +2 = skip if message cannot be sent vm::CellSlice cs{cs0}; - if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xc3) || (act_rec.mode & 0xc0) == 0xc0) { + if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xe3) || (act_rec.mode & 0xc0) == 0xc0) { return -1; } bool skip_invalid = (act_rec.mode & 2); @@ -1573,7 +1579,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap, ap.total_action_fees += fees_collected; ap.total_fwd_fees += fees_total; - if (act_rec.mode & 0x80) { + if ((act_rec.mode & 0xa0) == 0xa0) { CHECK(ap.remaining_balance.is_zero()); ap.acc_delete_req = ap.reserved_balance.is_zero(); } diff --git a/submodules/ton/tonlib-src/crypto/block/transaction.h b/submodules/ton/tonlib-src/crypto/block/transaction.h index 015dc3f39e..25f8059560 100644 --- a/submodules/ton/tonlib-src/crypto/block/transaction.h +++ b/submodules/ton/tonlib-src/crypto/block/transaction.h @@ -65,10 +65,10 @@ struct NewOutMsg { NewOutMsg(ton::LogicalTime _lt, Ref _msg, Ref _trans) : lt(_lt), msg(std::move(_msg)), trans(std::move(_trans)) { } - bool operator<(const NewOutMsg& other) const & { + bool operator<(const NewOutMsg& other) const& { return lt < other.lt || (lt == other.lt && msg->get_hash() < other.msg->get_hash()); } - bool operator>(const NewOutMsg& other) const & { + bool operator>(const NewOutMsg& other) const& { return lt > other.lt || (lt == other.lt && other.msg->get_hash() < msg->get_hash()); } }; @@ -132,29 +132,6 @@ struct ComputePhaseConfig { bool parse_GasLimitsPrices(Ref cell, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit); }; -// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms -// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms -// bits in the root cell of a message are not included in msg.bits (lump_price pays for them) - -struct MsgPrices { - td::uint64 lump_price; - td::uint64 bit_price; - td::uint64 cell_price; - td::uint32 ihr_factor; - td::uint32 first_frac; - td::uint32 next_frac; - td::uint64 compute_fwd_fees(td::uint64 cells, td::uint64 bits) const; - std::pair compute_fwd_ihr_fees(td::uint64 cells, td::uint64 bits, - bool ihr_disabled = false) const; - MsgPrices() = default; - MsgPrices(td::uint64 lump, td::uint64 bitp, td::uint64 cellp, td::uint32 ihrf, td::uint32 firstf, td::uint32 nextf) - : lump_price(lump), bit_price(bitp), cell_price(cellp), ihr_factor(ihrf), first_frac(firstf), next_frac(nextf) { - } - td::RefInt256 get_first_part(td::RefInt256 total) const; - td::uint64 get_first_part(td::uint64 total) const; - td::RefInt256 get_next_part(td::RefInt256 total) const; -}; - struct ActionPhaseConfig { int max_actions{255}; MsgPrices fwd_std; diff --git a/submodules/ton/tonlib-src/crypto/common/bitstring.h b/submodules/ton/tonlib-src/crypto/common/bitstring.h index b2a37c72f0..901ff709b7 100644 --- a/submodules/ton/tonlib-src/crypto/common/bitstring.h +++ b/submodules/ton/tonlib-src/crypto/common/bitstring.h @@ -224,6 +224,8 @@ class BitSliceGen { BitSliceGen(BitSliceGen&& bs, unsigned _offs, unsigned _len); BitSliceGen(Pt* _ptr, unsigned _len) : ref(), ptr(_ptr), offs(0), len(_len) { } + explicit BitSliceGen(Slice slice) : BitSliceGen(slice.data(), slice.size() * 8) { + } ~BitSliceGen() { } Pt* get_ptr() const { diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Asm.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Asm.fif index 69adeeeaa8..eb9034ec1e 100644 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Asm.fif +++ b/submodules/ton/tonlib-src/crypto/fift/lib/Asm.fif @@ -756,6 +756,12 @@ x{EDF9} @Defop BOOLEVAL { PUSHINT c3 PREPAREVAR } cond } dup : PREPARE : PREPAREDICT // +// inline support +{ dup sbits { @addop } { + dup srefs 1- abort"exactly one reference expected in inline" + ref@ CALLREF } cond +} : INLINE +// // throwing and handling exceptions { dup 6 ufits { { s>c c } : }END> diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/Fift.fif b/submodules/ton/tonlib-src/crypto/fift/lib/Fift.fif index f674be7976..5430c359e7 100644 --- a/submodules/ton/tonlib-src/crypto/fift/lib/Fift.fif +++ b/submodules/ton/tonlib-src/crypto/fift/lib/Fift.fif @@ -42,8 +42,8 @@ { dup 10 < { 48 } { 55 } cond + } : Digit { dup 10 < { 48 } { 87 } cond + } : digit // x s b -- x' s' -{ -rot swap rot /mod Digit rot swap hold } : B# -{ -rot swap rot /mod digit rot swap hold } : b# +{ rot swap /mod Digit rot swap hold } : B# +{ rot swap /mod digit rot swap hold } : b# { 16 B# } : X# { 16 b# } : x# // x s b -- 0 s' @@ -110,3 +110,4 @@ variable base { null ' cons rot times } : list { true (atom) drop } : atom { bl word atom 1 'nop } ::_ ` +{ hole dup 1 { @ execute } does create } : recursive diff --git a/submodules/ton/tonlib-src/crypto/fift/lib/TonUtil.fif b/submodules/ton/tonlib-src/crypto/fift/lib/TonUtil.fif index 9535322255..44f1ff1cfd 100644 --- a/submodules/ton/tonlib-src/crypto/fift/lib/TonUtil.fif +++ b/submodules/ton/tonlib-src/crypto/fift/lib/TonUtil.fif @@ -123,3 +123,28 @@ forget val, forget val@ forget .val { 0 lib+ } : private_lib // ( D c -- D' ) Add public library c to collection D { 1 lib+ } : public_lib + +// serialize simple transfers with long comments +// b B n -- b' +recursive append-long-bytes { + over Blen over <= { drop B, } { + B| -rot B, swap ref, + } cond +} swap ! +// b S n -- b' +{ swap $>B swap append-long-bytes } : append-long-string +// S -- c +{ +} : simple-transfer-body + +// ( S -- x ) parse public key +{ dup $len 48 <> abort"public key must be 48 characters long" + base64>B dup Blen 36 <> abort"public key must be 48 characters long" + 34 B| 16 B>u@ over crc16 <> abort"crc16 mismatch in public key" + 16 B>u@+ 0x3ee6 <> abort"invalid tag in public key" + 256 B>u@ +} : parse-pubkey +{ bl word parse-pubkey 1 'nop } ::_ PK' +// ( x -- S ) serialize public key +{ 256 u>B B{3ee6} swap B+ dup crc16 16 u>B B+ B>base64 } : pubkey>$ +{ pubkey>$ type } : .pubkey diff --git a/submodules/ton/tonlib-src/crypto/fift/utils.cpp b/submodules/ton/tonlib-src/crypto/fift/utils.cpp index 1c16b2cd4a..fdbd0c7eef 100644 --- a/submodules/ton/tonlib-src/crypto/fift/utils.cpp +++ b/submodules/ton/tonlib-src/crypto/fift/utils.cpp @@ -43,6 +43,9 @@ td::Result load_TonUtil_fif(std::string dir = "") { td::Result load_Lists_fif(std::string dir = "") { return load_source("Lists.fif", dir); } +td::Result load_Lisp_fif(std::string dir = "") { + return load_source("Lisp.fif", dir); +} class MemoryFileLoader : public fift::FileLoader { public: @@ -91,7 +94,8 @@ class MemoryFileLoader : public fift::FileLoader { }; td::Result create_source_lookup(std::string main, bool need_preamble = true, bool need_asm = true, - bool need_ton_util = true, std::string dir = "") { + bool need_ton_util = true, bool need_lisp = true, + std::string dir = "") { auto loader = std::make_unique(); loader->add_file("/main.fif", std::move(main)); if (need_preamble) { @@ -112,6 +116,10 @@ td::Result create_source_lookup(std::string main, bool need_ loader->add_file("/TonUtil.fif", std::move(f)); } } + if (need_lisp) { + TRY_RESULT(f, load_Lisp_fif(dir)); + loader->add_file("/Lisp.fif", std::move(f)); + } auto res = fift::SourceLookup(std::move(loader)); res.add_include_path("/"); return std::move(res); @@ -143,7 +151,7 @@ td::Result run_fift(fift::SourceLookup source_lookup, std::o } // namespace td::Result mem_run_fift(std::string source, std::vector args, std::string fift_dir) { std::stringstream ss; - TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, fift_dir)); + TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, true, fift_dir)); TRY_RESULT_ASSIGN(source_lookup, run_fift(std::move(source_lookup), &ss, true, std::move(args))); FiftOutput res; res.source_lookup = std::move(source_lookup); @@ -159,8 +167,8 @@ td::Result mem_run_fift(SourceLookup source_lookup, std::vector create_mem_source_lookup(std::string main, std::string fift_dir, bool need_preamble, - bool need_asm, bool need_ton_util) { - return create_source_lookup(main, need_preamble, need_asm, need_ton_util, fift_dir); + bool need_asm, bool need_ton_util, bool need_lisp) { + return create_source_lookup(main, need_preamble, need_asm, need_ton_util, need_lisp, fift_dir); } td::Result> compile_asm(td::Slice asm_code, std::string fift_dir, bool is_raw) { @@ -168,7 +176,7 @@ td::Result> compile_asm(td::Slice asm_code, std::string fift_d TRY_RESULT(source_lookup, create_source_lookup(PSTRING() << "\"Asm.fif\" include\n " << (is_raw ? "<{" : "") << asm_code << "\n" << (is_raw ? "}>c" : "") << " boc>B \"res\" B>file", - true, true, true, fift_dir)); + true, true, true, false, fift_dir)); TRY_RESULT(res, run_fift(std::move(source_lookup), &ss)); TRY_RESULT(boc, res.read_file("res")); return vm::std_boc_deserialize(std::move(boc.data)); diff --git a/submodules/ton/tonlib-src/crypto/fift/utils.h b/submodules/ton/tonlib-src/crypto/fift/utils.h index e17eb8ae2c..0dcc629f91 100644 --- a/submodules/ton/tonlib-src/crypto/fift/utils.h +++ b/submodules/ton/tonlib-src/crypto/fift/utils.h @@ -28,7 +28,7 @@ struct FiftOutput { }; td::Result create_mem_source_lookup(std::string main, std::string fift_dir = "", bool need_preamble = true, bool need_asm = true, - bool need_ton_util = true); + bool need_ton_util = true, bool need_lisp = true); td::Result mem_run_fift(std::string source, std::vector args = {}, std::string fift_dir = ""); td::Result mem_run_fift(SourceLookup source_lookup, std::vector args); td::Result> compile_asm(td::Slice asm_code, std::string fift_dir = "", bool is_raw = true); diff --git a/submodules/ton/tonlib-src/crypto/fift/words.cpp b/submodules/ton/tonlib-src/crypto/fift/words.cpp index 87c269b78e..2c1a3083d6 100644 --- a/submodules/ton/tonlib-src/crypto/fift/words.cpp +++ b/submodules/ton/tonlib-src/crypto/fift/words.cpp @@ -614,6 +614,43 @@ void interpret_str_reverse(vm::Stack& stack) { stack.push_string(std::move(s)); } +void interpret_utf8_str_len(vm::Stack& stack) { + std::string s = stack.pop_string(); + long long cnt = 0; + for (char c : s) { + if ((c & 0xc0) != 0x80) { + cnt++; + } + } + stack.push_smallint(cnt); +} + +void interpret_utf8_str_split(vm::Stack& stack) { + stack.check_underflow(2); + unsigned c = stack.pop_smallint_range(0xffff); + std::string s = stack.pop_string(); + if (c > s.size()) { + throw IntError{"not enough utf8 characters for cutting"}; + } + auto it = s.begin(); + for (; it < s.end(); ++it) { + if ((*it & 0xc0) != 0x80) { + if (!c) { + stack.push_string(std::string{s.begin(), it}); + stack.push_string(std::string{it, s.end()}); + return; + } + --c; + } + } + if (!c) { + stack.push_string(std::move(s)); + stack.push_string(std::string{}); + } else { + throw IntError{"not enough utf8 characters for cutting"}; + } +} + void interpret_str_remove_trailing_int(vm::Stack& stack, int arg) { char x = (char)(arg ? arg : stack.pop_long_range(127)); std::string s = stack.pop_string(); @@ -1797,6 +1834,16 @@ void interpret_char(IntCtx& ctx) { push_argcount(ctx, 1); } +void interpret_char_internal(vm::Stack& stack) { + auto s = stack.pop_string(); + int len = (s.size() < 10 ? (int)s.size() : 10); + int code = str_utf8_code(s.c_str(), len); + if (code < 0 || s.size() != (unsigned)len) { + throw IntError{"exactly one character expected"}; + } + stack.push_smallint(code); +} + int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool allow_frac = true, bool throw_error = false) { if (allow_frac) { @@ -2149,7 +2196,23 @@ void interpret_run_vm(IntCtx& ctx, bool with_gas) { OstreamLogger ostream_logger(ctx.error_stream); auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr); vm::GasLimits gas{gas_limit}; - int res = vm::run_vm_code(cs, ctx.stack, 3, &data, log, nullptr, &gas); + int res = vm::run_vm_code(cs, ctx.stack, 1, &data, log, nullptr, &gas, get_vm_libraries()); + ctx.stack.push_smallint(res); + ctx.stack.push_cell(std::move(data)); + if (with_gas) { + ctx.stack.push_smallint(gas.gas_consumed()); + } +} + +void interpret_run_vm_c7(IntCtx& ctx, bool with_gas) { + long long gas_limit = with_gas ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty; + auto c7 = ctx.stack.pop_tuple(); + auto data = ctx.stack.pop_cell(); + auto cs = ctx.stack.pop_cellslice(); + OstreamLogger ostream_logger(ctx.error_stream); + auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr); + vm::GasLimits gas{gas_limit}; + int res = vm::run_vm_code(cs, ctx.stack, 1, &data, log, nullptr, &gas, get_vm_libraries(), std::move(c7)); ctx.stack.push_smallint(res); ctx.stack.push_cell(std::move(data)); if (with_gas) { @@ -2278,6 +2341,21 @@ void interpret_get_cmdline_arg(IntCtx& ctx) { } } +void interpret_getenv(vm::Stack& stack) { + auto str = stack.pop_string(); + auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr; + stack.push_string(value ? std::string{value} : ""); +} + +void interpret_getenv_exists(vm::Stack& stack) { + auto str = stack.pop_string(); + auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr; + if (value) { + stack.push_string(std::string{value}); + } + stack.push_bool((bool)value); +} + // x1 .. xn n 'w --> void interpret_execute_internal(IntCtx& ctx) { Ref word_def = pop_exec_token(ctx); @@ -2315,7 +2393,7 @@ void compile_one_literal(WordList& wlist, vm::StackEntry val) { auto x = std::move(val).as_int(); if (!x->signed_fits_bits(257)) { throw IntError{"invalid numeric literal"}; - } else if (x->signed_fits_bits(64)) { + } else if (x->signed_fits_bits(td::BigIntInfo::word_shift)) { wlist.push_back(Ref{true, std::bind(interpret_const, _1, x->to_long())}); } else { wlist.push_back(Ref{true, std::bind(interpret_big_const, _1, std::move(x))}); @@ -2465,6 +2543,7 @@ void init_words_common(Dictionary& d) { // char/string manipulation d.def_active_word("\"", interpret_quote_str); d.def_active_word("char ", interpret_char); + d.def_stack_word("(char) ", interpret_char_internal); d.def_ctx_word("emit ", interpret_emit); d.def_ctx_word("space ", std::bind(interpret_emit_const, _1, ' ')); d.def_ctx_word("cr ", std::bind(interpret_emit_const, _1, '\n')); @@ -2484,6 +2563,8 @@ void init_words_common(Dictionary& d) { d.def_stack_word("-trailing0 ", std::bind(interpret_str_remove_trailing_int, _1, '0')); d.def_stack_word("$len ", interpret_str_len); d.def_stack_word("Blen ", interpret_bytes_len); + d.def_stack_word("$Len ", interpret_utf8_str_len); + d.def_stack_word("$Split ", interpret_utf8_str_split); d.def_ctx_word("Bx. ", std::bind(interpret_bytes_hex_print_raw, _1, true)); d.def_stack_word("B>X ", std::bind(interpret_bytes_to_hex, _1, true)); d.def_stack_word("B>x ", std::bind(interpret_bytes_to_hex, _1, false)); @@ -2572,6 +2653,8 @@ void init_words_common(Dictionary& d) { d.def_ctx_word("file-exists? ", interpret_file_exists); // custom & crypto d.def_ctx_word("now ", interpret_now); + d.def_stack_word("getenv ", interpret_getenv); + d.def_stack_word("getenv? ", interpret_getenv_exists); d.def_stack_word("newkeypair ", interpret_new_keypair); d.def_stack_word("priv>pub ", interpret_priv_key_to_pub); d.def_stack_word("ed25519_sign ", interpret_ed25519_sign); @@ -2696,6 +2779,8 @@ void init_words_vm(Dictionary& d) { d.def_ctx_word("gasrunvmdict ", std::bind(interpret_run_vm_dict, _1, true)); d.def_ctx_word("runvm ", std::bind(interpret_run_vm, _1, false)); d.def_ctx_word("gasrunvm ", std::bind(interpret_run_vm, _1, true)); + d.def_ctx_word("runvmctx ", std::bind(interpret_run_vm_c7, _1, false)); + d.def_ctx_word("gasrunvmctx ", std::bind(interpret_run_vm_c7, _1, true)); d.def_ctx_word("dbrunvm ", interpret_db_run_vm); d.def_ctx_word("dbrunvm-parallel ", interpret_db_run_vm_parallel); } diff --git a/submodules/ton/tonlib-src/crypto/func/abscode.cpp b/submodules/ton/tonlib-src/crypto/func/abscode.cpp index 1bc4f0d9db..8ff204f13c 100644 --- a/submodules/ton/tonlib-src/crypto/func/abscode.cpp +++ b/submodules/ton/tonlib-src/crypto/func/abscode.cpp @@ -205,6 +205,9 @@ void VarDescr::clear_value() { } void VarDescrList::show(std::ostream& os) const { + if (unreachable) { + os << " "; + } os << "["; for (const auto& v : list) { os << ' ' << v; diff --git a/submodules/ton/tonlib-src/crypto/func/analyzer.cpp b/submodules/ton/tonlib-src/crypto/func/analyzer.cpp index 4d2e790298..a80bc74e23 100644 --- a/submodules/ton/tonlib-src/crypto/func/analyzer.cpp +++ b/submodules/ton/tonlib-src/crypto/func/analyzer.cpp @@ -272,6 +272,12 @@ VarDescrList& VarDescrList::operator+=(const VarDescrList& y) { } VarDescrList VarDescrList::operator|(const VarDescrList& y) const { + if (y.unreachable) { + return *this; + } + if (unreachable) { + return y; + } VarDescrList res; auto it1 = list.cbegin(); auto it2 = y.list.cbegin(); @@ -289,7 +295,11 @@ VarDescrList VarDescrList::operator|(const VarDescrList& y) const { } VarDescrList& VarDescrList::operator|=(const VarDescrList& y) { - return *this = *this | y; + if (y.unreachable) { + return *this; + } else { + return *this = *this | y; + } } VarDescrList& VarDescrList::operator&=(const VarDescrList& values) { @@ -299,16 +309,22 @@ VarDescrList& VarDescrList::operator&=(const VarDescrList& values) { *item &= vd; } } + unreachable |= values.unreachable; return *this; } VarDescrList& VarDescrList::import_values(const VarDescrList& values) { - for (const VarDescr& vd : values.list) { - VarDescr* item = operator[](vd.idx); - if (item) { - item->set_value(vd); + if (values.unreachable) { + set_unreachable(); + } else + for (auto& vd : list) { + auto new_vd = values[vd.idx]; + if (new_vd) { + vd.set_value(*new_vd); + } else { + vd.clear_value(); + } } - } return *this; } @@ -658,8 +674,11 @@ void Op::prepare_args(VarDescrList values) { const VarDescr* val = values[right[i]]; if (val) { args[i].set_value(*val); - args[i].clear_unused(); + // args[i].clear_unused(); + } else { + args[i].clear_value(); } + args[i].clear_unused(); } } @@ -670,7 +689,7 @@ VarDescrList Op::fwd_analyze(VarDescrList values) { case _Import: break; case _Return: - values.list.clear(); + values.set_unreachable(); break; case _IntConst: { values.add_newval(left[0]).set_const(int_const); diff --git a/submodules/ton/tonlib-src/crypto/func/asmops.cpp b/submodules/ton/tonlib-src/crypto/func/asmops.cpp index afc164715c..df4443a4d2 100644 --- a/submodules/ton/tonlib-src/crypto/func/asmops.cpp +++ b/submodules/ton/tonlib-src/crypto/func/asmops.cpp @@ -193,21 +193,21 @@ void AsmOp::out(std::ostream& os) const { os << (b ? "SWAP" : "NOP"); break; } - os << "s" << a << " s" << b << " XCHG"; + os << SReg(a) << ' ' << SReg(b) << " XCHG"; break; case a_push: if (!(a & -2)) { os << (a ? "OVER" : "DUP"); break; } - os << "s" << a << " PUSH"; + os << SReg(a) << " PUSH"; break; case a_pop: if (!(a & -2)) { os << (a ? "NIP" : "DROP"); break; } - os << "s" << a << " POP"; + os << SReg(a) << " POP"; break; default: throw src::Fatal{"unknown assembler operation"}; diff --git a/submodules/ton/tonlib-src/crypto/func/builtins.cpp b/submodules/ton/tonlib-src/crypto/func/builtins.cpp index 5010a2564b..dd156f24c6 100644 --- a/submodules/ton/tonlib-src/crypto/func/builtins.cpp +++ b/submodules/ton/tonlib-src/crypto/func/builtins.cpp @@ -50,15 +50,15 @@ void define_builtin_func(std::string name, TypeExpr* func_type, const T& func, b } template -void define_builtin_func_x(std::string name, TypeExpr* func_type, const T& func, std::initializer_list arg_order, - std::initializer_list ret_order = {}, bool impure = false) { +void define_builtin_func(std::string name, TypeExpr* func_type, const T& func, std::initializer_list arg_order, + std::initializer_list ret_order = {}, bool impure = false) { SymDef* def = predefine_builtin_func(name, func_type); def->value = new SymValAsmFunc{func_type, func, arg_order, ret_order, impure}; } -void define_builtin_func_x(std::string name, TypeExpr* func_type, const AsmOp& macro, - std::initializer_list arg_order, std::initializer_list ret_order = {}, - bool impure = false) { +void define_builtin_func(std::string name, TypeExpr* func_type, const AsmOp& macro, + std::initializer_list arg_order, std::initializer_list ret_order = {}, + bool impure = false) { SymDef* def = predefine_builtin_func(name, func_type); def->value = new SymValAsmFunc{func_type, make_simple_compile(macro), arg_order, ret_order, impure}; } @@ -429,10 +429,14 @@ AsmOp compile_mul(std::vector& res, std::vector& args) { } return exec_arg_op("MULCONST", y.int_const, 1); } - if (k >= 0) { + if (k > 0) { y.unused(); return exec_arg_op("LSHIFT#", k, 1); } + if (k == 0) { + y.unused(); + return AsmOp::Nop(); + } } if (x.is_int_const()) { int k = is_pos_pow2(x.int_const); @@ -451,10 +455,14 @@ AsmOp compile_mul(std::vector& res, std::vector& args) { } return exec_arg_op("MULCONST", x.int_const, 1); } - if (k >= 0) { + if (k > 0) { x.unused(); return exec_arg_op("LSHIFT#", k, 1); } + if (k == 0) { + x.unused(); + return AsmOp::Nop(); + } } return exec_op("MUL", 2); } @@ -668,6 +676,7 @@ AsmOp compile_cmp_int(std::vector& res, std::vector& args, i return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v != 0); } int v = compute_compare(x, y, mode); + // std::cerr << "compute_compare(" << x << ", " << y << ", " << mode << ") = " << v << std::endl; assert(v); if (!(v & (v - 1))) { r.set_const(v - (v >> 2) - 2); @@ -685,6 +694,7 @@ AsmOp compile_cmp_int(std::vector& res, std::vector& args, i if (v & 4) { r.val &= VarDescr::ConstOne; } + // std::cerr << "result: " << r << std::endl; static const char* cmp_int_names[] = {"", "GTINT", "EQINT", "GTINT", "LESSINT", "NEQINT", "LESSINT"}; static const char* cmp_names[] = {"", "GREATER", "EQUAL", "GEQ", "LESS", "NEQ", "LEQ", "CMP"}; static int cmp_int_delta[] = {0, 0, 0, -1, 0, 0, 1}; @@ -846,10 +856,7 @@ void define_builtins() { auto X = TypeExpr::new_var(); auto Y = TypeExpr::new_var(); auto Z = TypeExpr::new_var(); - auto T = TypeExpr::new_var(); auto XY = TypeExpr::new_tensor({X, Y}); - auto XYZ = TypeExpr::new_tensor({X, Y, Z}); - auto XYZT = TypeExpr::new_tensor({X, Y, Z, T}); auto arith_bin_op = TypeExpr::new_map(Int2, Int); auto arith_un_op = TypeExpr::new_map(Int, Int); auto impure_bin_op = TypeExpr::new_map(Int2, Unit); @@ -867,16 +874,20 @@ void define_builtins() { define_builtin_func("-_", arith_un_op, compile_negate); define_builtin_func("_*_", arith_bin_op, compile_mul); define_builtin_func("_/_", arith_bin_op, std::bind(compile_div, _1, _2, -1)); - define_builtin_func("_/~_", arith_bin_op, std::bind(compile_div, _1, _2, 0)); - define_builtin_func("_/^_", arith_bin_op, std::bind(compile_div, _1, _2, 1)); + define_builtin_func("_~/_", arith_bin_op, std::bind(compile_div, _1, _2, 0)); + define_builtin_func("_^/_", arith_bin_op, std::bind(compile_div, _1, _2, 1)); define_builtin_func("_%_", arith_bin_op, std::bind(compile_mod, _1, _2, -1)); - define_builtin_func("_%~_", arith_bin_op, std::bind(compile_mod, _1, _2, 0)); - define_builtin_func("_%^_", arith_bin_op, std::bind(compile_mod, _1, _2, -1)); + define_builtin_func("_~%_", arith_bin_op, std::bind(compile_mod, _1, _2, 0)); + define_builtin_func("_^%_", arith_bin_op, std::bind(compile_mod, _1, _2, 1)); define_builtin_func("_/%_", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2)); + define_builtin_func("divmod", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2)); + define_builtin_func("~divmod", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2)); + define_builtin_func("moddiv", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2), {}, {1, 0}); + define_builtin_func("~moddiv", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2), {}, {1, 0}); define_builtin_func("_<<_", arith_bin_op, compile_lshift); define_builtin_func("_>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, -1)); - define_builtin_func("_>>~_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0)); - define_builtin_func("_>>^_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1)); + define_builtin_func("_~>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0)); + define_builtin_func("_^>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1)); define_builtin_func("_&_", arith_bin_op, AsmOp::Custom("AND", 2)); define_builtin_func("_|_", arith_bin_op, AsmOp::Custom("OR", 2)); define_builtin_func("_^_", arith_bin_op, AsmOp::Custom("XOR", 2)); @@ -885,15 +896,15 @@ void define_builtins() { define_builtin_func("^_-=_", arith_bin_op, compile_sub); define_builtin_func("^_*=_", arith_bin_op, compile_mul); define_builtin_func("^_/=_", arith_bin_op, std::bind(compile_div, _1, _2, -1)); - define_builtin_func("^_/~=_", arith_bin_op, std::bind(compile_div, _1, _2, 0)); - define_builtin_func("^_/^=_", arith_bin_op, std::bind(compile_div, _1, _2, 1)); + define_builtin_func("^_~/=_", arith_bin_op, std::bind(compile_div, _1, _2, 0)); + define_builtin_func("^_^/=_", arith_bin_op, std::bind(compile_div, _1, _2, 1)); define_builtin_func("^_%=_", arith_bin_op, std::bind(compile_mod, _1, _2, -1)); - define_builtin_func("^_%~=_", arith_bin_op, std::bind(compile_mod, _1, _2, 0)); - define_builtin_func("^_%^=_", arith_bin_op, std::bind(compile_mod, _1, _2, 1)); + define_builtin_func("^_~%=_", arith_bin_op, std::bind(compile_mod, _1, _2, 0)); + define_builtin_func("^_^%=_", arith_bin_op, std::bind(compile_mod, _1, _2, 1)); define_builtin_func("^_<<=_", arith_bin_op, compile_lshift); define_builtin_func("^_>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, -1)); - define_builtin_func("^_>>~=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0)); - define_builtin_func("^_>>^=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1)); + define_builtin_func("^_~>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0)); + define_builtin_func("^_^>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1)); define_builtin_func("^_&=_", arith_bin_op, AsmOp::Custom("AND", 2)); define_builtin_func("^_|=_", arith_bin_op, AsmOp::Custom("OR", 2)); define_builtin_func("^_^=_", arith_bin_op, AsmOp::Custom("XOR", 2)); @@ -911,43 +922,24 @@ void define_builtins() { define_builtin_func("false", Int, /* AsmOp::Const("FALSE") */ std::bind(compile_bool_const, _1, _2, false)); // define_builtin_func("null", Null, AsmOp::Const("PUSHNULL")); define_builtin_func("nil", Tuple, AsmOp::Const("PUSHNULL")); + define_builtin_func("Nil", Tuple, AsmOp::Const("NIL")); define_builtin_func("null?", TypeExpr::new_forall({X}, TypeExpr::new_map(X, Int)), compile_is_null); - define_builtin_func("cons", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor(X, Tuple), Tuple)), - AsmOp::Custom("CONS", 2, 1)); - define_builtin_func("uncons", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, TypeExpr::new_tensor(X, Tuple))), - AsmOp::Custom("UNCONS", 1, 2)); - define_builtin_func_x("list_next", - TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, TypeExpr::new_tensor(Tuple, X))), - AsmOp::Custom("UNCONS", 1, 2), {}, {1, 0}); - define_builtin_func("car", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, X)), AsmOp::Custom("CAR", 1, 1)); - define_builtin_func("cdr", TypeExpr::new_map(Tuple, Tuple), AsmOp::Custom("CDR", 1, 1)); - define_builtin_func("pair", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(XY, Tuple)), AsmOp::Custom("PAIR", 2, 1)); - define_builtin_func("unpair", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(Tuple, XY)), - AsmOp::Custom("UNPAIR", 1, 2)); - define_builtin_func("triple", TypeExpr::new_forall({X, Y, Z}, TypeExpr::new_map(XYZ, Tuple)), - AsmOp::Custom("TRIPLE", 3, 1)); - define_builtin_func("untriple", TypeExpr::new_forall({X, Y, Z}, TypeExpr::new_map(Tuple, XYZ)), - AsmOp::Custom("UNTRIPLE", 1, 3)); - define_builtin_func("tuple4", TypeExpr::new_forall({X, Y, Z, T}, TypeExpr::new_map(XYZT, Tuple)), - AsmOp::Custom("4 TUPLE", 4, 1)); - define_builtin_func("untuple4", TypeExpr::new_forall({X, Y, Z, T}, TypeExpr::new_map(Tuple, XYZT)), - AsmOp::Custom("4 UNTUPLE", 1, 4)); define_builtin_func("throw", impure_un_op, compile_throw, true); define_builtin_func("throw_if", impure_bin_op, std::bind(compile_cond_throw, _1, _2, true), true); define_builtin_func("throw_unless", impure_bin_op, std::bind(compile_cond_throw, _1, _2, false), true); - define_builtin_func_x("load_int", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, true), {}, {1, 0}); - define_builtin_func_x("load_uint", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, false), {}, {1, 0}); + define_builtin_func("load_int", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, true), {}, {1, 0}); + define_builtin_func("load_uint", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, false), {}, {1, 0}); define_builtin_func("preload_int", prefetch_int_op, std::bind(compile_fetch_int, _1, _2, false, true)); define_builtin_func("preload_uint", prefetch_int_op, std::bind(compile_fetch_int, _1, _2, false, false)); - define_builtin_func_x("store_int", store_int_op, std::bind(compile_store_int, _1, _2, true), {1, 0, 2}); - define_builtin_func_x("store_uint", store_int_op, std::bind(compile_store_int, _1, _2, false), {1, 0, 2}); - define_builtin_func_x("~store_int", store_int_method, std::bind(compile_store_int, _1, _2, true), {1, 0, 2}); - define_builtin_func_x("~store_uint", store_int_method, std::bind(compile_store_int, _1, _2, false), {1, 0, 2}); - define_builtin_func_x("load_bits", fetch_slice_op, std::bind(compile_fetch_slice, _1, _2, true), {}, {1, 0}); + define_builtin_func("store_int", store_int_op, std::bind(compile_store_int, _1, _2, true), {1, 0, 2}); + define_builtin_func("store_uint", store_int_op, std::bind(compile_store_int, _1, _2, false), {1, 0, 2}); + define_builtin_func("~store_int", store_int_method, std::bind(compile_store_int, _1, _2, true), {1, 0, 2}); + define_builtin_func("~store_uint", store_int_method, std::bind(compile_store_int, _1, _2, false), {1, 0, 2}); + define_builtin_func("load_bits", fetch_slice_op, std::bind(compile_fetch_slice, _1, _2, true), {}, {1, 0}); define_builtin_func("preload_bits", prefetch_slice_op, std::bind(compile_fetch_slice, _1, _2, false)); define_builtin_func("int_at", TypeExpr::new_map(TupleInt, Int), compile_tuple_at); define_builtin_func("cell_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at); - define_builtin_func("slice_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at); + define_builtin_func("slice_at", TypeExpr::new_map(TupleInt, Slice), compile_tuple_at); define_builtin_func("tuple_at", TypeExpr::new_map(TupleInt, Tuple), compile_tuple_at); define_builtin_func("at", TypeExpr::new_forall({X}, TypeExpr::new_map(TupleInt, X)), compile_tuple_at); define_builtin_func("touch", TypeExpr::new_forall({X}, TypeExpr::new_map(X, X)), AsmOp::Nop()); @@ -960,13 +952,12 @@ void define_builtins() { AsmOp::Custom("s0 DUMP", 1, 1)); define_builtin_func("run_method0", TypeExpr::new_map(Int, Unit), [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true); - define_builtin_func_x("run_method1", - TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)), - [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true); - define_builtin_func_x( + define_builtin_func("run_method1", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)), + [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true); + define_builtin_func( "run_method2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y}), Unit)), [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 2, false); }, {1, 2, 0}, {}, true); - define_builtin_func_x( + define_builtin_func( "run_method3", TypeExpr::new_forall({X, Y, Z}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y, Z}), Unit)), [](auto a, auto b, auto c) { return compile_run_method(a, b, c, 3, false); }, {1, 2, 3, 0}, {}, true); } diff --git a/submodules/ton/tonlib-src/crypto/func/codegen.cpp b/submodules/ton/tonlib-src/crypto/func/codegen.cpp index 7e0d873ff6..70ae929df3 100644 --- a/submodules/ton/tonlib-src/crypto/func/codegen.cpp +++ b/submodules/ton/tonlib-src/crypto/func/codegen.cpp @@ -308,7 +308,7 @@ bool Op::generate_code_step(Stack& stack) { func->compile(stack.o, res, args); // compile res := f (args) } else { std::string name = sym::symbols.get_name(fun_ref->sym_idx); - stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size()); + stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size()); } stack.push_new_var(left[0]); return true; @@ -395,7 +395,7 @@ bool Op::generate_code_step(Stack& stack) { assert(stack.s[k + i].first == right1[i]); } if (cl == _CallInd) { - stack.o << exec_arg_op("CALLARGS", (int)right.size() - 1, -1, (int)right.size() - 1); + stack.o << exec_arg_op("CALLARGS", (int)right.size() - 1, (int)right.size(), (int)left.size()); } else { auto func = dynamic_cast(fun_ref->value); if (func) { @@ -406,8 +406,11 @@ bool Op::generate_code_step(Stack& stack) { } func->compile(stack.o, res, args); // compile res := f (args) } else { + auto fv = dynamic_cast(fun_ref->value); std::string name = sym::symbols.get_name(fun_ref->sym_idx); - stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size()); + bool is_inline = (fv && (fv->flags & 3)); + stack.o << AsmOp::Custom(name + (is_inline ? " INLINECALLDICT" : " CALLDICT"), (int)right.size(), + (int)left.size()); } } stack.s.resize(k); @@ -421,6 +424,11 @@ bool Op::generate_code_step(Stack& stack) { if (block0->is_empty() && block1->is_empty()) { return true; } + if (!next->noreturn() && (block0->noreturn() != block1->noreturn())) { + // simple fix of unbalanced returns in if/else branches + // (to be replaced with a finer condition working in loop bodies) + throw src::ParseError{where, "`if` and `else` branches should both return or both not return"}; + } var_idx_t x = left[0]; stack.rearrange_top(x, var_info[x] && var_info[x]->is_last()); assert(stack[0] == x); @@ -548,7 +556,7 @@ bool Op::generate_code_step(Stack& stack) { stack.opt_show(); stack.s.pop_back(); stack.modified(); - if (!next->is_empty()) { + if (true || !next->is_empty()) { stack.o << "REPEAT:<{"; stack.o.indent(); stack.forget_const(); @@ -596,7 +604,7 @@ bool Op::generate_code_step(Stack& stack) { case _Until: { // stack.drop_vars_except(block0->var_info); // stack.opt_show(); - if (!next->is_empty()) { + if (true || !next->is_empty()) { stack.o << "UNTIL:<{"; stack.o.indent(); stack.forget_const(); @@ -627,7 +635,7 @@ bool Op::generate_code_step(Stack& stack) { stack.drop_vars_except(block0->var_info); stack.opt_show(); StackLayout layout1 = stack.vars(); - bool next_empty = next->is_empty(); + bool next_empty = false && next->is_empty(); stack.o << "WHILE:<{"; stack.o.indent(); stack.forget_const(); diff --git a/submodules/ton/tonlib-src/crypto/func/func.cpp b/submodules/ton/tonlib-src/crypto/func/func.cpp index 223e6fcf95..2b98c332bd 100644 --- a/submodules/ton/tonlib-src/crypto/func/func.cpp +++ b/submodules/ton/tonlib-src/crypto/func/func.cpp @@ -60,21 +60,36 @@ void generate_output_func(SymDef* func_sym) { code.print(std::cerr, 9); } code.simplify_var_types(); - // std::cerr << "after simplify_var_types: \n"; code.print(std::cerr, 0); + if (verbosity >= 5) { + std::cerr << "after simplify_var_types: \n"; + code.print(std::cerr, 0); + } code.prune_unreachable_code(); - // std::cerr << "after prune_unreachable: \n"; code.print(std::cerr, 0); + if (verbosity >= 5) { + std::cerr << "after prune_unreachable: \n"; + code.print(std::cerr, 0); + } code.split_vars(true); - // std::cerr << "after split_vars: \n"; code.print(std::cerr, 0); + if (verbosity >= 5) { + std::cerr << "after split_vars: \n"; + code.print(std::cerr, 0); + } for (int i = 0; i < 8; i++) { code.compute_used_code_vars(); - if (verbosity >= 5) { + if (verbosity >= 4) { std::cerr << "after compute_used_vars: \n"; code.print(std::cerr, 6); } code.fwd_analyze(); - // std::cerr << "after fwd_analyze: \n"; code.print(std::cerr, 6); + if (verbosity >= 5) { + std::cerr << "after fwd_analyze: \n"; + code.print(std::cerr, 6); + } code.prune_unreachable_code(); - // std::cerr << "after prune_unreachable: \n"; code.print(std::cerr, 6); + if (verbosity >= 5) { + std::cerr << "after prune_unreachable: \n"; + code.print(std::cerr, 6); + } } code.mark_noreturn(); if (verbosity >= 3) { @@ -83,7 +98,8 @@ void generate_output_func(SymDef* func_sym) { if (verbosity >= 2) { std::cerr << "\n---------- resulting code for " << name << " -------------\n"; } - *outs << std::string(indent * 2, ' ') << name << " PROC:<{\n"; + bool inline_ref = (func_val->flags & 2); + *outs << std::string(indent * 2, ' ') << name << " PROC" << (inline_ref ? "REF" : "") << ":<{\n"; code.generate_code( *outs, (stack_layout_comments ? Stack::_StkCmt | Stack::_CptStkCmt : 0) | (opt_level < 2 ? Stack::_DisableOpt : 0), diff --git a/submodules/ton/tonlib-src/crypto/func/func.h b/submodules/ton/tonlib-src/crypto/func/func.h index 8fc881c88b..d1481299b8 100644 --- a/submodules/ton/tonlib-src/crypto/func/func.h +++ b/submodules/ton/tonlib-src/crypto/func/func.h @@ -67,6 +67,8 @@ enum Keyword { _RshiftC, _DivR, _DivC, + _ModR, + _ModC, _DivMod, _PlusLet, _MinusLet, @@ -75,10 +77,15 @@ enum Keyword { _DivRLet, _DivCLet, _ModLet, + _ModRLet, + _ModCLet, _LshiftLet, _RshiftLet, _RshiftRLet, _RshiftCLet, + _AndLet, + _OrLet, + _XorLet, _Int, _Cell, _Slice, @@ -87,9 +94,12 @@ enum Keyword { _Tuple, _Type, _Mapsto, + _Forall, _Asm, _Impure, _Extern, + _Inline, + _InlineRef, _MethodId, _Operator, _Infix, @@ -123,7 +133,7 @@ class IdSc { */ struct TypeExpr { - enum te_type { te_Unknown, te_Indirect, te_Atomic, te_Tensor, te_Map, te_Type, te_ForAll } constr; + enum te_type { te_Unknown, te_Var, te_Indirect, te_Atomic, te_Tensor, te_Map, te_Type, te_ForAll } constr; enum { _Int = Keyword::_Int, _Cell = Keyword::_Cell, @@ -168,6 +178,9 @@ struct TypeExpr { bool is_int() const { return is_atomic(_Int); } + bool is_var() const { + return constr == te_Var; + } bool has_fixed_width() const { return minw == maxw; } @@ -210,7 +223,10 @@ struct TypeExpr { return new_tensor({te1, te2, te3}); } static TypeExpr* new_var() { - return new TypeExpr{te_Unknown, --type_vars, 1}; + return new TypeExpr{te_Var, --type_vars, 1}; + } + static TypeExpr* new_var(int idx) { + return new TypeExpr{te_Var, idx, 1}; } static TypeExpr* new_forall(std::vector list, TypeExpr* body) { return new TypeExpr{te_ForAll, body, std::move(list)}; @@ -392,6 +408,7 @@ inline std::ostream& operator<<(std::ostream& os, const VarDescr& vd) { struct VarDescrList { std::vector list; + bool unreachable{false}; VarDescrList() : list() { } VarDescrList(const std::vector& _list) : list(_list) { @@ -425,6 +442,10 @@ struct VarDescrList { VarDescrList operator|(const VarDescrList& y) const; VarDescrList& operator|=(const VarDescrList& values); void show(std::ostream& os) const; + void set_unreachable() { + list.clear(); + unreachable = true; + } }; inline std::ostream& operator<<(std::ostream& os, const VarDescrList& values) { @@ -632,6 +653,9 @@ struct CodeBlob { } bool import_params(FormalArgList arg_list); var_idx_t create_var(int cls, TypeExpr* var_type = 0, SymDef* sym = 0, const SrcLocation* loc = 0); + var_idx_t create_tmp_var(TypeExpr* var_type = 0, const SrcLocation* loc = 0) { + return create_var(TmpVar::_Tmp, var_type, nullptr, loc); + } int split_vars(bool strict = false); bool compute_used_code_vars(); bool compute_used_code_vars(std::unique_ptr& ops, const VarDescrList& var_info, bool edit) const; @@ -670,8 +694,9 @@ struct SymVal : sym::SymValBase { TypeExpr* sym_type; td::RefInt256 method_id; bool impure; + short flags; // +1 = inline, +2 = inline_ref SymVal(int _type, int _idx, TypeExpr* _stype = nullptr, bool _impure = false) - : sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure) { + : sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure), flags(0) { } ~SymVal() override = default; TypeExpr* get_type() const { @@ -710,6 +735,16 @@ struct SymValCodeFunc : SymValFunc { } }; +struct SymValType : sym::SymValBase { + TypeExpr* sym_type; + SymValType(int _type, int _idx, TypeExpr* _stype = nullptr) : sym::SymValBase(_type, _idx), sym_type(_stype) { + } + ~SymValType() override = default; + TypeExpr* get_type() const { + return sym_type; + } +}; + extern int glob_func_cnt, undef_func_cnt; extern std::vector glob_func; @@ -802,6 +837,10 @@ struct Expr { int define_new_vars(CodeBlob& code); int predefine_vars(); std::vector pre_compile(CodeBlob& code) const; + var_idx_t new_tmp(CodeBlob& code) const; + std::vector new_tmp_vect(CodeBlob& code) const { + return {new_tmp(code)}; + } }; /* diff --git a/submodules/ton/tonlib-src/crypto/func/gen-abscode.cpp b/submodules/ton/tonlib-src/crypto/func/gen-abscode.cpp index ab2efed541..a3cc52042d 100644 --- a/submodules/ton/tonlib-src/crypto/func/gen-abscode.cpp +++ b/submodules/ton/tonlib-src/crypto/func/gen-abscode.cpp @@ -212,6 +212,10 @@ int Expr::predefine_vars() { return 0; } +var_idx_t Expr::new_tmp(CodeBlob& code) const { + return code.create_tmp_var(e_type, &here); +} + std::vector Expr::pre_compile(CodeBlob& code) const { switch (cls) { case _Tuple: { @@ -241,8 +245,7 @@ std::vector Expr::pre_compile(CodeBlob& code) const { res.insert(res.end(), add.cbegin(), add.cend()); } } - var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - std::vector rvect{rv}; + auto rvect = new_tmp_vect(code); auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), sym); if (flags & _IsImpure) { op.flags |= Op::_Impure; @@ -256,57 +259,52 @@ std::vector Expr::pre_compile(CodeBlob& code) const { return {val}; case _VarApply: if (args[0]->cls == _Glob) { - std::vector res = args[1]->pre_compile(code); - var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - std::vector rvect{rv}; + auto res = args[1]->pre_compile(code); + auto rvect = new_tmp_vect(code); auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), args[0]->sym); if (args[0]->flags & _IsImpure) { op.flags |= Op::_Impure; } return rvect; } else { - std::vector res = args[1]->pre_compile(code); - std::vector tfunc = args[0]->pre_compile(code); + auto res = args[1]->pre_compile(code); + auto tfunc = args[0]->pre_compile(code); if (tfunc.size() != 1) { throw src::Fatal{"stack tuple used as a function"}; } res.push_back(tfunc[0]); - var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - std::vector rvect{rv}; + auto rvect = new_tmp_vect(code); code.emplace_back(here, Op::_CallInd, rvect, std::move(res)); return rvect; } case _Const: { - var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - std::vector rvect{rv}; + auto rvect = new_tmp_vect(code); code.emplace_back(here, Op::_IntConst, rvect, intval); return rvect; } case _Glob: { - var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - std::vector rvect{rv}; + auto rvect = new_tmp_vect(code); code.emplace_back(here, Op::_GlobVar, rvect, std::vector{}, sym); return rvect; } case _Letop: { - std::vector right = args[1]->pre_compile(code); - std::vector left = args[0]->pre_compile(code); - code.emplace_back(here, Op::_Let, left, std::move(right)); - return left; + auto right = args[1]->pre_compile(code); + auto left = args[0]->pre_compile(code); + code.emplace_back(here, Op::_Let, std::move(left), right); + return right; } case _LetFirst: { - var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - std::vector right = args[1]->pre_compile(code); - std::vector left = args[0]->pre_compile(code); - left.push_back(rv); + auto rvect = new_tmp_vect(code); + auto right = args[1]->pre_compile(code); + auto left = args[0]->pre_compile(code); + left.push_back(rvect[0]); code.emplace_back(here, Op::_Let, std::move(left), std::move(right)); - return std::vector{rv}; + return rvect; } case _CondExpr: { auto cond = args[0]->pre_compile(code); assert(cond.size() == 1); - var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here); - std::vector rvect{rv}; + auto rvect = new_tmp_vect(code); Op& if_op = code.emplace_back(here, Op::_If, cond); code.push_set_cur(if_op.block0); code.emplace_back(here, Op::_Let, rvect, args[1]->pre_compile(code)); diff --git a/submodules/ton/tonlib-src/crypto/func/keywords.cpp b/submodules/ton/tonlib-src/crypto/func/keywords.cpp index bab30d32a6..c640f4fe71 100644 --- a/submodules/ton/tonlib-src/crypto/func/keywords.cpp +++ b/submodules/ton/tonlib-src/crypto/func/keywords.cpp @@ -54,6 +54,7 @@ void define_keywords() { .add_kw_char('>') .add_kw_char('&') .add_kw_char('|') + .add_kw_char('^') .add_kw_char('~'); using Kw = funC::Keyword; @@ -64,22 +65,29 @@ void define_keywords() { .add_keyword("<=>", Kw::_Spaceship) .add_keyword("<<", Kw::_Lshift) .add_keyword(">>", Kw::_Rshift) - .add_keyword(">>~", Kw::_RshiftR) - .add_keyword(">>^", Kw::_RshiftC) - .add_keyword("/~", Kw::_DivR) - .add_keyword("/^", Kw::_DivC) + .add_keyword("~>>", Kw::_RshiftR) + .add_keyword("^>>", Kw::_RshiftC) + .add_keyword("~/", Kw::_DivR) + .add_keyword("^/", Kw::_DivC) + .add_keyword("~%", Kw::_ModR) + .add_keyword("^%", Kw::_ModC) .add_keyword("/%", Kw::_DivMod) .add_keyword("+=", Kw::_PlusLet) .add_keyword("-=", Kw::_MinusLet) .add_keyword("*=", Kw::_TimesLet) .add_keyword("/=", Kw::_DivLet) + .add_keyword("~/=", Kw::_DivRLet) + .add_keyword("^/=", Kw::_DivCLet) .add_keyword("%=", Kw::_ModLet) - .add_keyword("/~=", Kw::_DivRLet) - .add_keyword("/^=", Kw::_DivCLet) + .add_keyword("~%=", Kw::_ModRLet) + .add_keyword("^%=", Kw::_ModCLet) .add_keyword("<<=", Kw::_LshiftLet) .add_keyword(">>=", Kw::_RshiftLet) - .add_keyword(">>~=", Kw::_RshiftRLet) - .add_keyword(">>^=", Kw::_RshiftCLet); + .add_keyword("~>>=", Kw::_RshiftRLet) + .add_keyword("^>>=", Kw::_RshiftCLet) + .add_keyword("&=", Kw::_AndLet) + .add_keyword("|=", Kw::_OrLet) + .add_keyword("^=", Kw::_XorLet); sym::symbols.add_keyword("return", Kw::_Return) .add_keyword("var", Kw::_Var) @@ -100,11 +108,15 @@ void define_keywords() { .add_keyword("builder", Kw::_Builder) .add_keyword("cont", Kw::_Cont) .add_keyword("tuple", Kw::_Tuple) - .add_keyword("->", Kw::_Mapsto); + .add_keyword("type", Kw::_Type) + .add_keyword("->", Kw::_Mapsto) + .add_keyword("forall", Kw::_Forall); sym::symbols.add_keyword("extern", Kw::_Extern) .add_keyword("asm", Kw::_Asm) .add_keyword("impure", Kw::_Impure) + .add_keyword("inline", Kw::_Inline) + .add_keyword("inline_ref", Kw::_InlineRef) .add_keyword("method_id", Kw::_MethodId) .add_keyword("operator", Kw::_Operator) .add_keyword("infix", Kw::_Infix) diff --git a/submodules/ton/tonlib-src/crypto/func/parse-func.cpp b/submodules/ton/tonlib-src/crypto/func/parse-func.cpp index f605bd83ef..e04077918c 100644 --- a/submodules/ton/tonlib-src/crypto/func/parse-func.cpp +++ b/submodules/ton/tonlib-src/crypto/func/parse-func.cpp @@ -89,6 +89,15 @@ TypeExpr* parse_type1(Lexer& lex) { case '_': lex.next(); return TypeExpr::new_hole(); + case _Ident: { + auto sym = sym::lookup_symbol(lex.cur().val); + if (sym && dynamic_cast(sym->value)) { + auto val = dynamic_cast(sym->value); + lex.next(); + return val->get_type(); + } + lex.cur().error_at("`", "` is not a type identifier"); + } } lex.expect('('); if (lex.tp() == ')') { @@ -133,7 +142,14 @@ FormalArg parse_formal_arg(Lexer& lex, int fa_idx) { } else if (lex.tp() != _Ident) { arg_type = parse_type(lex); } else { - arg_type = TypeExpr::new_hole(); + auto sym = sym::lookup_symbol(lex.cur().val); + if (sym && dynamic_cast(sym->value)) { + auto val = dynamic_cast(sym->value); + lex.next(); + arg_type = val->get_type(); + } else { + arg_type = TypeExpr::new_hole(); + } } if (lex.tp() == '_' || lex.tp() == ',' || lex.tp() == ')') { if (lex.tp() == '_') { @@ -147,6 +163,9 @@ FormalArg parse_formal_arg(Lexer& lex, int fa_idx) { } loc = lex.cur().loc; SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc); + if (!new_sym_def) { + lex.cur().error_at("cannot define symbol `", "`"); + } if (new_sym_def->value) { lex.cur().error_at("redefined formal parameter `", "`"); } @@ -295,6 +314,15 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) { return res; } if (t == _Ident) { + auto sym = sym::lookup_symbol(lex.cur().val); + if (sym && dynamic_cast(sym->value)) { + auto val = dynamic_cast(sym->value); + Expr* res = new Expr{Expr::_Type, lex.cur().loc}; + res->flags = Expr::_IsType; + res->e_type = val->get_type(); + lex.next(); + return res; + } Expr* res = new Expr{Expr::_Var, lex.cur().loc}; if (nv) { res->val = ~lex.cur().val; @@ -302,14 +330,14 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) { res->flags = Expr::_IsLvalue | Expr::_IsNewVar; // std::cerr << "defined new variable " << lex.cur().str << " : " << res->e_type << std::endl; } else { - res->sym = sym::lookup_symbol(lex.cur().val); - if (!res->sym) { + if (!sym) { check_global_func(lex.cur()); - res->sym = sym::lookup_symbol(lex.cur().val); + sym = sym::lookup_symbol(lex.cur().val); } + res->sym = sym; SymVal* val = nullptr; - if (res->sym) { - val = dynamic_cast(res->sym->value); + if (sym) { + val = dynamic_cast(sym->value); } if (!val) { lex.cur().error_at("undefined identifier `", "`"); @@ -428,7 +456,6 @@ Expr* parse_expr80(Lexer& lex, CodeBlob& code, bool nv) { res->flags = Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0); res->deduce_type(lex.cur()); if (modify) { - // FIXME (use _LetFirst instead of _Letop) auto tmp = res; res = new Expr{Expr::_LetFirst, {obj->copy(), tmp}}; res->here = loc; @@ -464,7 +491,7 @@ Expr* parse_expr75(Lexer& lex, CodeBlob& code, bool nv) { Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) { Expr* res = parse_expr75(lex, code, nv); while (lex.tp() == '*' || lex.tp() == '/' || lex.tp() == '%' || lex.tp() == _DivMod || lex.tp() == _DivC || - lex.tp() == _DivR || lex.tp() == '&') { + lex.tp() == _DivR || lex.tp() == _ModC || lex.tp() == _ModR || lex.tp() == '&') { res->chk_rvalue(lex.cur()); int t = lex.tp(); sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_"); @@ -482,7 +509,7 @@ Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) { return res; } -// parse [-] E { (+ | - | `|` ) E } +// parse [-] E { (+ | - | `|` | ^) E } Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) { Expr* res; int t = lex.tp(); @@ -501,7 +528,7 @@ Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) { } else { res = parse_expr30(lex, code, nv); } - while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|') { + while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|' || lex.tp() == '^') { res->chk_rvalue(lex.cur()); t = lex.tp(); sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_"); @@ -587,7 +614,8 @@ Expr* parse_expr10(Lexer& lex, CodeBlob& code, bool nv) { auto x = parse_expr13(lex, code, nv); int t = lex.tp(); if (t == _PlusLet || t == _MinusLet || t == _TimesLet || t == _DivLet || t == _DivRLet || t == _DivCLet || - t == _ModLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || t == _RshiftRLet) { + t == _ModLet || t == _ModCLet || t == _ModRLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || + t == _RshiftRLet || t == _AndLet || t == _OrLet || t == _XorLet) { x->chk_lvalue(lex.cur()); x->chk_rvalue(lex.cur()); sym_idx_t name = symbols.lookup_add(std::string{"^_"} + lex.cur().str + "_"); @@ -960,9 +988,76 @@ SymValAsmFunc* parse_asm_func_body(Lexer& lex, TypeExpr* func_type, const Formal return res; } +std::vector parse_type_var_list(Lexer& lex) { + std::vector res; + lex.expect(_Forall); + int idx = 0; + while (true) { + if (lex.tp() == _Type) { + lex.next(); + } + if (lex.tp() != _Ident) { + throw src::ParseError{lex.cur().loc, "free type identifier expected"}; + } + auto loc = lex.cur().loc; + SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc); + if (new_sym_def->value) { + lex.cur().error_at("redefined type variable `", "`"); + } + auto var = TypeExpr::new_var(idx); + new_sym_def->value = new SymValType{SymVal::_Typename, idx++, var}; + res.push_back(var); + lex.next(); + if (lex.tp() != ',') { + break; + } + lex.next(); + } + lex.expect(_Mapsto); + return res; +} + +void type_var_usage(TypeExpr* expr, const std::vector& typevars, std::vector& used) { + if (expr->constr != TypeExpr::te_Var) { + for (auto arg : expr->args) { + type_var_usage(arg, typevars, used); + } + return; + } + for (std::size_t i = 0; i < typevars.size(); i++) { + if (typevars[i] == expr) { + used.at(i) = true; + return; + } + } + return; +} + +TypeExpr* compute_type_closure(TypeExpr* expr, const std::vector& typevars) { + if (typevars.empty()) { + return expr; + } + std::vector used(typevars.size(), false); + type_var_usage(expr, typevars, used); + std::vector used_vars; + for (std::size_t i = 0; i < typevars.size(); i++) { + if (used.at(i)) { + used_vars.push_back(typevars[i]); + } + } + if (!used_vars.empty()) { + expr = TypeExpr::new_forall(std::move(used_vars), expr); + } + return expr; +} + void parse_func_def(Lexer& lex) { SrcLocation loc{lex.cur().loc}; sym::open_scope(lex); + std::vector type_vars; + if (lex.tp() == _Forall) { + type_vars = parse_type_var_list(lex); + } auto ret_type = parse_type(lex); if (lex.tp() != _Ident) { throw src::ParseError{lex.cur().loc, "function name identifier expected"}; @@ -974,6 +1069,11 @@ void parse_func_def(Lexer& lex) { if (impure) { lex.next(); } + int f = 0; + if (lex.tp() == _Inline || lex.tp() == _InlineRef) { + f = (lex.tp() == _Inline) ? 1 : 2; + lex.next(); + } td::RefInt256 method_id; std::string method_name; if (lex.tp() == _MethodId) { @@ -1005,6 +1105,7 @@ void parse_func_def(Lexer& lex) { lex.expect('{', "function body block expected"); } TypeExpr* func_type = TypeExpr::new_map(extract_total_arg_type(arg_list), ret_type); + func_type = compute_type_closure(func_type, type_vars); if (verbosity >= 1) { std::cerr << "function " << func_name.str << " : " << func_type << std::endl; } @@ -1071,6 +1172,17 @@ void parse_func_def(Lexer& lex) { lex.cur().error("integer method identifier for `"s + func_name.str + "` changed to a different value"); } } + if (f) { + auto val = dynamic_cast(func_sym->value); + if (!val) { + lex.cur().error("cannot set unknown function `"s + func_name.str + "` as an inline"); + } + if (!(val->flags & 3)) { + val->flags = (short)(val->flags | f); + } else if ((val->flags & 3) != f) { + lex.cur().error("inline mode for `"s + func_name.str + "` changed with respect to a previous declaration"); + } + } if (verbosity >= 1) { std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl; } diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6.fc b/submodules/ton/tonlib-src/crypto/func/test/a6.fc index 06eeed9fe3..3a387aace1 100644 --- a/submodules/ton/tonlib-src/crypto/func/test/a6.fc +++ b/submodules/ton/tonlib-src/crypto/func/test/a6.fc @@ -59,20 +59,20 @@ operator _/%_ infix 20; return (x / y, x % y); } -} -{- -< type A, type B, type C > + +forall A, B, C -> (B, C, A) rot (A x, B y, C z) { return (y, z, x); } --} + int ataninv(int base, int q) { ;; computes base*atan(1/q) - base /~= q; + base ~/= q; q *= - q; int sum = 0; int n = 1; do { - sum += base /~ n; - base /~= q; + sum += base ~/ n; + base ~/= q; n += 2; } until base == 0; return sum; @@ -81,5 +81,9 @@ int ataninv(int base, int q) { ;; computes base*atan(1/q) int calc_pi() { int base = 64; repeat (70) { base *= 10; } - return (ataninv(base << 2, 5) - ataninv(base, 239)) >>~ 4; + return (ataninv(base << 2, 5) - ataninv(base, 239)) ~>> 4; +} + +int main() { + return calc_pi(); } diff --git a/submodules/ton/tonlib-src/crypto/func/test/a6_3.fc b/submodules/ton/tonlib-src/crypto/func/test/a6_3.fc new file mode 100644 index 0000000000..7c8ff3af2e --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/a6_3.fc @@ -0,0 +1,22 @@ +forall A, B, C -> +(B, C, A) rot(A x, B y, C z) { + return (y, z, x); +} + +forall A, B, C -> +_ rot2(A x, B y, C z) { + return rot(rot(x, y, z)); +} + +_ test() { + return rot2(2, 3, 9); +} + +_ test2(cell x, slice y, tuple z) { + return rot2(x, y, z); +} + +forall A -> +_ test3(cell x, A y, int z) { + return rot2(x, y, z); +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/b3.fc b/submodules/ton/tonlib-src/crypto/func/test/b3.fc new file mode 100644 index 0000000000..0e1e403474 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/b3.fc @@ -0,0 +1,20 @@ +;; inline test +_ unpack() inline { + var ds = get_data().begin_parse(); + var res = (ds~load_uint(8), ds~load_int(32), ds~load_int(32)); + return res; +} + +() pack(a, x, y) impure inline_ref { + set_data(begin_cell() + .store_uint(a, 8) + .store_int(x, 32) + .store_int(y, 32) + .end_cell()); +} + +() main() impure { + var (a, x, y) = unpack(); + x += y; + pack(a, x, y); +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w1.fc b/submodules/ton/tonlib-src/crypto/func/test/w1.fc new file mode 100644 index 0000000000..6efd4f3e19 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/w1.fc @@ -0,0 +1,9 @@ +(int, int) nested_if(int id) method_id { + dump_stack(); + if (id > 0) { + if (id > 10) { + return (2 * id, 3 * id); + } + } + return (5, 6); +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w2.fc b/submodules/ton/tonlib-src/crypto/func/test/w2.fc new file mode 100644 index 0000000000..3bbcd415ab --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/w2.fc @@ -0,0 +1,14 @@ +_ f(cs) { + return (cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), + cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), + cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), + cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), + cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8)); +} + +_ main(cs) { + var (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, + x11, x12, x13, x14, x15, x16, x17, x18, x19) = f(cs); + return x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19; +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w3.fc b/submodules/ton/tonlib-src/crypto/func/test/w3.fc new file mode 100644 index 0000000000..0de8e551f6 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/w3.fc @@ -0,0 +1,13 @@ +() main(cs) impure { + int i = 0; + if (cs.slice_refs()) { + do { + i = i + 1; + } until(i > 10); + } + set_data(begin_cell() + .store_uint(1, 32) + .store_uint(2, 32) + .store_uint(i, 32) + .end_cell()); +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w4.fc b/submodules/ton/tonlib-src/crypto/func/test/w4.fc new file mode 100644 index 0000000000..1c0e2cefe1 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/w4.fc @@ -0,0 +1,13 @@ +_ main(cell dict, int t3) { + int index = -1; + do { + (index, slice value, int found) = dict.udict_get_next?(32, index); + if (found) { + (int temp1, int temp2) = (value~load_uint(16), value~load_uint(32)); + if (t3 > temp2) { + dict~udict_delete_get?(32, index); + } + } + } until ( ~ found); + return dict; +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w5.fc b/submodules/ton/tonlib-src/crypto/func/test/w5.fc new file mode 100644 index 0000000000..330a505042 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/w5.fc @@ -0,0 +1,14 @@ +(cell) recv_external(slice in_msg) impure { + cell mydict = new_dict(); + builder r = begin_cell().store_int(10, 16); + mydict~udict_set_builder(32, 1, r ); + int index = -1; + do { + (var index, var value, var found) = mydict.udict_get_next?(32, index); + } until ( ~ found ); + return mydict; +} + +() recv_internal() impure { + ;; Nothing +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w6.fc b/submodules/ton/tonlib-src/crypto/func/test/w6.fc new file mode 100644 index 0000000000..37251a58e8 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/w6.fc @@ -0,0 +1,12 @@ +int test(int x) method_id { + int i = 0; + ;; int f = false; + do { + i = i + 1; + if (i > 5) { + return 1; + } + int f = (i * i == 64); + } until (f); + return -1; +} diff --git a/submodules/ton/tonlib-src/crypto/func/test/w7.fc b/submodules/ton/tonlib-src/crypto/func/test/w7.fc new file mode 100644 index 0000000000..dddfd627b2 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/func/test/w7.fc @@ -0,0 +1,14 @@ +int test(int y) { + int x = 1; + if (y > 0) { + return 1; + } + return x > 0; +} + +int f(int y) { + if (y > 0) { + return 1; + } + return 2; +} diff --git a/submodules/ton/tonlib-src/crypto/func/unify-types.cpp b/submodules/ton/tonlib-src/crypto/func/unify-types.cpp index fd841a0fbe..698d21feba 100644 --- a/submodules/ton/tonlib-src/crypto/func/unify-types.cpp +++ b/submodules/ton/tonlib-src/crypto/func/unify-types.cpp @@ -153,7 +153,7 @@ bool TypeExpr::remove_forall(TypeExpr*& te) { bool TypeExpr::remove_forall_in(TypeExpr*& te, TypeExpr* te2, const std::vector& new_vars) { assert(te); assert(te2 && te2->constr == te_ForAll); - if (te->constr == te_Unknown) { + if (te->constr == te_Var) { for (std::size_t i = 0; i < new_vars.size(); i++) { if (te == te2->args[i + 1]) { te = new_vars[i]; @@ -201,12 +201,14 @@ std::ostream& operator<<(std::ostream& os, TypeExpr* type_expr) { std::ostream& TypeExpr::print(std::ostream& os, int lex_level) { switch (constr) { case te_Unknown: - if (value >= 0) { - return os << "??" << value; - } else if (value >= -26) { - return os << (char)(64 - value); + return os << "??" << value; + case te_Var: + if (value >= -26 && value < 0) { + return os << "_" << (char)(91 + value); + } else if (value >= 0 && value < 26) { + return os << (char)(65 + value); } else { - return os << "TVAR" << -value; + return os << "TVAR" << value; } case te_Indirect: return os << args[0]; diff --git a/submodules/ton/tonlib-src/crypto/smartcont/CreateState.fif b/submodules/ton/tonlib-src/crypto/smartcont/CreateState.fif index d701ecdc69..d3c05c00c9 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/CreateState.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/CreateState.fif @@ -182,3 +182,48 @@ dictnew constant special-dict -2 constant run_ticktock -3 constant split_prepare -4 constant split_install + +// public key conversion + + +// restricted wallet creation +"auto/restricted-wallet-code.fif" include =: RWCode1 +"auto/restricted-wallet2-code.fif" include =: RWCode2 + +// pubkey amount -- +{ over ."Key " pubkey>$ type ." -> " + RWCode1 // code + // data + empty_cell // libs + 3 roll // balance + 0 // split_depth + 0 // ticktock + 2 // mode: create + register_smc + Masterchain 6 .Addr cr +} : create-wallet1 + +// D x t -- D' +{ idict! not abort"cannot add value" +} : rdict-entry +// balance -- dict +{ dictnew + over -32768 rdict-entry + over 3/4 */ 92 rdict-entry + over 1/2 */ 183 rdict-entry + swap 1/4 */ 366 rdict-entry + 0 548 rdict-entry +} : make-rdict + +// pubkey amount -- +{ over ."Key " pubkey>$ type ." -> " + RWCode2 // code + // data + empty_cell // libs + 3 roll // balance + 0 // split_depth + 0 // ticktock + 2 // mode: create + register_smc + Masterchain 6 .Addr cr +} : create-wallet2 diff --git a/submodules/ton/tonlib-src/crypto/smartcont/asm-to-cpp.fif b/submodules/ton/tonlib-src/crypto/smartcont/asm-to-cpp.fif new file mode 100755 index 0000000000..21ff34bb2d --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/asm-to-cpp.fif @@ -0,0 +1,31 @@ +#!/usr/bin/fift -s +"TonUtil.fif" include +"Asm.fif" include + +{ ."usage: " @' $0 type ." " cr + ."Compiles asm from file and stores serialization in a way prepared for usage from c++ to " cr 1 halt +} : usage + + +$# 3 - ' usage if + + +$1 =: source +$2 =: destination +$3 =: name + +."Include source from " source type cr +source include + +boc>B +."Convert boc to base64" cr +B>base64 + +{ char " chr tuck $+ $+ } : wrp +wrp // "" +"with_tvm_code(" name wrp $+ +", " swap ");" 10 hold $+ $+ // "with_tm_code("");\n" + +$>B + +."Store tvm code to " destination type cr +destination B>file diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.cpp new file mode 100644 index 0000000000..fdc0e4fa4d --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.cpp @@ -0,0 +1 @@ +with_tvm_code("config", "te6ccgECFQEAAjUAART/APSkE/Sg8sgLAQIBIAIDAgLHBAUCAvETFAIBzwYHAAaqglsCASAICQIBIA4PAgEgCgsCASAMDQDpAHQ0wP6QDAg+kQBpANxsBOxI8cAsZJfA+AC0x/TPyKCEE5WU1S6jj0yAdTRcfgzIG6SMH+U0NcL/+IDcAS6mzIh8AIh+CO8ArywkQLinYAkWPABghDudk9L8ATgMYIQ7nZPb/AF4BAkXwQgwAABgx6wsfKlgACU7UTQ1FAzgCD0FcjMAc8Wye1UgADM0NMHAcAR8onTH9Mf0w/TDzAgwgDyib7yiYAArHCAGMjLBVAFzxYUy27LH8s/yQH7AIAIBIBAQAgEgERIACSAQPADgAFscfgz0NcL//gjghBOQ29kcIIAxP/IyxAUy/+DHfoCE8tqEssfyz8BzxbJcPsAgAL8IYIQQ2ZQIbqbMdMf1NFAE4Ag9BWORyGCEE5Db2S6jhcx1CH7BCDHAJFbm+1DAu1TIfEGgu1T4o4iIYIQUGJLIbqVMTHT/9GOESGCEE5D7wW6kzHwBpMw8mDi4uIB4gGAArQw7UTQ1IAggCRTMfRqIG6TECNbjjgg0CDXScInjinTB9cLHwHAEfgjEr6wjhUBgCJUEET0blRTIfRuMIAkQBP0WjCTECNb4pQQNF8D4uLIzAHPFsntVIAB5IMI1xgg0x/TH9Mf+CMSufJj7UTQ1NMf0//RUUG68qEF+QFUEGP5EPKi+AAQNBLwBwKkyBLMyx/L/8ntVIA=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif new file mode 100644 index 0000000000..2fed584c31 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif @@ -0,0 +1,344 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/config-code.fc` +PROGRAM{ + DECLPROC set_conf_param + DECLPROC check_validator_set + DECLPROC send_answer + DECLPROC send_confirmation + DECLPROC send_error + DECLPROC recv_internal + DECLPROC change_elector_code + 1666 DECLMETHOD after_code_upgrade + DECLPROC perform_action + DECLPROC recv_external + DECLPROC run_ticktock + set_conf_param PROC:<{ + // index value + c4 PUSH // index value _3 + CTOS // index value cs + LDREF // index value cfg_dict cs + s3 s3 XCHG2 + 32 PUSHINT // cs value index cfg_dict _9=32 + DICTISETREF // cs cfg_dict + NEWC // cs cfg_dict _11 + STREF // cs _12 + SWAP // _12 cs + STSLICER // _13 + ENDC // _14 + c4 POP + }> + check_validator_set PROC:<{ + // vset + CTOS // cs + 8 LDU // _4 cs + SWAP // cs _4 + 17 EQINT // cs _8 + 9 THROWIFNOT + 32 LDU // utime_since cs + 32 LDU // utime_since utime_until cs + 16 LDU // utime_since utime_until total cs + 16 LDU // utime_since utime_until total _42 _41 + DROP // utime_since utime_until total main + DUP // utime_since utime_until total main main + 0 GTINT // utime_since utime_until total main _28 + 9 THROWIFNOT + GEQ // utime_since utime_until _31 + 9 THROWIFNOT + }> + send_answer PROC:<{ + // addr query_id ans_tag mode + 0 PUSHINT // addr query_id ans_tag mode _4=0 + 24 PUSHINT // addr query_id ans_tag mode _4=0 _5=24 + NEWC // addr query_id ans_tag mode _4=0 _5=24 _6 + 6 STU // addr query_id ans_tag mode _4=0 _8 + s0 s5 XCHG2 // _4=0 query_id ans_tag mode _8 addr + STSLICER // _4=0 query_id ans_tag mode _9 + s1 s4 XCHG // mode query_id ans_tag _4=0 _9 + 111 STU // mode query_id ans_tag _23 + 32 STU // mode query_id _25 + 64 STU // mode _27 + ENDC // mode _28 + SWAP // _28 mode + SENDRAWMSG + }> + send_confirmation PROC:<{ + // addr query_id ans_tag + 64 PUSHINT // addr query_id ans_tag _3=64 + send_answer CALLDICT + }> + send_error PROC:<{ + // addr query_id ans_tag + 64 PUSHINT // addr query_id ans_tag _3=64 + send_answer CALLDICT + }> + recv_internal PROC:<{ + // in_msg_cell in_msg + SWAP // in_msg in_msg_cell + CTOS // in_msg cs + 4 LDU // in_msg flags cs + LDMSGADDR // in_msg flags _74 _73 + DROP // in_msg flags s_addr + DUP // in_msg flags s_addr s_addr + REWRITESTDADDR // in_msg flags s_addr src_wc src_addr + SWAP // in_msg flags s_addr src_addr src_wc + INC // in_msg flags s_addr src_addr _15 + s0 s3 XCHG + 1 PUSHINT // in_msg _15 s_addr src_addr flags _16=1 + AND // in_msg _15 s_addr src_addr _17 + s1 s3 XCHG // in_msg src_addr s_addr _15 _17 + OR // in_msg src_addr s_addr _18 + s3 PUSH // in_msg src_addr s_addr _18 in_msg + SEMPTY // in_msg src_addr s_addr _18 _19 + OR // in_msg src_addr s_addr _20 + IFJMP:<{ // in_msg src_addr s_addr + 3 BLKDROP // + }> // in_msg src_addr s_addr + s0 s2 XCHG // s_addr src_addr in_msg + 32 LDU // s_addr src_addr tag in_msg + 64 LDU // s_addr src_addr tag query_id in_msg + s2 PUSH + 1314280276 PUSHINT // s_addr src_addr tag query_id in_msg tag _29=1314280276 + EQUAL // s_addr src_addr tag query_id in_msg _30 + IFJMP:<{ // s_addr src_addr tag query_id in_msg + s2 POP // s_addr src_addr in_msg query_id + SWAP // s_addr src_addr query_id in_msg + LDREF // s_addr src_addr query_id vset in_msg + ENDS + 1 PUSHINT // s_addr src_addr query_id vset _36=1 + CONFIGOPTPARAM // s_addr src_addr query_id vset elector_param + DUP // s_addr src_addr query_id vset elector_param elector_param + ISNULL // s_addr src_addr query_id vset elector_param _39 + IF:<{ // s_addr src_addr query_id vset elector_param + DROP // s_addr src_addr query_id vset + -1 PUSHINT // s_addr src_addr query_id vset _40=-1 + }>ELSE<{ // s_addr src_addr query_id vset elector_param + CTOS // s_addr src_addr query_id vset _42 + 256 PLDU // s_addr src_addr query_id vset _40 + }> // s_addr src_addr query_id vset elector_addr + s0 s3 XCHG + FALSE + s0 s4 XCHG // s_addr ok query_id vset src_addr elector_addr + EQUAL // s_addr ok query_id vset _47 + IF:<{ // s_addr ok query_id vset + s2 POP // s_addr vset query_id + OVER // s_addr vset query_id vset + check_validator_set CALLDICT // s_addr vset query_id t_since t_until + OVER + NOW // s_addr vset query_id t_since t_until t_since t + GREATER // s_addr vset query_id t_since t_until _53 + s0 s2 XCHG // s_addr vset query_id _53 t_until t_since + GREATER // s_addr vset query_id _53 _54 + AND // s_addr vset query_id ok + }>ELSE<{ + s0 s2 XCHG // s_addr vset query_id ok + }> + IFJMP:<{ // s_addr vset query_id + 36 PUSHINT // s_addr vset query_id _56=36 + ROT // s_addr query_id _56=36 vset + set_conf_param CALLDICT + 4000730955 PUSHINT // s_addr query_id _58=4000730955 + send_confirmation CALLDICT + }> // s_addr vset query_id + NIP // s_addr query_id + 4000730991 PUSHINT // s_addr query_id _60=4000730991 + send_error CALLDICT + }> // s_addr src_addr tag query_id in_msg + s2 s4 XCHG + 4 BLKDROP // tag + DUP // tag tag + 0 EQINT // tag _64 + SWAP + 31 PUSHPOW2 // _64 tag _67 + AND // _64 _68 + OR // _69 + 37 THROWIFNOT + }> + change_elector_code PROC:<{ + // cs + 1 PUSHINT // cs _2=1 + CONFIGOPTPARAM // cs _3 + CTOS // cs _4 + 256 PLDU // cs dest_addr + NOW // cs dest_addr query_id + 1313042276 PUSHINT // cs dest_addr query_id _9=1313042276 + 0 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0 + 50431 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0 _11=50431 + NEWC // cs dest_addr query_id _9=1313042276 _10=0 _11=50431 _12 + 17 STU // cs dest_addr query_id _9=1313042276 _10=0 _14 + s1 s4 XCHG // cs _10=0 query_id _9=1313042276 dest_addr _14 + 256 STU // cs _10=0 query_id _9=1313042276 _16 + 30 PUSHPOW2 // cs _10=0 query_id _9=1313042276 _16 _19 + STGRAMS // cs _10=0 query_id _9=1313042276 _20 + s1 s3 XCHG // cs _9=1313042276 query_id _10=0 _20 + 107 STU // cs _9=1313042276 query_id _34 + s1 s2 XCHG // cs query_id _9=1313042276 _34 + 32 STU // cs query_id _36 + 64 STU // cs _38 + SWAP // _38 cs + STSLICER // _39 + ENDC // _40 + 0 PUSHINT // _40 _41=0 + SENDRAWMSG + }> + after_code_upgrade PROC:<{ + // param old_code + 2DROP // + }> + perform_action PROC:<{ + // cfg_dict public_key action cs + OVER + 1130778657 PUSHINT // cfg_dict public_key action cs action _4=1130778657 + EQUAL // cfg_dict public_key action cs _5 + IF:<{ // cfg_dict public_key action cs + NIP // cfg_dict public_key cs + 32 LDU // cfg_dict public_key param_index cs + LDREF // cfg_dict public_key param_index param_value cs + ENDS + s0 s1 s3 XCHG3 + 32 PUSHINT // public_key param_value param_index cfg_dict _15=32 + DICTISETREF // public_key cfg_dict + }>ELSE<{ // cfg_dict public_key action cs + OVER + 1313042276 PUSHINT // cfg_dict public_key action cs action _17=1313042276 + EQUAL // cfg_dict public_key action cs _18 + IF:<{ // cfg_dict public_key action cs + NIP // cfg_dict public_key cs + LDREF // cfg_dict public_key new_code cs + OVER // cfg_dict public_key new_code cs new_code + SETCODE + DUP // cfg_dict public_key new_code cs cs + SEMPTY // cfg_dict public_key new_code cs _23 + IFNOT:<{ // cfg_dict public_key new_code cs + c3 PUSH // cfg_dict public_key new_code cs old_code + s0 s2 XCHG // cfg_dict public_key old_code cs new_code + c3 POP + OVER // cfg_dict public_key old_code cs old_code + after_code_upgrade CALLDICT + c3 POP + }>ELSE<{ + 2DROP // cfg_dict public_key + }> + }>ELSE<{ // cfg_dict public_key action cs + OVER + 1348619041 PUSHINT // cfg_dict public_key action cs action _29=1348619041 + EQUAL // cfg_dict public_key action cs _30 + IF:<{ // cfg_dict public_key action cs + NIP + NIP // cfg_dict cs + 256 LDU // cfg_dict public_key cs + ENDS + }>ELSE<{ // cfg_dict public_key action cs + OVER + 1313074949 PUSHINT // cfg_dict public_key action cs action _35=1313074949 + EQUAL // cfg_dict public_key action cs _36 + IF:<{ // cfg_dict public_key action cs + NIP // cfg_dict public_key cs + change_elector_code CALLDICT + }>ELSE<{ // cfg_dict public_key action cs + DROP // cfg_dict public_key action + 32 THROWIF + }> + }> + }> + SWAP // public_key cfg_dict + }> + SWAP // cfg_dict public_key + }> + recv_external PROC:<{ + // in_msg + 9 PUSHPOW2 // in_msg _3=512 + LDSLICEX // signature in_msg + DUP // signature in_msg cs + 32 LDU // signature in_msg action cs + 32 LDU // signature in_msg action msg_seqno cs + 32 LDU // signature in_msg action msg_seqno valid_until cs + NOW // signature in_msg action msg_seqno valid_until cs _19 + s1 s2 XCHG // signature in_msg action msg_seqno cs valid_until _19 + LESS // signature in_msg action msg_seqno cs _20 + 35 THROWIF + c4 PUSH // signature in_msg action msg_seqno cs _23 + CTOS // signature in_msg action msg_seqno cs cs2 + LDREF // signature in_msg action msg_seqno cs cfg_dict cs2 + 32 LDU // signature in_msg action msg_seqno cs cfg_dict stored_seqno cs2 + 256 LDU // signature in_msg action msg_seqno cs cfg_dict stored_seqno public_key cs2 + ENDS + s4 s1 XCPU // signature in_msg action public_key cs cfg_dict stored_seqno msg_seqno stored_seqno + EQUAL // signature in_msg action public_key cs cfg_dict stored_seqno _38 + 33 THROWIFNOT + s0 s5 XCHG // signature stored_seqno action public_key cs cfg_dict in_msg + HASHSU // signature stored_seqno action public_key cs cfg_dict _41 + s0 s6 s3 XC2PU // cfg_dict stored_seqno action public_key cs _41 signature public_key + CHKSIGNU // cfg_dict stored_seqno action public_key cs _42 + 34 THROWIFNOT + ACCEPT + s3 s4 XCHG + s1 s2 XCHG // stored_seqno cfg_dict public_key action cs + perform_action CALLDICT // stored_seqno cfg_dict public_key + s0 s2 XCHG // public_key cfg_dict stored_seqno + INC // public_key cfg_dict _47 + NEWC // public_key cfg_dict _47 _48 + s1 s2 XCHG // public_key _47 cfg_dict _48 + STREF // public_key _47 _49 + 32 STU // public_key _51 + 256 STU // _53 + ENDC // _54 + c4 POP + }> + run_ticktock PROC:<{ + // is_tock + DROP // + c4 PUSH // _2 + CTOS // cs + LDREF // cfg_dict cs + 32 PUSHINT // cfg_dict cs kl=32 + 36 PUSHINT // cfg_dict cs kl=32 _10=36 + s3 s1 PUSH2 // cfg_dict cs kl=32 _10=36 cfg_dict kl=32 + DICTIGETOPTREF // cfg_dict cs kl=32 next_vset + DUP // cfg_dict cs kl=32 next_vset next_vset + ISNULL // cfg_dict cs kl=32 next_vset _12 + IFNOT:<{ // cfg_dict cs kl=32 next_vset + DUP // cfg_dict cs kl=32 next_vset next_vset + CTOS // cfg_dict cs kl=32 next_vset ds + DUP // cfg_dict cs kl=32 next_vset ds ds + SBITS // cfg_dict cs kl=32 next_vset ds _15 + 39 GTINT // cfg_dict cs kl=32 next_vset ds _17 + IF:<{ // cfg_dict cs kl=32 next_vset ds + 8 LDU // cfg_dict cs kl=32 next_vset tag ds + 32 PLDU // cfg_dict cs kl=32 next_vset tag since + SWAP // cfg_dict cs kl=32 next_vset since tag + 17 EQINT // cfg_dict cs kl=32 next_vset since _26 + NOW // cfg_dict cs kl=32 next_vset since _26 _27 + s1 s2 XCHG // cfg_dict cs kl=32 next_vset _26 since _27 + GEQ // cfg_dict cs kl=32 next_vset _26 _28 + AND // cfg_dict cs kl=32 next_vset _29 + IF:<{ // cfg_dict cs kl=32 next_vset + SWAP + 34 PUSHINT + s0 s4 s4 XC2PU // kl=32 cs next_vset _32=34 cfg_dict kl=32 + DICTISETGETOPTREF // kl=32 cs cfg_dict cur_vset + s3 s1 s0 PUXCPU // kl=32 cs cur_vset _35=32 cfg_dict kl=32 + DICTISETGETOPTREF // kl=32 cs _51 _52 + DROP // kl=32 cs cfg_dict + 36 PUSHINT // kl=32 cs cfg_dict _38=36 + s0 s1 s3 XCHG3 // cs _38=36 cfg_dict kl=32 + DICTIDEL // cs _53 _54 + DROP // cs cfg_dict + }>ELSE<{ + s2 s3 XCHG + 2DROP // cs cfg_dict + }> + }>ELSE<{ + s3 s4 XCHG + 3 BLKDROP // cs cfg_dict + }> + }>ELSE<{ + s2 s3 XCHG + 2DROP // cs cfg_dict + }> + NEWC // cs cfg_dict _40 + STREF // cs _41 + SWAP // _41 cs + STSLICER // _42 + ENDC // _43 + c4 POP + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.cpp new file mode 100644 index 0000000000..eb520f79ef --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.cpp @@ -0,0 +1 @@ +with_tvm_code("elector-code", "te6ccgECVAEACrkAART/APSkE/Sg8sgLAQIBIAIDAgFIBAUAUaX//xh2omh6AnoCETdKrPgN+SBOKjgQ+At5ICz4DPkgcXgL+SB4DRhAAgLFBgcCASAKCwIBywgJACyqgjGCEE5Db2SCEM5Db2RwQzCAQPAGAgEgEBECASAzNAIDeqAMDQIBbg4PACSqB+1E0PQFIG6SMHCU0NcLH+IAQqss7UTQ9AUgbpJbcODwAxAmXwaDB/QOb6GT+gAwkjBw4gBzsKV7UTQ9AUgbpIwbeDwAxAmXwZthP+OHiKDB/R+b6FvoSCcAvoAMFIQbwJQA28Cklow4gGzEuYwMYAAzs+A7UTQ9AQx9AQwgwf0Dm+hk/oAMJIwcOKACASASEwIBICMkAgEgFBUCASAdHgIBIBYXAgEgGxwBASAYACE7UTQ9AT0BPQE+gDTH9P/0YAL8AdDTAwFxsJJfA+D6QDAhxwCUMQHwEOAB0x8hwACUWwHwEODTPyKCEE5zdEu6lTIQI/AL4DQhghBHZXQkupMT8BHgIYIQTkNvZLqOGVRSRPASloIQzkNvZJKEH+JwEDRDMIBA8AbgIYIQ7nZPS7oighDudk9vulIQsYrgMDMgGRoADDIQIwHwDwAkgx6wm4QfcBA0QzCAQPAG4V8DACkyBb0ABT0ABL0AAH6Assfy//J7VSAAITQ0x/TH/oA+gD0BNIA0gDRgAgEgHyACASAhIgArMgXyx8Vyx9QA/oCAfoC9ADKAMoAyYAAdIAP+DPQ0h/SH9If1wofgAEUcIAYyMsFUAfPFlj6AhXLahPLH8s/IcL/kssfkTHiyQH7AIAAbIIQ7m9FTHBDMIBA8AaACASAlJgIBIC0uAgEgJygCASApKgAjIIQ83RITIIQO5rKAEMwcvAGgAEcghBOVlNUcIIAxP/IyxAVy/+DHfoCFMtqE8sfEss/zMlx+wCAAMxTEoMH9A5voZT6ADCgkTDiyAH6AgKDB/RDgAQEgKwH+I/pE7UTQ9AQhbgSkFLGXEDVfBXDwB+AE0//TH9Mf0//UAdCDCNcZAdGCEGVMUHTIyx9SQMsfUjDLH1Jgy/9SIMv/ydBRFfkRlxBoXwhx8AfhIYMPuZcQaF8IdvAH4AfwAzEF/iANghA7msoAoSCqCyO5mBC8XwwxcvAH4FEioCwA/lF9vZcQrF8Mc/AH4ASXEJtfC3DwB+BTY4MH9A5voSCfMPoAWaAB0z8x0/8wUoC9kTHilxCbXwt08AfgUwG5lxCbXwt18AfgIPKs+AD4I8hY+gLLHxTLHxbL/xjL/0A3gwf0Q3AQVxA0ECMQJnDwBMj0AAHPFsntVCCTcPAI4FsCASAvMAIBIDEyAHkcCB/jjAkgwf0fG+hb6EgjhwC0//TPzH6ANIA0ZQxUTOgl1QYiPAKBwPiUEOgk1BCMOIBsxPmMDMBuvK7gAKEcFMAf447JoMH9HxvoW+hII4nAtP/0z8x+gDSANGUMVEzoI4RVHcIqYRRZqBSF6BLsPAKCQPiUFOgk1BSMOIBsxTmMDUDulMhu7DyuxKgAaGAAVwBgCD0Zm+hkjBw4dM/MdP/MfQE+gD6APQEMdEgwgCUEDTwDZUwECPwDOISgAKMMgL6RHD4M9DXC//tRND0BASkWr2xIW6xkl8E4PADBV8FUhW9BLMUsZJfA+D4AAGRW44d9AT0BPoAQzTwDnDIygAT9AD0AFmg+gIBzxbJ7VTigAgEgNTYCAUhOTwIBIDc4AgEgPT4CASA5OgIBIDs8AKU8AEH+kQBpLEhwACxlwWgVRMB8ALgUwKAIPQOb6GOJ9M/0//0BPoA+gALoMgVyz8Ty//0AAH6AgH6AlAGzxYBgCBURkT0Q5QwBaAB4hA1QUPwAoADZDEh+kQBpJ8wghD////+cBA0E4BA8Abg7UTQ9AT0BFAzgwf0Zm+hjhBfBIIQ/////nAQNBOAQPAG4TYF+gDRyBL0ABX0AAHPFsntVIIQ+W9zJHCAGMjLBVAEzxZQBPoCEstqEssfyz/JgED7AIABpHD4MyBuk18EcODQ1wv/I/pEAaQCvbGTXwNw4PgAAdQh+wQgxwCSXwSZAe1TAfEGgvIA4n+AAAxwgAgEgP0ACASBJSgA1HACjhMCbyIhbxACbxEkqKsPErYIEqBY5DAxgAQEgQQP+gBD4M9DTD9MPMdMP0XG2CXBtf45GKYMH9HxvoW+hII4wAvoA0x/TH9P/0//RA6PIFct/FMofUkDL/8nQURq2CMjLHxPL/8v/QBSBAaD0QQOklBA0WjDiAbNDMOYwNFi2CFMBuZZfB21tcCDgbYrmMzSlXJJvEeRwIIrmMjI0NEJDRABqA4EBoPSSb6FvoSCOIAHTf1EZtggB0x8x1wv/A9Mf0/8x1wv/QTAUbwRQBW8Ck0YWW+IEsxQASgJvIgFvEASkU0i+jhBUZQbwFFMCvJMyMiKSEzDik1A0MOJTNr4BXiLAAFJDuRKxll8EbW1wIOAg/iAipZJvEeRvEG8QcCBtbYrmMzMzNVIUuvKxECMBRQL+BW8iAW8kUxyDB/QOb6HyvfoAMdM/MdcL/1OLuY5XUTmoqw9SQLYIUUShJKo7LakEUYWgghCOgSeKI5KAc5KAU+LIywfLH1JAy/9SkMs/I5MTy/+TUAMw4gGAEFRKmfRDcCTIy/8Zyz9QBfoCF8oAQBmDB/RDlgoQRgNfA+IjikZHAAhLc/AKARiK4gOkKW4QShBGREBIAAZLc1sBASBLAa08AGAIvgz+QBTAbqTXwdw4CKOL1MkgCD0Dm+hjh/THzEg0x/T/zBQBLryufgjUAOgyMsfWM8WQASAIPRDlBUTXwPik0QUW+J/iuYgbpIwcJDiUAPwAn+BNAf4B8AM0+CMluZNfCHDgcPgzbpRfCPAT4IAR+DPQ+gD6APoA0x/RU2G5lF8M8BPgBJRfC/AT4AaTXwpw4BA4KFEyUHfwFSDAACCzKgYQWhBJEDhMzPAEIo4TMjIyMjLIEvQA9AABzxbJ7VTwE+HwBTL4IwGgpsQotgmAEPgz0IAQTADI1yHXCw9SYLYIUxOggBHIywdSMMsfyx8Xyw8Wyw8J0BnPFslw+DPQ1wv/UxjwCQn0BHAL+QBQY6ApoMjLHxnLH8v/FfQAUAP6AnD6AhbKAEA0gCD0Q8gT9AD0APQAAc8Wye1UfwCkIYAg9HxvoW+hII4/AtM/0/9TF7qOLTQD9AT6APoAKKsCUZmhUCmgyBXLPxbL/xL0AAH6AgH6AljPFgGAIFRBRPRDcJYQNRA0XwPik0MDMOKzEgIBIFBRAgEgUlMAGQhbpJbcJUB+QABuuKAAlQB8AMFXwWTXwNw4QL0BFExgCD0Dm+hk18EcOGAQNch1wv/gCL4MyHwGIAk+DNY8BixjhNwyMoAEvQA9AABzxbJ7VTwFzB/4F8DcIACTPABf44+JIAg9HxvoW+hII4kAtMfMPgju1MUvbCOETFUFUTwDhSgVHYTVHNY8AJwlEYVUETilhA3FkUFMOKzECYQRRTmBl8GbrOAA4QxgCT4M26SW3Dhcfgz0NcL//go+kQBpAK9sZJbcOCAIvgzIG6TXwNw4PAFMDIC0IAo1yHXCx/4I1EToVy5k18GcOBcocE8kTGRMOKAEfgz0PoAMAOg/iBSAqFwbXAQRRA0cPAEyPQA9AABzxbJ7VR/g"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif new file mode 100644 index 0000000000..d964063b2e --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif @@ -0,0 +1,1712 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/elector-code.fc` +PROGRAM{ + DECLPROC load_data + DECLPROC store_data + DECLPROC unpack_elect + DECLPROC pack_elect + DECLPROC get_validator_conf + DECLPROC send_message_back + DECLPROC return_stake + DECLPROC send_confirmation + DECLPROC send_validator_set_to_config + DECLPROC ~credit_to + DECLPROC process_new_stake + DECLPROC unfreeze_without_bonuses + DECLPROC unfreeze_with_bonuses + DECLPROC unfreeze_all + DECLPROC config_set_confirmed + DECLPROC process_simple_transfer + DECLPROC recover_stake + 1666 DECLMETHOD after_code_upgrade + DECLPROC upgrade_code + DECLPROC recv_internal + DECLPROC postpone_elections + DECLPROC compute_total_stake + DECLPROC try_elect + DECLPROC conduct_elections + DECLPROC update_active_vset_id + DECLPROC cell_hash_eq? + DECLPROC validator_set_installed + DECLPROC check_unfreeze + DECLPROC announce_new_elections + DECLPROC run_ticktock + 86535 DECLMETHOD active_election_id + 87852 DECLMETHOD participates_in + 123541 DECLMETHOD participant_list + 130944 DECLMETHOD compute_returned_stake + load_data PROC:<{ + // + c4 PUSH // _1 + CTOS // cs + LDDICT // _4 cs + LDDICT // _4 _6 cs + LDDICT // _4 _6 _8 cs + LDGRAMS // _4 _6 _8 _10 cs + 32 LDU // _4 _6 _8 _10 _12 cs + 256 LDU // res res res res res res cs + ENDS + }> + store_data PROC:<{ + // elect credits past_elect grams active_id active_hash + NEWC // elect credits past_elect grams active_id active_hash _6 + s1 s6 XCHG // active_hash credits past_elect grams active_id elect _6 + STDICT // active_hash credits past_elect grams active_id _7 + s1 s4 XCHG // active_hash active_id past_elect grams credits _7 + STDICT // active_hash active_id past_elect grams _8 + s1 s2 XCHG // active_hash active_id grams past_elect _8 + STDICT // active_hash active_id grams _9 + SWAP // active_hash active_id _9 grams + STGRAMS // active_hash active_id _10 + 32 STU // active_hash _12 + 256 STU // _14 + ENDC // _15 + c4 POP + }> + unpack_elect PROC:<{ + // elect + CTOS // es + 32 LDU // _4 es + 32 LDU // _4 _7 es + LDGRAMS // _4 _7 _10 es + LDGRAMS // _4 _7 _10 _12 es + LDDICT // _4 _7 _10 _12 _14 es + 1 LDI // _4 _7 _10 _12 _14 _16 es + 1 LDI // res res res res res res res es + ENDS + }> + pack_elect PROC:<{ + // elect_at elect_close min_stake total_stake members failed finished + NEWC // elect_at elect_close min_stake total_stake members failed finished _7 + s1 s7 XCHG // finished elect_close min_stake total_stake members failed elect_at _7 + 32 STU // finished elect_close min_stake total_stake members failed _9 + s1 s5 XCHG // finished failed min_stake total_stake members elect_close _9 + 32 STU // finished failed min_stake total_stake members _11 + s0 s3 XCHG2 // finished failed members total_stake _11 min_stake + STGRAMS // finished failed members total_stake _12 + SWAP // finished failed members _12 total_stake + STGRAMS // finished failed members _13 + STDICT // finished failed _14 + 1 STI // finished _16 + 1 STI // _18 + ENDC // _19 + }> + get_validator_conf PROC:<{ + // + 15 PUSHINT // _1=15 + CONFIGOPTPARAM // _2 + CTOS // cs + 32 LDI // _4 cs + 32 LDI // _4 _7 cs + 32 LDI // _4 _7 _10 cs + 32 PLDI // _4 _7 _10 _14 + }> + send_message_back PROC:<{ + // addr ans_tag query_id body grams mode + 0 PUSHINT // addr ans_tag query_id body grams mode _7=0 + 24 PUSHINT // addr ans_tag query_id body grams mode _7=0 _8=24 + NEWC // addr ans_tag query_id body grams mode _7=0 _8=24 _9 + 6 STU // addr ans_tag query_id body grams mode _7=0 _11 + s0 s7 XCHG2 // _7=0 ans_tag query_id body grams mode _11 addr + STSLICER // _7=0 ans_tag query_id body grams mode _12 + ROT // _7=0 ans_tag query_id body mode _12 grams + STGRAMS // _7=0 ans_tag query_id body mode _13 + s1 s5 XCHG // mode ans_tag query_id body _7=0 _13 + 107 STU // mode ans_tag query_id body _27 + s1 s3 XCHG // mode body query_id ans_tag _27 + 32 STU // mode body query_id _29 + 64 STU // mode body msg + OVER // mode body msg body + -1 GTINT // mode body msg _33 + IF:<{ // mode body msg + 32 STU // mode msg + }>ELSE<{ + NIP // mode msg + }> + ENDC // mode _37 + SWAP // _37 mode + SENDRAWMSG + }> + return_stake PROC:<{ + // addr query_id reason + 4000269644 PUSHINT // addr query_id reason _3=4000269644 + 0 PUSHINT // addr query_id reason _3=4000269644 _4=0 + s3 s3 s0 XCHG3 + 64 PUSHINT // addr _3=4000269644 query_id reason _4=0 _5=64 + send_message_back CALLDICT + }> + send_confirmation PROC:<{ + // addr query_id comment + 4084484172 PUSHINT // addr query_id comment _3=4084484172 + 1000000000 PUSHINT // addr query_id comment _3=4084484172 _4=1000000000 + s3 s3 s0 XCHG3 + 2 PUSHINT // addr _3=4084484172 query_id comment _4=1000000000 _5=2 + send_message_back CALLDICT + }> + send_validator_set_to_config PROC:<{ + // config_addr vset query_id + 1314280276 PUSHINT // config_addr vset query_id _4=1314280276 + 0 PUSHINT // config_addr vset query_id _4=1314280276 _5=0 + 50431 PUSHINT // config_addr vset query_id _4=1314280276 _5=0 _6=50431 + NEWC // config_addr vset query_id _4=1314280276 _5=0 _6=50431 _7 + 17 STU // config_addr vset query_id _4=1314280276 _5=0 _9 + s1 s5 XCHG // _5=0 vset query_id _4=1314280276 config_addr _9 + 256 STU // _5=0 vset query_id _4=1314280276 _11 + 30 PUSHPOW2 // _5=0 vset query_id _4=1314280276 _11 _14 + STGRAMS // _5=0 vset query_id _4=1314280276 _15 + s1 s4 XCHG // _4=1314280276 vset query_id _5=0 _15 + 107 STU // _4=1314280276 vset query_id _29 + s1 s3 XCHG // query_id vset _4=1314280276 _29 + 32 STU // query_id vset _31 + s1 s2 XCHG // vset query_id _31 + 64 STU // vset _33 + STREF // msg + ENDC // _35 + 1 PUSHINT // _35 _36=1 + SENDRAWMSG + }> + ~credit_to PROC:<{ + // credits addr amount + s1 s2 PUSH2 + 8 PUSHPOW2 // credits addr amount addr credits _5=256 + DICTUGET + NULLSWAPIFNOT // credits addr amount val f + IF:<{ // credits addr amount val + LDGRAMS // credits addr amount _18 _17 + DROP // credits addr amount _7 + ADD // credits addr amount + }>ELSE<{ + DROP // credits addr amount + }> + NEWC // credits addr amount _11 + SWAP // credits addr _11 amount + STGRAMS // credits addr _12 + s0 s2 XCHG + 8 PUSHPOW2 // _12 addr credits _13=256 + DICTUSETB // credits + }> + process_new_stake PROC:<{ + // s_addr msg_value cs query_id + s3 PUSH // s_addr msg_value cs query_id s_addr + REWRITESTDADDR // s_addr msg_value cs query_id src_wc src_addr + c4 PUSH // s_addr msg_value cs query_id src_wc src_addr _8 + CTOS // s_addr msg_value cs query_id src_wc src_addr ds + LDDICT // s_addr msg_value cs query_id src_wc src_addr elect ds + OVER // s_addr msg_value cs query_id src_wc src_addr elect ds elect + ISNULL // s_addr msg_value cs query_id src_wc src_addr elect ds _13 + s0 s4 XCHG // s_addr msg_value cs query_id _13 src_addr elect ds src_wc + INC // s_addr msg_value cs query_id _13 src_addr elect ds _15 + s1 s4 XCHG // s_addr msg_value cs query_id ds src_addr elect _13 _15 + OR // s_addr msg_value cs query_id ds src_addr elect _16 + IFJMP:<{ // s_addr msg_value cs query_id ds src_addr elect + s3 s5 XCHG + 5 BLKDROP // s_addr query_id + 0 PUSHINT // s_addr query_id _17=0 + return_stake CALLDICT + }> // s_addr msg_value cs query_id ds src_addr elect + s0 s4 XCHG // s_addr msg_value elect query_id ds src_addr cs + 256 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey cs + 32 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at cs + 32 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor cs + 256 LDU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs + LDREF // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _36 cs + SWAP // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs _36 + CTOS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs _38 + 9 PUSHPOW2 // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs _38 _39=512 + PLDSLICEX // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr cs signature + SWAP // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature cs + ENDS + 1699500148 PUSHINT // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _42=1699500148 + NEWC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _42=1699500148 _43 + 32 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _45 + s4 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature stake_at _45 + 32 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _47 + s3 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature max_factor _47 + 32 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _49 + s6 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature src_addr _49 + 256 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _51 + s2 s(-1) PUXC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature adnl_addr _51 + 256 STU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _53 + ENDC // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _54 + CTOS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr signature _55 + s1 s5 XCPU // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _55 signature validator_pubkey + CHKSIGNS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _56 + IFNOTJMP:<{ // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr + s6 s8 XCHG + 8 BLKDROP // s_addr query_id + 1 PUSHINT // s_addr query_id _57=1 + return_stake CALLDICT + }> // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr + OVER + 16 PUSHPOW2 // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr max_factor _59=65536 + LESS // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr _60 + IFJMP:<{ // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr + s6 s8 XCHG + 8 BLKDROP // s_addr query_id + 6 PUSHINT // s_addr query_id _61=6 + return_stake CALLDICT + }> // s_addr msg_value elect query_id ds src_addr validator_pubkey stake_at max_factor adnl_addr + s0 s7 XCHG // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect + unpack_elect CALLDICT // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor _146 _147 _148 _149 _150 _151 _152 + NIP // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor elect_at elect_close min_stake total_stake members finished + s0 s5 XCHG // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members elect_at + s0 DUMP // s_addr msg_value adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members elect_at + s0 s13 XCHG + 1000000000 PUSHINT // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value _73=1000000000 + SUB // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value + DUP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value msg_value + 12 LSHIFT# // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value _76 + s3 PUSH // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value _76 total_stake + LESS // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value _77 + IFJMP:<{ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value + s11 s12 XCHG + 12 BLKDROP + NIP // s_addr query_id + 2 PUSHINT // s_addr query_id _78=2 + return_stake CALLDICT + }> // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake total_stake members msg_value + s2 s2 XCPU // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake msg_value members total_stake msg_value + ADD // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey stake_at max_factor finished elect_close min_stake msg_value members total_stake + s7 s13 XCPU // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor finished elect_close min_stake msg_value members stake_at elect_at + NEQ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor finished elect_close min_stake msg_value members _81 + IFJMP:<{ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor finished elect_close min_stake msg_value members + s10 s12 XCHG + 12 BLKDROP // s_addr query_id + 3 PUSHINT // s_addr query_id _82=3 + return_stake CALLDICT + }> // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor finished elect_close min_stake msg_value members + s0 s4 XCHG // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value finished + IFJMP:<{ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value + s9 s11 XCHG + 11 BLKDROP // s_addr query_id + 0 PUSHINT // s_addr query_id _84=0 + return_stake CALLDICT + }> // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value + s6 s3 PUSH2 + 8 PUSHPOW2 // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value validator_pubkey members _88=256 + DICTUGET + NULLSWAPIFNOT // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value mem found + DUP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value mem found found + IF:<{ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value mem found + DROP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value mem + LDGRAMS // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value _90 mem + -ROT // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake mem msg_value _90 + ADD // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake mem msg_value + SWAP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value mem + 64 LDU // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value _158 _157 + NIP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value mem + 256 LDU // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value _160 _159 + DROP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value _96 + s8 s(-1) PUXC // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value src_addr _96 + NEQ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value found + }>ELSE<{ + NIP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value found + }> + IFJMP:<{ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value + s9 s11 XCHG + 11 BLKDROP // s_addr query_id + 4 PUSHINT // s_addr query_id _100=4 + return_stake CALLDICT + }> // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value + s0 s1 PUSH2 // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value msg_value min_stake + LESS // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value _102 + IFJMP:<{ // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value + s9 s11 XCHG + 11 BLKDROP // s_addr query_id + 5 PUSHINT // s_addr query_id _103=5 + return_stake CALLDICT + }> // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value + DUP // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value msg_value + 44 THROWIFNOT + ACCEPT + NOW // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value _109 + NEWC // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake msg_value _109 _110 + ROT // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake _109 _110 msg_value + STGRAMS // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake _109 _111 + 32 STU // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake max_factor members elect_close min_stake _113 + s1 s4 XCHG // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake min_stake members elect_close max_factor _113 + 32 STU // s_addr elect_at adnl_addr query_id ds src_addr validator_pubkey total_stake min_stake members elect_close _115 + s1 s6 XCHG // s_addr elect_at adnl_addr query_id ds elect_close validator_pubkey total_stake min_stake members src_addr _115 + 256 STU // s_addr elect_at adnl_addr query_id ds elect_close validator_pubkey total_stake min_stake members _117 + s1 s8 XCHG // s_addr elect_at members query_id ds elect_close validator_pubkey total_stake min_stake adnl_addr _117 + 256 STU // s_addr elect_at members query_id ds elect_close validator_pubkey total_stake min_stake _119 + s0 s3 s7 XCHG3 + 8 PUSHPOW2 // s_addr elect_at total_stake query_id ds elect_close min_stake _119 validator_pubkey members _120=256 + DICTUSETB // s_addr elect_at total_stake query_id ds elect_close min_stake members + FALSE // s_addr elect_at total_stake query_id ds elect_close min_stake members _122 + s5 s7 XCHG + s3 s4 XCHG + s2 s3 XCHG + s2 s6 XCHG + FALSE // s_addr query_id ds elect_at elect_close min_stake total_stake members _122 _123 + pack_elect CALLDICT // s_addr query_id ds elect + NEWC // s_addr query_id ds elect _125 + STDICT // s_addr query_id ds _126 + SWAP // s_addr query_id _126 ds + STSLICER // s_addr query_id _127 + ENDC // s_addr query_id _128 + c4 POP + DUP // s_addr query_id query_id + IFJMP:<{ // s_addr query_id + 0 PUSHINT // s_addr query_id _130=0 + send_confirmation CALLDICT + }> // s_addr query_id + 2DROP // + }> + unfreeze_without_bonuses PROC:<{ + // credits freeze_dict tot_stakes + 0 PUSHINT // credits freeze_dict tot_stakes _5=0 + DUP // credits freeze_dict tot_stakes total=0 recovered=0 + -1 PUSHINT // credits freeze_dict tot_stakes total=0 recovered=0 pubkey=-1 + UNTIL:<{ + s4 PUSH + 8 PUSHPOW2 // credits freeze_dict tot_stakes total recovered pubkey freeze_dict _10=256 + DICTUGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // credits freeze_dict tot_stakes total recovered cs pubkey f + DUP // credits freeze_dict tot_stakes total recovered cs pubkey f f + IF:<{ // credits freeze_dict tot_stakes total recovered cs pubkey f + s0 s2 XCHG // credits freeze_dict tot_stakes total recovered f pubkey cs + 256 LDU // credits freeze_dict tot_stakes total recovered f pubkey _16 cs + 64 LDU // credits freeze_dict tot_stakes total recovered f pubkey _16 _42 _41 + NIP // credits freeze_dict tot_stakes total recovered f pubkey _16 cs + LDGRAMS // credits freeze_dict tot_stakes total recovered f pubkey _16 _22 cs + 1 LDI // credits freeze_dict tot_stakes total recovered f pubkey addr stake banned cs + ENDS + IF:<{ // credits freeze_dict tot_stakes total recovered f pubkey addr stake + NIP // credits freeze_dict tot_stakes total recovered f pubkey stake + s3 s3 XCPU // credits freeze_dict tot_stakes total stake f pubkey recovered stake + ADD // credits freeze_dict tot_stakes total stake f pubkey recovered + }>ELSE<{ // credits freeze_dict tot_stakes total recovered f pubkey addr stake + s8 s8 s8 XC2PU // stake freeze_dict tot_stakes total recovered f pubkey credits addr stake + ~credit_to CALLDICT // stake freeze_dict tot_stakes total recovered f pubkey credits + s0 s7 XCHG + s0 s3 XCHG // credits freeze_dict tot_stakes total stake f pubkey recovered + }> + s4 s3 XCHG2 // credits freeze_dict tot_stakes pubkey recovered f total stake + ADD // credits freeze_dict tot_stakes pubkey recovered f total + }>ELSE<{ + s4 s2 XCHG2 + DROP // credits freeze_dict tot_stakes pubkey recovered f total + }> + SWAP // credits freeze_dict tot_stakes pubkey recovered total f + NOT // credits freeze_dict tot_stakes pubkey recovered total _32 + s1 s3 XCHG // credits freeze_dict tot_stakes total recovered pubkey _32 + }> // credits freeze_dict tot_stakes total recovered pubkey + DROP + s3 POP // credits recovered tot_stakes total + SWAP // credits recovered total tot_stakes + EQUAL // credits recovered _34 + 59 THROWIFNOT + }> + unfreeze_with_bonuses PROC:<{ + // credits freeze_dict tot_stakes tot_bonuses + 0 PUSHINT // credits freeze_dict tot_stakes tot_bonuses _7=0 + s0 s0 PUSH2 // credits freeze_dict tot_stakes tot_bonuses total=0 returned_bonuses=0 recovered=0 + -1 PUSHINT // credits freeze_dict tot_stakes tot_bonuses total=0 returned_bonuses=0 recovered=0 pubkey=-1 + UNTIL:<{ + s6 PUSH + 8 PUSHPOW2 // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey freeze_dict _12=256 + DICTUGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f + DUP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f f + IF:<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f + s0 s2 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey cs + 256 LDU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 cs + 64 LDU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 _52 _51 + NIP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 cs + LDGRAMS // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 _24 cs + 1 LDI // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake banned cs + ENDS + IF:<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake + NIP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey stake + s3 s3 XCPU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered stake + ADD // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered + }>ELSE<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake + s7 s0 s8 PUSH3 // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake tot_bonuses stake tot_stakes + MULDIV // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake bonus + s6 s6 XCPU // credits freeze_dict tot_stakes tot_bonuses total bonus recovered f pubkey addr stake returned_bonuses bonus + ADD // credits freeze_dict tot_stakes tot_bonuses total bonus recovered f pubkey addr stake returned_bonuses + s1 s6 PUXC // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake stake bonus + ADD // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake _35 + s11 s11 s0 XCHG3 // stake freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey credits addr _35 + ~credit_to CALLDICT // stake freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey credits + s0 s9 XCHG + s0 s3 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered + }> + s5 s3 XCHG2 // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total stake + ADD // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total + }>ELSE<{ + s5 s2 XCHG2 + DROP // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total + }> + SWAP // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered total f + NOT // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered total _38 + s1 s4 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey _38 + }> // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey + DROP + s5 POP // credits recovered tot_stakes tot_bonuses total returned_bonuses + s0 s3 XCHG // credits recovered returned_bonuses tot_bonuses total tot_stakes + EQUAL // credits recovered returned_bonuses tot_bonuses _40 + s2 s1 PUSH2 // credits recovered returned_bonuses tot_bonuses _40 returned_bonuses tot_bonuses + LEQ // credits recovered returned_bonuses tot_bonuses _40 _41 + AND // credits recovered returned_bonuses tot_bonuses _42 + 59 THROWIFNOT + s1 s2 XCHG // credits returned_bonuses recovered tot_bonuses + ADD // credits returned_bonuses _44 + SWAP // credits _44 returned_bonuses + SUB // credits _45 + }> + unfreeze_all PROC:<{ + // credits past_elections elect_id + SWAP + 32 PUSHINT // credits elect_id past_elections _6=32 + DICTUDELGET + NULLSWAPIFNOT // credits past_elections fs f + IFNOTJMP:<{ // credits past_elections fs + DROP // credits past_elections + 0 PUSHINT // credits past_elections _8=0 + }> // credits past_elections fs + 64 LDU // credits past_elections _44 _43 + NIP // credits past_elections fs + 256 LDU // credits past_elections _46 _45 + NIP // credits past_elections fs + LDDICT // credits past_elections _21 fs + LDGRAMS // credits past_elections _21 _23 fs + LDGRAMS // credits past_elections _21 _23 _25 fs + LDDICT // credits past_elections _21 _23 _25 _54 _53 + NIP // credits past_elections fdict tot_stakes bonuses fs + ENDS + DUP // credits past_elections fdict tot_stakes bonuses bonuses + 0 GTINT // credits past_elections fdict tot_stakes bonuses _32 + IF:<{ // credits past_elections fdict tot_stakes bonuses + s3 s4 XCHG // past_elections credits fdict tot_stakes bonuses + unfreeze_with_bonuses CALLDICT // past_elections credits _33 + }>ELSE<{ // credits past_elections fdict tot_stakes bonuses + DROP // credits past_elections fdict tot_stakes + s2 s3 XCHG // past_elections credits fdict tot_stakes + unfreeze_without_bonuses CALLDICT // past_elections credits _33 + }> // past_elections credits unused_prizes + s1 s2 XCHG // credits past_elections unused_prizes + }> + config_set_confirmed PROC:<{ + // s_addr cs query_id ok + s2 POP // s_addr ok query_id + s0 s2 XCHG // query_id ok s_addr + REWRITESTDADDR // query_id ok src_wc src_addr + 0 PUSHINT // query_id ok src_wc src_addr _8=0 + CONFIGOPTPARAM // query_id ok src_wc src_addr _9 + CTOS // query_id ok src_wc src_addr _10 + 256 PLDU // query_id ok src_wc src_addr config_addr + c4 PUSH // query_id ok src_wc src_addr config_addr _14 + CTOS // query_id ok src_wc src_addr config_addr ds + LDDICT // query_id ok src_wc src_addr config_addr elect ds + s0 s4 XCHG // query_id ok ds src_addr config_addr elect src_wc + INC // query_id ok ds src_addr config_addr elect _20 + 2SWAP // query_id ok ds elect _20 src_addr config_addr + NEQ // query_id ok ds elect _20 _21 + OR // query_id ok ds elect _22 + OVER // query_id ok ds elect _22 elect + ISNULL // query_id ok ds elect _22 _23 + OR // query_id ok ds elect _24 + IFJMP:<{ // query_id ok ds elect + 4 BLKDROP // + }> // query_id ok ds elect + unpack_elect CALLDICT // query_id ok ds _63 _64 _65 _66 _67 _68 _69 + s0 s5 XCHG + 5 BLKDROP // query_id ok ds elect_at finished + s1 s4 PUXC // finished ok ds elect_at elect_at query_id + NEQ // finished ok ds elect_at _33 + s0 s4 XCHG // _33 ok ds elect_at finished + NOT // _33 ok ds elect_at _34 + s1 s4 XCHG // elect_at ok ds _33 _34 + OR // elect_at ok ds _35 + IFJMP:<{ // elect_at ok ds + 3 BLKDROP // + }> // elect_at ok ds + ACCEPT + SWAP // elect_at ds ok + IFNOT:<{ // elect_at ds + LDDICT // elect_at _40 ds + LDDICT // elect_at _40 _42 ds + LDGRAMS // elect_at credits past_elections grams ds + s3 s3 s4 XCHG3 // ds grams credits past_elections elect_at + unfreeze_all CALLDICT // ds grams credits past_elections unused_prizes + FALSE // ds grams credits past_elections unused_prizes _48 + NEWC // ds grams credits past_elections unused_prizes _48 _49 + 1 STI // ds grams credits past_elections unused_prizes _51 + s1 s3 XCHG // ds grams unused_prizes past_elections credits _51 + STDICT // ds grams unused_prizes past_elections _52 + STDICT // ds grams unused_prizes _53 + -ROT // ds _53 grams unused_prizes + ADD // ds _53 _54 + STGRAMS // ds _55 + SWAP // _55 ds + STSLICER // _56 + ENDC // _57 + c4 POP + }>ELSE<{ + 2DROP // + }> + }> + process_simple_transfer PROC:<{ + // s_addr msg_value + load_data CALLDICT // s_addr msg_value elect credits past_elect grams active_id active_hash + s0 s7 XCHG // active_hash msg_value elect credits past_elect grams active_id s_addr + REWRITESTDADDR // active_hash msg_value elect credits past_elect grams active_id src_wc src_addr + SWAP // active_hash msg_value elect credits past_elect grams active_id src_addr src_wc + INC // active_hash msg_value elect credits past_elect grams active_id src_addr _13 + OR // active_hash msg_value elect credits past_elect grams active_id _14 + OVER // active_hash msg_value elect credits past_elect grams active_id _14 active_id + 0 EQINT // active_hash msg_value elect credits past_elect grams active_id _14 _16 + OR // active_hash msg_value elect credits past_elect grams active_id _17 + IFJMP:<{ // active_hash msg_value elect credits past_elect grams active_id + s0 s5 XCHG // active_hash active_id elect credits past_elect grams msg_value + ADD // active_hash active_id elect credits past_elect grams + 2 4 BLKSWAP + SWAP // elect credits past_elect grams active_id active_hash + store_data CALLDICT + }> // active_hash msg_value elect credits past_elect grams active_id + s0 s2 PUSH2 + 32 PUSHINT // active_hash msg_value elect credits past_elect grams active_id active_id past_elect _22=32 + DICTUGET + NULLSWAPIFNOT // active_hash msg_value elect credits past_elect grams active_id fs f + IF:<{ // active_hash msg_value elect credits past_elect grams active_id fs + 64 LDU // active_hash msg_value elect credits past_elect grams active_id _30 fs + 256 LDU // active_hash msg_value elect credits past_elect grams active_id _30 _33 fs + LDDICT // active_hash msg_value elect credits past_elect grams active_id _30 _33 _36 fs + LDGRAMS // active_hash msg_value elect credits past_elect grams active_id _30 _33 _36 _38 fs + LDGRAMS // active_hash msg_value elect credits past_elect grams active_id data hash dict total_stake bonuses fs + s0 s11 XCHG // active_hash fs elect credits past_elect grams active_id data hash dict total_stake bonuses msg_value + ADD // active_hash fs elect credits past_elect grams active_id data hash dict total_stake bonuses + NEWC // active_hash fs elect credits past_elect grams active_id data hash dict total_stake bonuses _44 + s1 s5 XCHG // active_hash fs elect credits past_elect grams active_id bonuses hash dict total_stake data _44 + 64 STU // active_hash fs elect credits past_elect grams active_id bonuses hash dict total_stake _46 + s1 s3 XCHG // active_hash fs elect credits past_elect grams active_id bonuses total_stake dict hash _46 + 256 STU // active_hash fs elect credits past_elect grams active_id bonuses total_stake dict _48 + STDICT // active_hash fs elect credits past_elect grams active_id bonuses total_stake _49 + SWAP // active_hash fs elect credits past_elect grams active_id bonuses _49 total_stake + STGRAMS // active_hash fs elect credits past_elect grams active_id bonuses _50 + SWAP // active_hash fs elect credits past_elect grams active_id _50 bonuses + STGRAMS // active_hash fs elect credits past_elect grams active_id _51 + s0 s6 XCHG2 // active_hash active_id elect credits past_elect grams _51 fs + STSLICER // active_hash active_id elect credits past_elect grams _52 + SWAP + 32 PUSHINT + s6 s3 s3 PUXC2 // active_hash active_id elect credits grams _52 active_id past_elect _53=32 + DICTUSETB // active_hash active_id elect credits grams past_elect + }>ELSE<{ // active_hash msg_value elect credits past_elect grams active_id fs + DROP // active_hash msg_value elect credits past_elect grams active_id + s0 s5 XCHG // active_hash active_id elect credits past_elect grams msg_value + ADD // active_hash active_id elect credits past_elect grams + SWAP // active_hash active_id elect credits grams past_elect + }> + s3 s5 XCHG + s1 s4 s3 XCHG3 // elect credits past_elect grams active_id active_hash + store_data CALLDICT + }> + recover_stake PROC:<{ + // op s_addr cs query_id + NIP // op s_addr query_id + OVER // op s_addr query_id s_addr + REWRITESTDADDR // op s_addr query_id src_wc src_addr + SWAP // op s_addr query_id src_addr src_wc + INC // op s_addr query_id src_addr _8 + IFJMP:<{ // op s_addr query_id src_addr + DROP // op s_addr query_id + 4294967294 PUSHINT // op s_addr query_id _9=4294967294 + 0 PUSHINT // op s_addr query_id _9=4294967294 _10=0 + s3 s4 XCHG + s1 s3 XCHG + 64 PUSHINT // s_addr _9=4294967294 query_id op _10=0 _11=64 + send_message_back CALLDICT + }> // op s_addr query_id src_addr + c4 PUSH // op s_addr query_id src_addr _14 + CTOS // op s_addr query_id src_addr ds + LDDICT // op s_addr query_id src_addr _18 ds + LDDICT // op s_addr query_id src_addr elect credits ds + s3 s3 XCHG2 + 8 PUSHPOW2 // op s_addr query_id ds elect src_addr credits _25=256 + DICTUDELGET + NULLSWAPIFNOT // op s_addr query_id ds elect credits cs f + IFNOTJMP:<{ // op s_addr query_id ds elect credits cs + 4 BLKDROP // op s_addr query_id + 4294967294 PUSHINT // op s_addr query_id _27=4294967294 + 0 PUSHINT // op s_addr query_id _27=4294967294 _28=0 + s3 s4 XCHG + s1 s3 XCHG + 64 PUSHINT // s_addr _27=4294967294 query_id op _28=0 _29=64 + send_message_back CALLDICT + }> // op s_addr query_id ds elect credits cs + s6 POP // cs s_addr query_id ds elect credits + s0 s5 XCHG // credits s_addr query_id ds elect cs + LDGRAMS // credits s_addr query_id ds elect amount cs + ENDS + NEWC // credits s_addr query_id ds elect amount _35 + s1 s2 XCHG // credits s_addr query_id ds amount elect _35 + STDICT // credits s_addr query_id ds amount _36 + s1 s5 XCHG // amount s_addr query_id ds credits _36 + STDICT // amount s_addr query_id ds _37 + SWAP // amount s_addr query_id _37 ds + STSLICER // amount s_addr query_id _38 + ENDC // amount s_addr query_id _39 + c4 POP + 4184830756 PUSHINT // amount s_addr query_id _41=4184830756 + 0 PUSHINT // amount s_addr query_id _41=4184830756 _42=0 + 24 PUSHINT // amount s_addr query_id _41=4184830756 _42=0 _43=24 + NEWC // amount s_addr query_id _41=4184830756 _42=0 _43=24 _44 + 6 STU // amount s_addr query_id _41=4184830756 _42=0 _46 + s0 s4 XCHG2 // amount _42=0 query_id _41=4184830756 _46 s_addr + STSLICER // amount _42=0 query_id _41=4184830756 _47 + s0 s4 XCHG2 // _41=4184830756 _42=0 query_id _47 amount + STGRAMS // _41=4184830756 _42=0 query_id _48 + s1 s2 XCHG // _41=4184830756 query_id _42=0 _48 + 107 STU // _41=4184830756 query_id _62 + s1 s2 XCHG // query_id _41=4184830756 _62 + 32 STU // query_id _64 + 64 STU // _66 + ENDC // _67 + 64 PUSHINT // _67 _68=64 + SENDRAWMSG + }> + after_code_upgrade PROC:<{ + // s_addr cs query_id + NIP // s_addr query_id + 1313042276 PUSHINT // s_addr query_id op=1313042276 + 3460525924 PUSHINT // s_addr query_id op=1313042276 _5=3460525924 + 0 PUSHINT // s_addr query_id op=1313042276 _5=3460525924 _6=0 + s3 s3 s0 XCHG3 + 64 PUSHINT // s_addr _5=3460525924 query_id op=1313042276 _6=0 _7=64 + send_message_back CALLDICT + }> + upgrade_code PROC:<{ + // s_addr cs query_id + 0 PUSHINT // s_addr cs query_id _4=0 + CONFIGOPTPARAM // s_addr cs query_id c_addr + DUP // s_addr cs query_id c_addr c_addr + ISNULL // s_addr cs query_id c_addr _6 + IFJMP:<{ // s_addr cs query_id c_addr + 4 BLKDROP // + FALSE // _7 + }> // s_addr cs query_id c_addr + CTOS // s_addr cs query_id _9 + 256 PLDU // s_addr cs query_id config_addr + s3 PUSH // s_addr cs query_id config_addr s_addr + REWRITESTDADDR // s_addr cs query_id config_addr src_wc src_addr + SWAP // s_addr cs query_id config_addr src_addr src_wc + INC // s_addr cs query_id config_addr src_addr _16 + s0 s2 XCHG // s_addr cs query_id _16 src_addr config_addr + NEQ // s_addr cs query_id _16 _17 + OR // s_addr cs query_id _18 + IFJMP:<{ // s_addr cs query_id + 3 BLKDROP // + FALSE // _19 + }> // s_addr cs query_id + ACCEPT + SWAP // s_addr query_id cs + LDREF // s_addr query_id code cs + OVER // s_addr query_id code cs code + SETCODE + DUP // s_addr query_id code cs cs + SEMPTY // s_addr query_id code cs _25 + IFNOT:<{ // s_addr query_id code cs + SWAP // s_addr query_id cs code + c3 POP + SWAP // s_addr cs query_id + after_code_upgrade CALLDICT + 0 THROW + }>ELSE<{ + 4 BLKDROP // + }> + TRUE // _30 + }> + recv_internal PROC:<{ + // msg_value in_msg_cell in_msg + SWAP // msg_value in_msg in_msg_cell + CTOS // msg_value in_msg cs + 4 LDU // msg_value in_msg flags cs + SWAP + 1 PUSHINT // msg_value in_msg cs flags _9=1 + AND // msg_value in_msg cs _10 + IFJMP:<{ // msg_value in_msg cs + 3 BLKDROP // + }> // msg_value in_msg cs + LDMSGADDR // msg_value in_msg _61 _60 + DROP // msg_value in_msg s_addr + OVER // msg_value in_msg s_addr in_msg + SEMPTY // msg_value in_msg s_addr _14 + IFJMP:<{ // msg_value in_msg s_addr + NIP // msg_value s_addr + SWAP // s_addr msg_value + process_simple_transfer CALLDICT + }> // msg_value in_msg s_addr + SWAP // msg_value s_addr in_msg + 32 LDU // msg_value s_addr op in_msg + OVER // msg_value s_addr op in_msg op + 0 EQINT // msg_value s_addr op in_msg _21 + IFJMP:<{ // msg_value s_addr op in_msg + 2DROP // msg_value s_addr + SWAP // s_addr msg_value + process_simple_transfer CALLDICT + }> // msg_value s_addr op in_msg + 64 LDU // msg_value s_addr op query_id in_msg + s2 PUSH + 1316189259 PUSHINT // msg_value s_addr op query_id in_msg op _27=1316189259 + EQUAL // msg_value s_addr op query_id in_msg _28 + IFJMP:<{ // msg_value s_addr op query_id in_msg + s2 POP // msg_value s_addr in_msg query_id + s2 s3 XCHG // s_addr msg_value in_msg query_id + process_new_stake CALLDICT + }> // msg_value s_addr op query_id in_msg + s4 POP // in_msg s_addr op query_id + OVER + 1197831204 PUSHINT // in_msg s_addr op query_id op _30=1197831204 + EQUAL // in_msg s_addr op query_id _31 + IFJMP:<{ // in_msg s_addr op query_id + s1 s3 XCHG // op s_addr in_msg query_id + recover_stake CALLDICT + }> // in_msg s_addr op query_id + OVER + 1313042276 PUSHINT // in_msg s_addr op query_id op _33=1313042276 + EQUAL // in_msg s_addr op query_id _34 + IFJMP:<{ // in_msg s_addr op query_id + s2 s3 s3 PUXCPU // query_id s_addr op s_addr in_msg query_id + upgrade_code CALLDICT // query_id s_addr op ok + IF:<{ // query_id s_addr op + 3460525924 PUSHINT // query_id s_addr op _37=3460525924 + }>ELSE<{ // query_id s_addr op + 32 PUSHPOW2DEC // query_id s_addr op _37=4294967295 + }> + 0 PUSHINT // query_id s_addr op _37 _40=0 + s3 s4 XCHG + s3 s3 s0 XCHG3 + 64 PUSHINT // s_addr _37 query_id op _40=0 _41=64 + send_message_back CALLDICT + }> // in_msg s_addr op query_id + OVER + 4000730955 PUSHINT // in_msg s_addr op query_id op _44=4000730955 + EQUAL // in_msg s_addr op query_id cfg_ok + s2 PUSH + 4000730991 PUSHINT // in_msg s_addr op query_id cfg_ok op _46=4000730991 + EQUAL // in_msg s_addr op query_id cfg_ok _47 + s1 s(-1) PUXC // in_msg s_addr op query_id cfg_ok cfg_ok _47 + OR // in_msg s_addr op query_id cfg_ok _48 + IFJMP:<{ // in_msg s_addr op query_id cfg_ok + s2 POP // in_msg s_addr cfg_ok query_id + s2 s3 XCHG + SWAP // s_addr in_msg query_id cfg_ok + config_set_confirmed CALLDICT + }> // in_msg s_addr op query_id cfg_ok + DROP + s3 POP // query_id s_addr op + DUP + 31 PUSHPOW2 // query_id s_addr op op _52 + AND // query_id s_addr op _53 + IFNOTJMP:<{ // query_id s_addr op + 32 PUSHPOW2DEC // query_id s_addr op _54=4294967295 + 0 PUSHINT // query_id s_addr op _54=4294967295 _55=0 + s3 s4 XCHG + s3 s3 s0 XCHG3 + 64 PUSHINT // s_addr _54=4294967295 query_id op _55=0 _56=64 + send_message_back CALLDICT + }> // query_id s_addr op + 3 BLKDROP // + }> + postpone_elections PROC:<{ + // + FALSE // _0 + }> + compute_total_stake PROC:<{ + // l n m_stake + 0 PUSHINT // l n m_stake tot_stake=0 + s0 s2 XCHG // l tot_stake=0 m_stake n + REPEAT:<{ // l tot_stake m_stake + s0 s2 XCHG // m_stake tot_stake l + UNCONS // m_stake tot_stake h l + OVER // m_stake tot_stake h l h + 0 INDEX // m_stake tot_stake h l stake + s0 s2 XCHG // m_stake tot_stake stake l h + 1 INDEX // m_stake tot_stake stake l max_f + s4 PUSH // m_stake tot_stake stake l max_f m_stake + MUL // m_stake tot_stake stake l _13 + 16 RSHIFT# // m_stake tot_stake stake l _15 + s1 s2 XCHG // m_stake tot_stake l stake _15 + MIN // m_stake tot_stake l stake + s1 s2 XCHG // m_stake l tot_stake stake + ADD // m_stake l tot_stake + ROT // l tot_stake m_stake + }> + DROP + NIP // tot_stake + }> + try_elect PROC:<{ + // credits members min_stake max_stake min_total_stake max_stake_factor + 16 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor _7=16 + CONFIGOPTPARAM // credits members min_stake max_stake min_total_stake max_stake_factor _8 + CTOS // credits members min_stake max_stake min_total_stake max_stake_factor cs + 16 LDU // credits members min_stake max_stake min_total_stake max_stake_factor _13 cs + 16 LDU // credits members min_stake max_stake min_total_stake max_stake_factor _13 _253 _252 + NIP // credits members min_stake max_stake min_total_stake max_stake_factor _13 cs + 16 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators cs + ENDS + 1 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators _23=1 + MAX // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators + 0 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n=0 + NEWDICT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n=0 sdict + -1 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n=0 sdict pubkey=-1 + UNTIL:<{ + s9 PUSH + 8 PUSHPOW2 // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict pubkey members _33=256 + DICTUGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict cs pubkey f + DUP // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict cs pubkey f f + IF:<{ // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict cs pubkey f + s0 s2 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey cs + LDGRAMS // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 cs + 32 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 _42 cs + 32 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 _42 _45 cs + 256 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _40 _42 _45 _48 cs + 256 LDU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey stake time max_factor addr adnl_addr cs + ENDS + s0 s3 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey stake adnl_addr max_factor addr time + NEGATE // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey stake adnl_addr max_factor addr _56 + NEWC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey stake adnl_addr max_factor addr _56 _57 + s1 s5 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _56 adnl_addr max_factor addr stake _57 + 128 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey _56 adnl_addr max_factor addr _59 + s1 s4 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _56 _59 + 32 STI // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _61 + s4 s(-1) PUXC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor pubkey _61 + 256 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _63 + ENDC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor _64 + CTOS // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr max_factor key + s1 s10 XCPU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key max_factor max_stake_factor + MIN // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key _67 + NEWC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key _67 _68 + 32 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey addr adnl_addr key _70 + s1 s3 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey key adnl_addr addr _70 + 256 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey key adnl_addr _72 + 256 STU // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict f pubkey key _74 + s0 s1 s4 XCHG3 + 416 PUSHINT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n pubkey f _74 key sdict _79 + DICTSETB // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n pubkey f sdict + s0 s3 XCHG // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators sdict pubkey f n + INC // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators sdict pubkey f n + }>ELSE<{ + s3 s4 XCHG + 2SWAP + DROP // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators sdict pubkey f n + }> + SWAP // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators sdict pubkey n f + NOT // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators sdict pubkey n _83 + s3 s3 s0 XCHG3 // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict pubkey _83 + }> // credits members min_stake max_stake min_total_stake max_stake_factor max_validators min_validators n sdict pubkey + DROP + s4 POP // credits members min_stake max_stake min_total_stake sdict max_validators min_validators n + ROT // credits members min_stake max_stake min_total_stake sdict min_validators n max_validators + MIN // credits members min_stake max_stake min_total_stake sdict min_validators n + s0 s1 PUSH2 // credits members min_stake max_stake min_total_stake sdict min_validators n n min_validators + LESS // credits members min_stake max_stake min_total_stake sdict min_validators n _85 + IFJMP:<{ // credits members min_stake max_stake min_total_stake sdict min_validators n + 7 BLKDROP // credits + NEWDICT // credits _86 + NEWDICT // credits _86 _87 + 0 PUSHINT // credits _86 _87 _88=0 + DUP // credits _86 _87 _88=0 _89=0 + }> // credits members min_stake max_stake min_total_stake sdict min_validators n + PUSHNULL // credits members min_stake max_stake min_total_stake sdict min_validators n l + UNTIL:<{ + s0 s3 XCHG + 416 PUSHINT // credits members min_stake max_stake min_total_stake l min_validators n sdict _100 + DICTREMMIN + NULLSWAPIFNOT + NULLSWAPIFNOT // credits members min_stake max_stake min_total_stake l min_validators n sdict cs key f + DUP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs key f f + IF:<{ // credits members min_stake max_stake min_total_stake l min_validators n sdict cs key f + SWAP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key + 128 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _105 key + s1 s9 XCPU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key _105 max_stake + MIN // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key _108 + SWAP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _108 key + 32 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _108 _279 _278 + NIP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _108 key + 256 PLDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f stake pubkey + s0 s3 XCHG // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake cs + 32 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _117 cs + 256 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _117 _283 _282 + NIP // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _117 cs + 256 PLDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake max_f adnl_addr + s1 s3 s0 XCHG3 + s1 s4 XCHG // credits members min_stake max_stake min_total_stake l min_validators n sdict f stake max_f pubkey adnl_addr + 4 TUPLE // credits members min_stake max_stake min_total_stake l min_validators n sdict f _125 + s0 s5 XCHG2 // credits members min_stake max_stake min_total_stake f min_validators n sdict _125 l + CONS // credits members min_stake max_stake min_total_stake f min_validators n sdict l + }>ELSE<{ + s6 s1 s6 XCHG3 + 2DROP // credits members min_stake max_stake min_total_stake f min_validators n sdict l + }> + s0 s4 XCHG // credits members min_stake max_stake min_total_stake l min_validators n sdict f + NOT // credits members min_stake max_stake min_total_stake l min_validators n sdict _127 + s1 s4 XCHG // credits members min_stake max_stake min_total_stake sdict min_validators n l _127 + }> // credits members min_stake max_stake min_total_stake sdict min_validators n l + s3 POP + s4 POP // credits members min_stake n min_total_stake l min_validators + DEC // credits members min_stake n min_total_stake l i + 2DUP // credits members min_stake n min_total_stake l i l1 i + REPEAT:<{ // credits members min_stake n min_total_stake l i l1 + CDR // credits members min_stake n min_total_stake l i l1 + }> + 0 PUSHINT // credits members min_stake n min_total_stake l i l1 _135=0 + DUP // credits members min_stake n min_total_stake l i l1 best_stake=0 m=0 + UNTIL:<{ + s0 s2 XCHG // credits members min_stake n min_total_stake l i m best_stake l1 + UNCONS // credits members min_stake n min_total_stake l i m best_stake _138 l1 + SWAP // credits members min_stake n min_total_stake l i m best_stake l1 _138 + 0 INDEX // credits members min_stake n min_total_stake l i m best_stake l1 stake + s0 s4 XCHG // credits members min_stake n min_total_stake l stake m best_stake l1 i + INC // credits members min_stake n min_total_stake l stake m best_stake l1 i + s4 s8 PUSH2 // credits members min_stake n min_total_stake l stake m best_stake l1 i stake min_stake + GEQ // credits members min_stake n min_total_stake l stake m best_stake l1 i _144 + IF:<{ // credits members min_stake n min_total_stake l stake m best_stake l1 i + s5 s(-1) s4 PU2XC // credits members min_stake n min_total_stake l i m best_stake l1 l i stake + compute_total_stake CALLDICT // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake + s0 s2 PUSH2 // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake tot_stake best_stake + GREATER // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake _147 + IF:<{ // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake + s2 POP + s2 POP // credits members min_stake n min_total_stake l i l1 tot_stake + s2 PUSH // credits members min_stake n min_total_stake l i l1 best_stake m + }>ELSE<{ + s1 s3 XCHG + DROP // credits members min_stake n min_total_stake l i l1 best_stake m + }> + }>ELSE<{ + s3 s4 XCHG2 + DROP // credits members min_stake n min_total_stake l i l1 best_stake m + }> + s3 s6 PUSH2 // credits members min_stake n min_total_stake l i l1 best_stake m i n + GEQ // credits members min_stake n min_total_stake l i l1 best_stake m _148 + }> // credits members min_stake n min_total_stake l i l1 best_stake m + s2 POP + s2 POP + s4 POP + s4 POP // credits members best_stake m min_total_stake l + s2 PUSH // credits members best_stake m min_total_stake l m + 0 EQINT // credits members best_stake m min_total_stake l _150 + s4 s2 PUXC // credits members best_stake m _150 l best_stake min_total_stake + LESS // credits members best_stake m _150 l _151 + s1 s2 XCHG // credits members best_stake m l _150 _151 + OR // credits members best_stake m l _152 + IFJMP:<{ // credits members best_stake m l + 4 BLKDROP // credits + NEWDICT // credits _153 + NEWDICT // credits _153 _154 + 0 PUSHINT // credits _153 _154 _155=0 + DUP // credits _153 _154 _155=0 _156=0 + }> // credits members best_stake m l + DUP // credits members best_stake m l l1 + s0 DUMP // credits members best_stake m l l1 + s2 PUSH // credits members best_stake m l l1 m + DEC // credits members best_stake m l l1 _161 + REPEAT:<{ // credits members best_stake m l l1 + CDR // credits members best_stake m l l1 + }> + CAR // credits members best_stake m l _164 + 0 INDEX // credits members best_stake m l m_stake + 0 PUSHINT // credits members best_stake m l m_stake i=0 + DUP // credits members best_stake m l m_stake i=0 tot_stake=0 + NEWDICT // credits members best_stake m l m_stake i=0 tot_stake=0 vset + NEWDICT // credits members best_stake m l m_stake i=0 tot_stake=0 vset frozen + UNTIL:<{ + s0 s5 XCHG // credits members best_stake m frozen m_stake i tot_stake vset l + UNCONS // credits members best_stake m frozen m_stake i tot_stake vset _179 l + SWAP // credits members best_stake m frozen m_stake i tot_stake vset l _179 + 4 UNTUPLE // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr + s1 s12 PUSH2 + 8 PUSHPOW2 // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr pubkey members _184=256 + DICTUGET + NULLSWAPIFNOT // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr val f + 61 THROWIFNOT + LDGRAMS // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr _295 _294 + NIP // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr val + 64 LDU // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr _297 _296 + NIP // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr val + 256 PLDU // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr src_addr + s8 s11 PUSH2 // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr src_addr i m + LESS // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr src_addr _198 + IF:<{ // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr src_addr + s3 s9 XCPU // credits members best_stake m frozen m_stake i tot_stake vset l stake src_addr pubkey adnl_addr max_f m_stake + MUL // credits members best_stake m frozen m_stake i tot_stake vset l stake src_addr pubkey adnl_addr _200 + 16 RSHIFT# // credits members best_stake m frozen m_stake i tot_stake vset l stake src_addr pubkey adnl_addr _202 + s4 s(-1) PUXC // credits members best_stake m frozen m_stake i tot_stake vset l stake src_addr pubkey adnl_addr stake _202 + MIN // credits members best_stake m frozen m_stake i tot_stake vset l stake src_addr pubkey adnl_addr true_stake + s4 s4 XCPU // credits members best_stake m frozen m_stake i tot_stake vset l true_stake src_addr pubkey adnl_addr stake true_stake + SUB // credits members best_stake m frozen m_stake i tot_stake vset l true_stake src_addr pubkey adnl_addr stake + s4 PUSH // credits members best_stake m frozen m_stake i tot_stake vset l true_stake src_addr pubkey adnl_addr stake true_stake + 60 LSHIFT# // credits members best_stake m frozen m_stake i tot_stake vset l true_stake src_addr pubkey adnl_addr stake _207 + s13 PUSH // credits members best_stake m frozen m_stake i tot_stake vset l true_stake src_addr pubkey adnl_addr stake _207 best_stake + DIV // credits members best_stake m frozen m_stake i tot_stake vset l true_stake src_addr pubkey adnl_addr stake weight + s8 s5 XCPU // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake true_stake + ADD // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake + 2390828938 PUSHINT // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 + s3 PUSH // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 adnl_addr + IF:<{ // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 + 115 PUSHINT // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 _212=115 + }>ELSE<{ // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 + 83 PUSHINT // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 _212=83 + }> + NEWC // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 _212 _215 + 8 STU // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _211=2390828938 _217 + 32 STU // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _219 + s4 s(-1) PUXC // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake pubkey _219 + 256 STU // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake _221 + s9 s(-1) PUXC // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake weight _221 + 64 STU // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake vinfo + s3 PUSH // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake vinfo adnl_addr + IF:<{ // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake vinfo + s1 s3 XCHG // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey tot_stake stake adnl_addr vinfo + 256 STU // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey tot_stake stake vinfo + }>ELSE<{ + s0 s3 XCHG2 + DROP // credits members best_stake m frozen m_stake i weight vset l true_stake src_addr pubkey tot_stake stake vinfo + }> + SWAP + 16 PUSHINT + s10 s8 s8 PUXC2 // credits members best_stake m frozen m_stake i weight stake l true_stake src_addr pubkey tot_stake vinfo i vset _228=16 + DICTUSETB // credits members best_stake m frozen m_stake i weight stake l true_stake src_addr pubkey tot_stake vset + FALSE // credits members best_stake m frozen m_stake i weight stake l true_stake src_addr pubkey tot_stake vset _231 + s4 PUSH + NEWC // credits members best_stake m frozen m_stake i weight stake l true_stake src_addr pubkey tot_stake vset _231 src_addr _232 + 256 STU // credits members best_stake m frozen m_stake i weight stake l true_stake src_addr pubkey tot_stake vset _231 _234 + s1 s9 XCHG // credits members best_stake m frozen m_stake i _231 stake l true_stake src_addr pubkey tot_stake vset weight _234 + 64 STU // credits members best_stake m frozen m_stake i _231 stake l true_stake src_addr pubkey tot_stake vset _236 + s0 s5 XCHG2 // credits members best_stake m frozen m_stake i _231 stake l vset src_addr pubkey tot_stake _236 true_stake + STGRAMS // credits members best_stake m frozen m_stake i _231 stake l vset src_addr pubkey tot_stake _237 + s1 s7 XCHG // credits members best_stake m frozen m_stake i tot_stake stake l vset src_addr pubkey _231 _237 + 1 STI // credits members best_stake m frozen m_stake i tot_stake stake l vset src_addr pubkey _239 + s0 s1 s9 XCHG3 + 8 PUSHPOW2 // credits members best_stake m src_addr m_stake i tot_stake stake l vset _239 pubkey frozen _240=256 + DICTUSETB // credits members best_stake m src_addr m_stake i tot_stake stake l vset frozen + }>ELSE<{ + s0 s10 XCHG + s4 s6 XCHG + s0 s3 XCHG + 3 BLKDROP // credits members best_stake m src_addr m_stake i tot_stake stake l vset frozen + }> + s3 PUSH // credits members best_stake m src_addr m_stake i tot_stake stake l vset frozen stake + IF:<{ // credits members best_stake m src_addr m_stake i tot_stake stake l vset frozen + s11 s7 s3 XCHG3 // l members best_stake m vset m_stake i tot_stake frozen credits src_addr stake + ~credit_to CALLDICT // l members best_stake m vset m_stake i tot_stake frozen credits + }>ELSE<{ + s11 s7 s3 XCHG3 + 2DROP // l members best_stake m vset m_stake i tot_stake frozen credits + }> + s0 s3 XCHG // l members best_stake m vset m_stake credits tot_stake frozen i + INC // l members best_stake m vset m_stake credits tot_stake frozen i + s9 PUSH // l members best_stake m vset m_stake credits tot_stake frozen i l + ISNULL // l members best_stake m vset m_stake credits tot_stake frozen i _246 + s4 s10 XCHG + s4 s6 XCHG + s4 s4 s0 XCHG3 // credits members best_stake m l m_stake i tot_stake vset frozen _246 + }> // credits members best_stake m l m_stake i tot_stake vset frozen + s3 POP + s3 POP + s3 POP + s5 POP // credits frozen best_stake m tot_stake vset + s1 s3 PUXC // credits frozen vset m tot_stake tot_stake best_stake + EQUAL // credits frozen vset m tot_stake _248 + 49 THROWIFNOT + s2 s3 XCHG + SWAP // credits vset frozen tot_stake m + }> + conduct_elections PROC:<{ + // ds elect credits + SWAP // ds credits elect + unpack_elect CALLDICT // ds credits _130 _131 _132 _133 _134 _135 _136 + s4 POP // ds credits elect_at elect_close finished total_stake members failed + NOW // ds credits elect_at elect_close finished total_stake members failed _11 + s5 PUSH // ds credits elect_at elect_close finished total_stake members failed _11 elect_close + LESS // ds credits elect_at elect_close finished total_stake members failed _12 + IFJMP:<{ // ds credits elect_at elect_close finished total_stake members failed + 8 BLKDROP // + FALSE // _13 + }> // ds credits elect_at elect_close finished total_stake members failed + 0 PUSHINT // ds credits elect_at elect_close finished total_stake members failed _14=0 + CONFIGOPTPARAM // ds credits elect_at elect_close finished total_stake members failed _15 + ISNULL // ds credits elect_at elect_close finished total_stake members failed _16 + IFJMP:<{ // ds credits elect_at elect_close finished total_stake members failed + 8 BLKDROP // + postpone_elections CALLDICT // _17 + }> // ds credits elect_at elect_close finished total_stake members failed + 17 PUSHINT // ds credits elect_at elect_close finished total_stake members failed _19=17 + CONFIGOPTPARAM // ds credits elect_at elect_close finished total_stake members failed _20 + CTOS // ds credits elect_at elect_close finished total_stake members failed cs + LDGRAMS // ds credits elect_at elect_close finished total_stake members failed min_stake cs + LDGRAMS // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake cs + LDGRAMS // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake cs + 32 LDU // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor cs + ENDS + s6 s1 PUSH2 // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor total_stake min_total_stake + LESS // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor _35 + IFJMP:<{ // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor + 12 BLKDROP // + postpone_elections CALLDICT // _36 + }> // ds credits elect_at elect_close finished total_stake members failed min_stake max_stake min_total_stake max_stake_factor + s0 s4 XCHG // ds credits elect_at elect_close finished total_stake members max_stake_factor min_stake max_stake min_total_stake failed + IFJMP:<{ // ds credits elect_at elect_close finished total_stake members max_stake_factor min_stake max_stake min_total_stake + 11 BLKDROP // + postpone_elections CALLDICT // _37 + }> // ds credits elect_at elect_close finished total_stake members max_stake_factor min_stake max_stake min_total_stake + s0 s6 XCHG // ds credits elect_at elect_close min_total_stake total_stake members max_stake_factor min_stake max_stake finished + IFJMP:<{ // ds credits elect_at elect_close min_total_stake total_stake members max_stake_factor min_stake max_stake + 10 BLKDROP // + FALSE // _38 + }> // ds credits elect_at elect_close min_total_stake total_stake members max_stake_factor min_stake max_stake + s3 s8 XCHG + s8 PUSH + s3 s2 XCPU + s7 s7 XCHG2 // ds members elect_at elect_close min_stake total_stake credits members min_stake max_stake min_total_stake max_stake_factor + try_elect CALLDICT // ds members elect_at elect_close min_stake total_stake credits vdict frozen total_stakes cnt + DUP // ds members elect_at elect_close min_stake total_stake credits vdict frozen total_stakes cnt cnt + 0 EQINT // ds members elect_at elect_close min_stake total_stake credits vdict frozen total_stakes cnt failed + DUP // ds members elect_at elect_close min_stake total_stake credits vdict frozen total_stakes cnt failed failed + NOT // ds members elect_at elect_close min_stake total_stake credits vdict frozen total_stakes cnt failed finished + s10 PUSH + s0 s6 XCHG + s5 s10 XCHG + s4 s9 XCHG + s3 s8 XCHG + s12 s12 s12 XCHG3 // ds vdict elect_at frozen total_stakes cnt credits elect_at elect_close min_stake total_stake members failed finished + pack_elect CALLDICT // ds vdict elect_at frozen total_stakes cnt credits elect + s2 PUSH // ds vdict elect_at frozen total_stakes cnt credits elect cnt + IFNOTJMP:<{ // ds vdict elect_at frozen total_stakes cnt credits elect + s2 POP + s2 POP + s2 POP + s2 POP + s2 POP // ds elect credits + NEWC // ds elect credits _48 + s1 s2 XCHG // ds credits elect _48 + STDICT // ds credits _49 + STDICT // ds _50 + SWAP // _50 ds + STSLICER // _51 + ENDC // _52 + c4 POP + postpone_elections CALLDICT // _54 + }> // ds vdict elect_at frozen total_stakes cnt credits elect + get_validator_conf CALLDICT // ds vdict elect_at frozen total_stakes cnt credits elect _150 _151 _152 _153 + s2 POP // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held elect_end_before + NOW // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held elect_end_before _61 + SWAP // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held _61 elect_end_before + ADD // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held _62 + -60 ADDCONST // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held _64 + s8 PUSH // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held _64 elect_at + MAX // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start + 16 PUSHINT // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _67=16 + CONFIGOPTPARAM // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _68 + CTOS // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _69 + 16 PUSHINT // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _69 _70=16 + SDSKIPFIRST // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _71 + 16 PLDU // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start main_validators + s6 s(-1) PUXC // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start cnt main_validators + MIN // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 + s1 s3 PUSH2 // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 start elect_for + ADD // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 _76 + 17 PUSHINT // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 _76 _77=17 + NEWC // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 _76 _77=17 _78 + 8 STU // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 _76 _80 + s3 s(-1) PUXC // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 _76 start _80 + 32 STU // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 _76 _82 + 32 STU // ds vdict elect_at frozen total_stakes cnt credits elect elect_for stake_held start _75 _84 + s1 s7 XCHG // ds vdict elect_at frozen total_stakes _75 credits elect elect_for stake_held start cnt _84 + 16 STU // ds vdict elect_at frozen total_stakes _75 credits elect elect_for stake_held start _86 + s1 s6 XCHG // ds vdict elect_at frozen total_stakes start credits elect elect_for stake_held _75 _86 + 16 STU // ds vdict elect_at frozen total_stakes start credits elect elect_for stake_held _88 + s0 s9 XCHG // ds _88 elect_at frozen total_stakes start credits elect elect_for stake_held vdict + CTOS // ds _88 elect_at frozen total_stakes start credits elect elect_for stake_held _89 + s1 s9 XCHG // ds stake_held elect_at frozen total_stakes start credits elect elect_for _88 _89 + STSLICER // ds stake_held elect_at frozen total_stakes start credits elect elect_for _90 + ENDC // ds stake_held elect_at frozen total_stakes start credits elect elect_for vset + 0 PUSHINT // ds stake_held elect_at frozen total_stakes start credits elect elect_for vset _93=0 + CONFIGOPTPARAM // ds stake_held elect_at frozen total_stakes start credits elect elect_for vset _94 + CTOS // ds stake_held elect_at frozen total_stakes start credits elect elect_for vset _95 + 256 PLDU // ds stake_held elect_at frozen total_stakes start credits elect elect_for vset config_addr + s1 s8 PUSH2 // ds stake_held elect_at frozen total_stakes start credits elect elect_for vset config_addr vset elect_at + send_validator_set_to_config CALLDICT + s0 s9 XCHG // vset stake_held elect_at frozen total_stakes start credits elect elect_for ds + LDDICT // vset stake_held elect_at frozen total_stakes start credits elect elect_for past_elect ds + FALSE // vset stake_held elect_at frozen total_stakes start credits elect elect_for past_elect ds _103 + s0 s11 XCHG // _103 stake_held elect_at frozen total_stakes start credits elect elect_for past_elect ds vset + HASHCU // _103 stake_held elect_at frozen total_stakes start credits elect elect_for past_elect ds _104 + s6 s3 XCHG2 // _103 stake_held elect_at frozen total_stakes ds credits elect _104 past_elect start elect_for + ADD // _103 stake_held elect_at frozen total_stakes ds credits elect _104 past_elect _105 + s9 PUSH // _103 stake_held elect_at frozen total_stakes ds credits elect _104 past_elect _105 stake_held + ADD // _103 stake_held elect_at frozen total_stakes ds credits elect _104 past_elect _106 + NEWC // _103 stake_held elect_at frozen total_stakes ds credits elect _104 past_elect _106 _107 + 32 STU // _103 stake_held elect_at frozen total_stakes ds credits elect _104 past_elect _109 + s1 s9 XCHG // _103 past_elect elect_at frozen total_stakes ds credits elect _104 stake_held _109 + 32 STU // _103 past_elect elect_at frozen total_stakes ds credits elect _104 _111 + 256 STU // _103 past_elect elect_at frozen total_stakes ds credits elect _113 + s1 s5 XCHG // _103 past_elect elect_at elect total_stakes ds credits frozen _113 + STDICT // _103 past_elect elect_at elect total_stakes ds credits _114 + s0 s3 XCHG2 // _103 past_elect elect_at elect credits ds _114 total_stakes + STGRAMS // _103 past_elect elect_at elect credits ds _115 + 0 PUSHINT // _103 past_elect elect_at elect credits ds _115 _116=0 + STGRAMS // _103 past_elect elect_at elect credits ds _117 + s1 s6 XCHG // ds past_elect elect_at elect credits _103 _117 + 1 STI // ds past_elect elect_at elect credits _119 + s0 s3 s4 XCHG3 + 32 PUSHINT // ds elect credits _119 elect_at past_elect _120=32 + DICTUSETB // ds elect credits past_elect + NEWC // ds elect credits past_elect _122 + s1 s3 XCHG // ds past_elect credits elect _122 + STDICT // ds past_elect credits _123 + STDICT // ds past_elect _124 + STDICT // ds _125 + SWAP // _125 ds + STSLICER // _126 + ENDC // _127 + c4 POP + TRUE // _129 + }> + update_active_vset_id PROC:<{ + // + load_data CALLDICT // elect credits past_elect grams active_id active_hash + 34 PUSHINT // elect credits past_elect grams active_id active_hash _8=34 + CONFIGOPTPARAM // elect credits past_elect grams active_id active_hash _9 + HASHCU // elect credits past_elect grams active_id active_hash cur_hash + s0 s1 PUSH2 // elect credits past_elect grams active_id active_hash cur_hash cur_hash active_hash + EQUAL // elect credits past_elect grams active_id active_hash cur_hash _11 + IFJMP:<{ // elect credits past_elect grams active_id active_hash cur_hash + 7 BLKDROP // + FALSE // _12 + }> // elect credits past_elect grams active_id active_hash cur_hash + s2 PUSH // elect credits past_elect grams active_id active_hash cur_hash active_id + IF:<{ // elect credits past_elect grams active_id active_hash cur_hash + s2 s4 PUSH2 + 32 PUSHINT // elect credits past_elect grams active_id active_hash cur_hash active_id past_elect _15=32 + DICTUGET + NULLSWAPIFNOT // elect credits past_elect grams active_id active_hash cur_hash fs f + IF:<{ // elect credits past_elect grams active_id active_hash cur_hash fs + 32 LDU // elect credits past_elect grams active_id active_hash cur_hash _99 _98 + NIP // elect credits past_elect grams active_id active_hash cur_hash fs + DUP // elect credits past_elect grams active_id active_hash cur_hash fs0 fs + 32 LDU // elect credits past_elect grams active_id active_hash cur_hash fs0 _24 fs + 256 LDU // elect credits past_elect grams active_id active_hash cur_hash fs0 _24 _103 _102 + DROP // elect credits past_elect grams active_id active_hash cur_hash fs0 stake_held hash + s0 s4 XCHG2 // elect credits past_elect grams active_id stake_held cur_hash fs0 hash active_hash + EQUAL // elect credits past_elect grams active_id stake_held cur_hash fs0 _31 + 57 THROWIFNOT + NOW // elect credits past_elect grams active_id stake_held cur_hash fs0 _33 + s0 s3 XCHG2 // elect credits past_elect grams active_id fs0 cur_hash _33 stake_held + ADD // elect credits past_elect grams active_id fs0 cur_hash unfreeze_time + NEWC // elect credits past_elect grams active_id fs0 cur_hash unfreeze_time _36 + 32 STU // elect credits past_elect grams active_id fs0 cur_hash _38 + ROT // elect credits past_elect grams active_id cur_hash _38 fs0 + STSLICER // elect credits past_elect grams active_id cur_hash _39 + s0 s0 s4 XCHG3 + 32 PUSHINT // elect credits cur_hash grams _39 active_id past_elect _40=32 + DICTUSETB // elect credits cur_hash grams past_elect + }>ELSE<{ + s1 s5 XCHG + s1 s3 XCHG + 3 BLKDROP // elect credits cur_hash grams past_elect + }> + }>ELSE<{ + s4 s1 s4 XCHG3 + 2DROP // elect credits cur_hash grams past_elect + }> + -1 PUSHINT // elect credits cur_hash grams past_elect id=-1 + UNTIL:<{ + OVER + 32 PUSHINT // elect credits cur_hash grams past_elect id past_elect _46=32 + DICTUGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // elect credits cur_hash grams past_elect fs id f + DUP // elect credits cur_hash grams past_elect fs id f f + IF:<{ // elect credits cur_hash grams past_elect fs id f + s0 s2 XCHG // elect credits cur_hash grams past_elect f id fs + 64 LDU // elect credits cur_hash grams past_elect f id _50 fs + 256 LDU // elect credits cur_hash grams past_elect f id tm hash fs + s1 s7 PUSH2 // elect credits cur_hash grams past_elect f id tm hash fs hash cur_hash + EQUAL // elect credits cur_hash grams past_elect f id tm hash fs _56 + IF:<{ // elect credits cur_hash grams past_elect f id tm hash fs + s4 POP // elect credits cur_hash grams past_elect fs id tm hash + s0 s3 XCHG // elect credits cur_hash grams past_elect hash id tm fs + LDDICT // elect credits cur_hash grams past_elect hash id tm _60 fs + LDGRAMS // elect credits cur_hash grams past_elect hash id tm _60 _62 fs + LDGRAMS // elect credits cur_hash grams past_elect hash id tm dict total_stake bonuses fs + s8 PUSH // elect credits cur_hash grams past_elect hash id tm dict total_stake bonuses fs grams + 3 RSHIFT# // elect credits cur_hash grams past_elect hash id tm dict total_stake bonuses fs amount + s9 s9 XCPU // elect credits cur_hash amount past_elect hash id tm dict total_stake bonuses fs grams amount + SUB // elect credits cur_hash amount past_elect hash id tm dict total_stake bonuses fs grams + s2 s9 XCHG2 // elect credits cur_hash grams past_elect hash id tm dict total_stake fs bonuses amount + ADD // elect credits cur_hash grams past_elect hash id tm dict total_stake fs bonuses + NEWC // elect credits cur_hash grams past_elect hash id tm dict total_stake fs bonuses _72 + s1 s5 XCHG // elect credits cur_hash grams past_elect hash id bonuses dict total_stake fs tm _72 + 64 STU // elect credits cur_hash grams past_elect hash id bonuses dict total_stake fs _74 + s1 s6 XCHG // elect credits cur_hash grams past_elect fs id bonuses dict total_stake hash _74 + 256 STU // elect credits cur_hash grams past_elect fs id bonuses dict total_stake _76 + s1 s2 XCHG // elect credits cur_hash grams past_elect fs id bonuses total_stake dict _76 + STDICT // elect credits cur_hash grams past_elect fs id bonuses total_stake _77 + SWAP // elect credits cur_hash grams past_elect fs id bonuses _77 total_stake + STGRAMS // elect credits cur_hash grams past_elect fs id bonuses _78 + SWAP // elect credits cur_hash grams past_elect fs id _78 bonuses + STGRAMS // elect credits cur_hash grams past_elect fs id _79 + ROT // elect credits cur_hash grams past_elect id _79 fs + STSLICER // elect credits cur_hash grams past_elect id _80 + SWAP + 32 PUSHINT + s1 s3 s3 PUXC2 // elect credits cur_hash grams id _80 id past_elect _81=32 + DICTUSETB // elect credits cur_hash grams id past_elect + FALSE // elect credits cur_hash grams id past_elect f + }>ELSE<{ + s3 s5 XCHG + s3 s4 XCHG + 3 BLKDROP // elect credits cur_hash grams id past_elect f + }> + }>ELSE<{ + s3 s0 s3 XCHG3 + DROP // elect credits cur_hash grams id past_elect f + }> + NOT // elect credits cur_hash grams id past_elect _84 + s1 s2 XCHG // elect credits cur_hash grams past_elect id _84 + }> // elect credits cur_hash grams past_elect id + DUP // elect credits cur_hash grams past_elect id id + ISNULL // elect credits cur_hash grams past_elect id _85 + IF:<{ // elect credits cur_hash grams past_elect id + DROP // elect credits cur_hash grams past_elect + 0 PUSHINT // elect credits cur_hash grams past_elect _86=0 + }>ELSE<{ // elect credits cur_hash grams past_elect _86 + }> // elect credits active_hash grams past_elect active_id + s0 s3 XCHG2 // elect credits past_elect grams active_id active_hash + store_data CALLDICT + TRUE // _89 + }> + cell_hash_eq? PROC:<{ + // vset expected_vset_hash + OVER // vset expected_vset_hash vset + ISNULL // vset expected_vset_hash _2 + IF:<{ // vset expected_vset_hash + 2DROP // + FALSE // _3 + }>ELSE<{ // vset expected_vset_hash + SWAP // expected_vset_hash vset + HASHCU // expected_vset_hash _5 + SWAP // _5 expected_vset_hash + EQUAL // _3 + }> + }> + validator_set_installed PROC:<{ + // ds elect credits + SWAP // ds credits elect + unpack_elect CALLDICT // ds credits _44 _45 _46 _47 _48 _49 _50 + s0 s5 XCHG + 5 BLKDROP // ds credits elect_at finished + IFNOTJMP:<{ // ds credits elect_at + 3 BLKDROP // + FALSE // _11 + }> // ds credits elect_at + s0 s2 XCHG // elect_at credits ds + LDDICT // elect_at credits past_elections ds + s3 s1 XCPU + 32 PUSHINT // ds credits past_elections elect_at past_elections _17=32 + DICTUGET + NULLSWAPIFNOT // ds credits past_elections fs f + IFNOTJMP:<{ // ds credits past_elections fs + 4 BLKDROP // + FALSE // _19 + }> // ds credits past_elections fs + 64 PUSHINT // ds credits past_elections fs _21=64 + SDSKIPFIRST // ds credits past_elections _22 + 256 PLDU // ds credits past_elections vset_hash + 34 PUSHINT // ds credits past_elections vset_hash _25=34 + CONFIGOPTPARAM // ds credits past_elections vset_hash _26 + OVER // ds credits past_elections vset_hash _26 vset_hash + cell_hash_eq? CALLDICT // ds credits past_elections vset_hash _27 + 36 PUSHINT // ds credits past_elections vset_hash _27 _28=36 + CONFIGOPTPARAM // ds credits past_elections vset_hash _27 _29 + ROT // ds credits past_elections _27 _29 vset_hash + cell_hash_eq? CALLDICT // ds credits past_elections _27 _30 + OR // ds credits past_elections _31 + IFJMP:<{ // ds credits past_elections + FALSE // ds credits past_elections _32 + NEWC // ds credits past_elections _32 _33 + 1 STI // ds credits past_elections _35 + s1 s2 XCHG // ds past_elections credits _35 + STDICT // ds past_elections _36 + STDICT // ds _37 + SWAP // _37 ds + STSLICER // _38 + ENDC // _39 + c4 POP + update_active_vset_id CALLDICT // _41 + DROP // + TRUE // _42 + }> // ds credits past_elections + 3 BLKDROP // + FALSE // _43 + }> + check_unfreeze PROC:<{ + // + load_data CALLDICT // elect credits past_elect grams active_id active_hash + -1 PUSHINT // elect credits past_elect grams active_id active_hash id=-1 + UNTIL:<{ + s4 PUSH + 32 PUSHINT // elect credits past_elect grams active_id active_hash id past_elect _11=32 + DICTUGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // elect credits past_elect grams active_id active_hash fs id f + DUP // elect credits past_elect grams active_id active_hash fs id f f + IF:<{ // elect credits past_elect grams active_id active_hash fs id f + s0 s2 XCHG // elect credits past_elect grams active_id active_hash f id fs + 32 LDU // elect credits past_elect grams active_id active_hash f id _39 _38 + DROP // elect credits past_elect grams active_id active_hash f id unfreeze_at + NOW // elect credits past_elect grams active_id active_hash f id unfreeze_at _17 + LEQ // elect credits past_elect grams active_id active_hash f id _18 + s1 s4 PUSH2 // elect credits past_elect grams active_id active_hash f id _18 id active_id + NEQ // elect credits past_elect grams active_id active_hash f id _18 _19 + AND // elect credits past_elect grams active_id active_hash f id _20 + IF:<{ // elect credits past_elect grams active_id active_hash f id + NIP // elect credits past_elect grams active_id active_hash id + s5 s4 s4 XC2PU // elect active_hash id grams active_id credits past_elect id + unfreeze_all CALLDICT // elect active_hash id grams active_id credits past_elect unused_prizes + s1 s4 XCHG // elect active_hash id past_elect active_id credits grams unused_prizes + ADD // elect active_hash id past_elect active_id credits grams + s6 s1 s3 PUSH3 + s3 s5 s8 PUSH3 // elect active_hash id past_elect active_id credits grams elect credits past_elect grams active_id active_hash + store_data CALLDICT + FALSE // elect active_hash id past_elect active_id credits grams f + }>ELSE<{ + s6 s1 s5 XCHG3 + s4 s4 XCHG2 // elect active_hash id past_elect active_id credits grams f + }> + }>ELSE<{ + s3 s7 XCHG + s1 s6 XCHG + s5 s0 s5 XCHG3 + DROP // elect active_hash id past_elect active_id credits grams f + }> + NOT // elect active_hash id past_elect active_id credits grams _26 + s2 s6 XCHG + s4 s5 XCHG + s1 s4 XCHG // elect credits past_elect grams active_id active_hash id _26 + }> // elect credits past_elect grams active_id active_hash id + s0 s6 XCHG + 6 BLKDROP // id + ISNULL // _27 + NOT // _28 + }> + announce_new_elections PROC:<{ + // ds elect credits + NIP // ds credits + 36 PUSHINT // ds credits _4=36 + CONFIGOPTPARAM // ds credits next_vset + ISNULL // ds credits _6 + IFNOTJMP:<{ // ds credits + 2DROP // + FALSE // _7 + }> // ds credits + 1 PUSHINT // ds credits _9=1 + CONFIGOPTPARAM // ds credits _10 + CTOS // ds credits _11 + 256 PLDU // ds credits elector_addr + MYADDR // ds credits elector_addr _16 + REWRITESTDADDR // ds credits elector_addr my_wc my_addr + SWAP // ds credits elector_addr my_addr my_wc + INC // ds credits elector_addr my_addr _19 + s0 s2 XCHG // ds credits _19 my_addr elector_addr + NEQ // ds credits _19 _20 + OR // ds credits _21 + IFJMP:<{ // ds credits + 2DROP // + FALSE // _22 + }> // ds credits + 34 PUSHINT // ds credits _24=34 + CONFIGOPTPARAM // ds credits cur_vset + DUP // ds credits cur_vset cur_vset + ISNULL // ds credits cur_vset _26 + IFJMP:<{ // ds credits cur_vset + 3 BLKDROP // + FALSE // _27 + }> // ds credits cur_vset + get_validator_conf CALLDICT // ds credits cur_vset _76 _77 _78 _79 + DROP + s2 POP // ds credits cur_vset elect_end_before elect_begin_before + s0 s2 XCHG // ds credits elect_begin_before elect_end_before cur_vset + CTOS // ds credits elect_begin_before elect_end_before _34 + 40 PUSHINT // ds credits elect_begin_before elect_end_before _34 _37 + SDSKIPFIRST // ds credits elect_begin_before elect_end_before _38 + 32 PLDU // ds credits elect_begin_before elect_end_before cur_valid_until + NOW // ds credits elect_begin_before elect_end_before cur_valid_until t + s1 s3 XCPU // ds credits elect_begin_before elect_end_before t cur_valid_until elect_begin_before + SUB // ds credits elect_begin_before elect_end_before t t0 + 2DUP // ds credits elect_begin_before elect_end_before t t0 t t0 + LESS // ds credits elect_begin_before elect_end_before t t0 _45 + IFJMP:<{ // ds credits elect_begin_before elect_end_before t t0 + 6 BLKDROP // + FALSE // _46 + }> // ds credits elect_begin_before elect_end_before t t0 + 2DUP // ds credits elect_begin_before elect_end_before t t0 t t0 + SUB // ds credits elect_begin_before elect_end_before t t0 _47 + 60 LESSINT // ds credits elect_begin_before elect_end_before t t0 _49 + IF:<{ // ds credits elect_begin_before elect_end_before t t0 + NIP // ds credits elect_begin_before elect_end_before t + }>ELSE<{ + DROP // ds credits elect_begin_before elect_end_before t + }> + 17 PUSHINT // ds credits elect_begin_before elect_end_before t _52=17 + CONFIGOPTPARAM // ds credits elect_begin_before elect_end_before t _53 + CTOS // ds credits elect_begin_before elect_end_before t _54 + LDGRAMS // ds credits elect_begin_before elect_end_before t _81 _80 + DROP // ds credits elect_begin_before elect_end_before t min_stake + s0 s3 XCHG // ds credits min_stake elect_end_before t elect_begin_before + ADD // ds credits min_stake elect_end_before elect_at + s0 DUMP // ds credits min_stake elect_end_before elect_at + s0 s1 PUXC // ds credits min_stake elect_at elect_at elect_end_before + SUB // ds credits min_stake elect_at elect_close + 0 PUSHINT // ds credits min_stake elect_at elect_close _62=0 + NEWDICT // ds credits min_stake elect_at elect_close _62=0 _63 + FALSE // ds credits min_stake elect_at elect_close _62=0 _63 _64 + s4 s5 XCHG + s3 s4 XCHG + FALSE // ds credits elect_at elect_close min_stake _62=0 _63 _64 _65 + pack_elect CALLDICT // ds credits elect + NEWC // ds credits elect _67 + STDICT // ds credits _68 + STDICT // ds _69 + SWAP // _69 ds + STSLICER // _70 + ENDC // _71 + c4 POP + TRUE // _73 + }> + run_ticktock PROC:<{ + // is_tock + DROP // + c4 PUSH // _2 + CTOS // ds + LDDICT // _6 ds + LDDICT // elect credits ds + s2 PUSH // elect credits ds elect + ISNULL // elect credits ds _10 + IF:<{ // elect credits ds + -ROT // ds elect credits + announce_new_elections CALLDICT // _18 + 0 THROWIF + }>ELSE<{ // elect credits ds + s0 s2 s1 PUSH3 // elect credits ds ds elect credits + conduct_elections CALLDICT // elect credits ds _12 + 0 THROWIF + -ROT // ds elect credits + validator_set_installed CALLDICT // _15 + 0 THROWIF + }> + update_active_vset_id CALLDICT // _21 + 0 THROWIF + check_unfreeze CALLDICT // _23 + DROP // + }> + active_election_id PROC:<{ + // + c4 PUSH // _1 + CTOS // _2 + PLDDICT // elect + DUP // elect elect + ISNULL // elect _4 + IF:<{ // elect + DROP // + 0 PUSHINT // _5=0 + }>ELSE<{ // elect + CTOS // _7 + 32 PLDU // _5 + }> + }> + participates_in PROC:<{ + // validator_pubkey + c4 PUSH // validator_pubkey _2 + CTOS // validator_pubkey _3 + PLDDICT // validator_pubkey elect + DUP // validator_pubkey elect elect + ISNULL // validator_pubkey elect _5 + IFJMP:<{ // validator_pubkey elect + 2DROP // + 0 PUSHINT // _6=0 + }> // validator_pubkey elect + unpack_elect CALLDICT // validator_pubkey _23 _24 _25 _26 _27 _28 _29 + s2 s6 XCHG + 6 BLKDROP // validator_pubkey members + 8 PUSHPOW2 // validator_pubkey members _17=256 + DICTUGET + NULLSWAPIFNOT // mem found + IF:<{ // mem + LDGRAMS // _33 _32 + DROP // _19 + }>ELSE<{ // mem + DROP // + 0 PUSHINT // _19=0 + }> + }> + participant_list PROC:<{ + // + c4 PUSH // _1 + CTOS // _2 + PLDDICT // elect + DUP // elect elect + ISNULL // elect _4 + IFJMP:<{ // elect + DROP // + PUSHNULL // _5 + }> // elect + unpack_elect CALLDICT // _35 _36 _37 _38 _39 _40 _41 + s2 s6 XCHG + 6 BLKDROP // members + PUSHNULL // members l + 256 PUSHPOW2DEC // members l id + UNTIL:<{ + s2 PUSH + 8 PUSHPOW2 // members l id members _28=256 + DICTUGETPREV + NULLSWAPIFNOT + NULLSWAPIFNOT // members l fs id f + DUP // members l fs id f f + IF:<{ // members l fs id f + s0 s2 XCHG // members l f id fs + LDGRAMS // members l f id _46 _45 + DROP // members l f id _30 + s1 s(-1) PUXC // members l f id id _30 + PAIR // members l f id _32 + s0 s3 XCHG2 // members id f _32 l + CONS // members id f l + }>ELSE<{ + 2SWAP + DROP // members id f l + }> + SWAP // members id l f + NOT // members id l _34 + s1 s2 XCHG // members l id _34 + }> // members l id + DROP + NIP // l + }> + compute_returned_stake PROC:<{ + // wallet_addr + c4 PUSH // wallet_addr _2 + CTOS // wallet_addr cs + LDDICT // wallet_addr _19 _18 + NIP // wallet_addr cs + LDDICT // wallet_addr _21 _20 + DROP // wallet_addr credits + 8 PUSHPOW2 // wallet_addr credits _12=256 + DICTUGET + NULLSWAPIFNOT // val f + IF:<{ // val + LDGRAMS // _25 _24 + DROP // _14 + }>ELSE<{ // val + DROP // + 0 PUSHINT // _14=0 + }> + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.cpp new file mode 100644 index 0000000000..ecc0b71d8e --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.cpp @@ -0,0 +1 @@ +with_tvm_code("highload-wallet", "te6ccgEBBgEAhgABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.fif new file mode 100644 index 0000000000..d2122a96fb --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-code.fif @@ -0,0 +1,79 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-code.fc` +PROGRAM{ + DECLPROC recv_internal + DECLPROC recv_external + 85143 DECLMETHOD seqno + recv_internal PROC:<{ + // in_msg + DROP // + }> + recv_external PROC:<{ + // in_msg + 9 PUSHPOW2 // in_msg _3=512 + LDSLICEX // signature in_msg + DUP // signature in_msg cs + 32 LDU // signature in_msg _9 cs + 32 LDU // signature in_msg _9 _12 cs + 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs + NOW // signature in_msg subwallet_id valid_until msg_seqno cs _19 + s1 s3 XCHG // signature in_msg subwallet_id cs msg_seqno valid_until _19 + LEQ // signature in_msg subwallet_id cs msg_seqno _20 + 35 THROWIF + c4 PUSH // signature in_msg subwallet_id cs msg_seqno _23 + CTOS // signature in_msg subwallet_id cs msg_seqno ds + 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 ds + 32 LDU // signature in_msg subwallet_id cs msg_seqno _28 _31 ds + 256 LDU // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds + ENDS + s3 s2 XCPU // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet msg_seqno stored_seqno + EQUAL // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet _39 + 33 THROWIFNOT + s4 s4 XCPU // signature in_msg stored_subwallet cs public_key stored_seqno subwallet_id stored_subwallet + EQUAL // signature in_msg stored_subwallet cs public_key stored_seqno _42 + 34 THROWIFNOT + s0 s4 XCHG // signature stored_seqno stored_subwallet cs public_key in_msg + HASHSU // signature stored_seqno stored_subwallet cs public_key _45 + s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs _45 signature public_key + CHKSIGNU // public_key stored_seqno stored_subwallet cs _46 + 35 THROWIFNOT + LDDICT // public_key stored_seqno stored_subwallet dict cs + ENDS + ACCEPT + -1 PUSHINT // public_key stored_seqno stored_subwallet dict i=-1 + UNTIL:<{ + OVER + 16 PUSHINT // public_key stored_seqno stored_subwallet dict i dict _57=16 + DICTIGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // public_key stored_seqno stored_subwallet dict cs i f + DUP // public_key stored_seqno stored_subwallet dict cs i f f + IF:<{ // public_key stored_seqno stored_subwallet dict cs i f + s0 s2 XCHG // public_key stored_seqno stored_subwallet dict f i cs + 8 LDU // public_key stored_seqno stored_subwallet dict f i mode cs + LDREF // public_key stored_seqno stored_subwallet dict f i mode _100 _99 + DROP // public_key stored_seqno stored_subwallet dict f i mode _63 + SWAP // public_key stored_seqno stored_subwallet dict f i _63 mode + SENDRAWMSG + }>ELSE<{ + s2 POP // public_key stored_seqno stored_subwallet dict f i + }> + SWAP // public_key stored_seqno stored_subwallet dict i f + NOT // public_key stored_seqno stored_subwallet dict i _66 + }> // public_key stored_seqno stored_subwallet dict i + 2DROP // public_key stored_seqno stored_subwallet + SWAP // public_key stored_subwallet stored_seqno + INC // public_key stored_subwallet _68 + NEWC // public_key stored_subwallet _68 _69 + 32 STU // public_key stored_subwallet _71 + 32 STU // public_key _73 + 256 STU // _75 + ENDC // _76 + c4 POP + }> + seqno PROC:<{ + // + c4 PUSH // _0 + CTOS // _1 + 32 PLDU // _3 + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.cpp new file mode 100644 index 0000000000..ca5d2c70f7 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.cpp @@ -0,0 +1 @@ +with_tvm_code("highoad-wallet-v2", "te6ccgEBBwEA1wABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQHu8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44YIYAQ9HhvoW+hIJgC0wfUMAH7AJEy4gGz5luDJaHIQDSAQPRDiuYxyBLLHxPLP8v/9ADJ7VQGAATQMABBoZfl2omhpj5jpn+n/mPoCaKkQQCB6BzfQmMktv8ld0fFADoggED0lm+hb6EyURCUMFMDud4gkjM2k0MTW+IBsw=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.fif new file mode 100644 index 0000000000..9d5e467de5 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/highload-wallet-v2-code.fif @@ -0,0 +1,134 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-v2-code.fc` +PROGRAM{ + DECLPROC recv_internal + DECLPROC recv_external + 117746 DECLMETHOD processed? + recv_internal PROC:<{ + // in_msg + DROP // + }> + recv_external PROC:<{ + // in_msg + 9 PUSHPOW2 // in_msg _3=512 + LDSLICEX // signature in_msg + DUP // signature in_msg cs + 32 LDU // signature in_msg _8 cs + 64 LDU // signature in_msg subwallet_id query_id cs + NOW // signature in_msg subwallet_id query_id cs _15 + 32 LSHIFT# // signature in_msg subwallet_id query_id cs bound + s2 s0 PUSH2 // signature in_msg subwallet_id query_id cs bound query_id bound + LESS // signature in_msg subwallet_id query_id cs bound _19 + 35 THROWIF + c4 PUSH // signature in_msg subwallet_id query_id cs bound _22 + CTOS // signature in_msg subwallet_id query_id cs bound ds + 32 LDU // signature in_msg subwallet_id query_id cs bound _28 ds + 64 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 ds + 256 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 _34 ds + LDDICT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries ds + ENDS + s6 s0 PUSH2 + 64 PUSHINT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries query_id old_queries _42=64 + DICTUGET + NULLSWAPIFNOT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries _115 _116 + NIP // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries found? + 32 THROWIF + s7 s3 XCPU // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key subwallet_id stored_subwallet + EQUAL // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key _47 + 34 THROWIFNOT + s0 s7 XCHG // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned in_msg + HASHSU // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned _50 + s0 s8 s7 XC2PU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _50 signature public_key + CHKSIGNU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _51 + 35 THROWIFNOT + s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound cs + LDDICT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs + ENDS + ACCEPT + -1 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i=-1 + UNTIL:<{ + OVER + 16 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i dict _62=16 + DICTIGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f + DUP // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f f + IF:<{ // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f + s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i cs + 8 LDU // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode cs + LDREF // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _125 _124 + DROP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _68 + SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i _68 mode + SENDRAWMSG + }>ELSE<{ + s2 POP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i + }> + SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict i f + NOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i _71 + }> // last_cleaned public_key old_queries query_id stored_subwallet bound dict i + 2DROP // last_cleaned public_key old_queries query_id stored_subwallet bound + 38 PUSHPOW2 // last_cleaned public_key old_queries query_id stored_subwallet bound _74 + SUB // last_cleaned public_key old_queries query_id stored_subwallet bound + NEWC // last_cleaned public_key old_queries query_id stored_subwallet bound _77 + s0 s3 s4 XCHG3 + 64 PUSHINT // last_cleaned public_key stored_subwallet bound _77 query_id old_queries _78=64 + DICTUSETB // last_cleaned public_key stored_subwallet bound old_queries + UNTIL:<{ + DUP + 64 PUSHINT // last_cleaned public_key stored_subwallet bound old_queries old_queries _85=64 + DICTUREMMIN + NULLSWAPIFNOT + NULLSWAPIFNOT // last_cleaned public_key stored_subwallet bound old_queries _126 _128 _127 _129 + s2 POP // last_cleaned public_key stored_subwallet bound old_queries old_queries' f i + s1 s0 XCPU // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f + IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f + DROP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i + s0 s3 PUSH2 // last_cleaned public_key stored_subwallet bound old_queries old_queries' i i bound + LESS // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f + }> // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f + DUP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f + IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f + s3 POP + s6 POP // last_cleaned public_key stored_subwallet bound f old_queries + }>ELSE<{ + s3 s1 s3 XCHG3 + 2DROP // last_cleaned public_key stored_subwallet bound f old_queries + }> + SWAP // last_cleaned public_key stored_subwallet bound old_queries f + NOT // last_cleaned public_key stored_subwallet bound old_queries _90 + }> // last_cleaned public_key stored_subwallet bound old_queries + NIP // last_cleaned public_key stored_subwallet old_queries + NEWC // last_cleaned public_key stored_subwallet old_queries _91 + s1 s2 XCHG // last_cleaned public_key old_queries stored_subwallet _91 + 32 STU // last_cleaned public_key old_queries _93 + s1 s3 XCHG // old_queries public_key last_cleaned _93 + 64 STU // old_queries public_key _95 + 256 STU // old_queries _97 + STDICT // _98 + ENDC // _99 + c4 POP + }> + processed? PROC:<{ + // query_id + c4 PUSH // query_id _2 + CTOS // query_id ds + 32 LDU // query_id _29 _28 + NIP // query_id ds + 64 LDU // query_id _11 ds + 256 LDU // query_id _11 _33 _32 + NIP // query_id _11 ds + LDDICT // query_id last_cleaned old_queries ds + ENDS + s2 s(-1) PUXC + 64 PUSHINT // query_id last_cleaned query_id old_queries _22=64 + DICTUGET + NULLSWAPIFNOT // query_id last_cleaned _36 _37 + NIP // query_id last_cleaned found + IF:<{ // query_id last_cleaned + 2DROP // + TRUE // _24 + }>ELSE<{ // query_id last_cleaned + LEQ // _26 + NEGATE // _24 + }> + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.cpp new file mode 100644 index 0000000000..39ac8a7f6f --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.cpp @@ -0,0 +1 @@ +with_tvm_code("multisig", "te6ccgECMAEAA2oAART/APSkE/Sg8sgLAQIBIAIDAgFICAkEwPIgxwCOgzDbPOCDCNcYIPkBAdMH2zwiwAAToVNhePQOb6Hyn9cL/0iQ+RDyoAP0BCD5AQHTP/gjqh9TILnyYVMngED0Dm+hECNUSADbPAquXLDyYrEBpPgAVDiTVHo5KxcvFgQEnts8VHCrU5rbPO1U+A9wJm5TqL6xmBA6EHlQdl8GiuIEgyWhjichgED0lm+hb6EyURCUMFMCud4glDQ2N3+XEEkQR0QUW+ICsxBXECXmMAMaHwUGAiowKkZTBts8UHegECQQN0EGU1bbPH8kGgEKipJfBeIHAQwQJNs87VQfAgLNCgsCASAbHAIBIAwNAgEgEhMCASAODwIBIBARAAMMIAEBIC8BASAfAQEgJAIBIBQVAgEgGBkBASAWAQEgFwA4jhXSAAHyo9MHWNcBIPkBBPkBFLrypFjgW3BSAgIc2zwC8mX4AFpxAts87VQvHwEBIBoATwhbpEx4CBukTDgAdAg10rDAJrUAvAHyFjPFszJ4HHXI8gBzxb0AMmAAaFIwvo4aXwOTIddKmAHTB9QC+wAB6DFwyMoAAoBA9EOOEnHIywATywdYzwFYzxYCgED0Q+ICASAdHgIBICUmARO77ZbVAjcFnbPIHwIBSCAhABjIywfLB8s/9AD0AMkCASAiIwF5sR10IMI1xgg+QEB0weCAdTE7UPYUyB49A5vofKf1wv/XjH5EPKgrgH0BCFulhAjXwNxAeD5AVjbPAGkAYCQAPa7agOgA6AD6AgF6AhH8gID8gN15T/gD5HoAAOeLZMAAFa4ZV0EA1WZ2oexAAGBwjikD0IMI1xjTB/QEMFMWePQOb6HypdcL/1RFRPkQ8qauUiCxUgO9FKEjbuYyMjICASAnKAIBSCkqAVW3JVtnhiZQCAqIhn6BzfQxwmYmQDpAADMaYOYuAFrgJhwLb+4cBgY3dG4QLwGNtVmbZ4Br4G/tscbqIlAIHo+N9C30JBHEgFpAADHDRA8a5CTa4GT2E5kAOeLAMAgKiCq+iHJCZhxSQmYcUktGHEA2fMCL4JAvAgEgKywCA5k4LS4BDawabZ4vgcAvABWt+UEAzJV2oewYQAENqTbPBRfBIC8AFa3cLOCAarM7UPYgABztRNDTB9MH0z/0BPQE0Q=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.fif new file mode 100644 index 0000000000..ce1c21bf08 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/multisig-code.fif @@ -0,0 +1,502 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/multisig-code.fc` +PROGRAM{ + DECLPROC unpack_state + DECLPROC pack_state + DECLPROC check_signatures + DECLPROC recv_internal + DECLPROC unpack_query_data + DECLPROC try_init + DECLPROC update_pending_queries + DECLPROC recv_external + 104746 DECLMETHOD get_query_state + 117746 DECLMETHOD processed? + 81625 DECLMETHOD create_init_state + DECLPROC merge_list + 120004 DECLMETHOD get_public_keys + 87157 DECLMETHOD check_query_signatures + 109260 DECLMETHOD messages_by_mask + 85042 DECLMETHOD get_messages_unsigned_by_id + 120055 DECLMETHOD get_messages_unsigned + 114740 DECLMETHOD get_n_k + 83381 DECLMETHOD merge_inner_queries + unpack_state PROCREF:<{ + // + c4 PUSH // _1 + CTOS // ds + 8 LDU // _4 ds + 8 LDU // _4 _7 ds + 64 LDU // _4 _7 _10 ds + LDDICT // _4 _7 _10 _13 ds + LDDICT // res res res res res ds + ENDS + }> + pack_state PROCREF:<{ + // pending_queries public_keys last_cleaned k n + NEWC // pending_queries public_keys last_cleaned k n _5 + 8 STU // pending_queries public_keys last_cleaned k _7 + 8 STU // pending_queries public_keys last_cleaned _9 + 64 STU // pending_queries public_keys _11 + STDICT // pending_queries _12 + STDICT // _13 + ENDC // _14 + }> + check_signatures PROCREF:<{ + // public_keys signatures hash cnt_bits + 0 PUSHINT // public_keys signatures hash cnt_bits cnt=0 + UNTIL:<{ + s0 s3 XCHG // public_keys cnt hash cnt_bits signatures + CTOS // public_keys cnt hash cnt_bits cs + 9 PUSHPOW2 // public_keys cnt hash cnt_bits cs _10=512 + LDSLICEX // public_keys cnt hash cnt_bits signature cs + 8 LDU // public_keys cnt hash cnt_bits signature i cs + LDDICT // public_keys cnt hash cnt_bits signature i _43 _42 + DROP // public_keys cnt hash cnt_bits signature i signatures + s1 s6 PUSH2 + 8 PUSHINT // public_keys cnt hash cnt_bits signature i signatures i public_keys _20=8 + DICTUGET + NULLSWAPIFNOT // public_keys cnt hash cnt_bits signature i signatures public_key found? + 37 THROWIFNOT + 256 PLDU // public_keys cnt hash cnt_bits signature i signatures _26 + s5 s3 s3 PUXC2 // public_keys cnt hash cnt_bits signatures i hash signature _26 + CHKSIGNU // public_keys cnt hash cnt_bits signatures i _27 + 38 THROWIFNOT + POW2 // public_keys cnt hash cnt_bits signatures mask + s2 s(-1) PUXC // public_keys cnt hash old_cnt_bits signatures cnt_bits mask + OR // public_keys cnt hash old_cnt_bits signatures cnt_bits + s0 s2 PUXC // public_keys cnt hash cnt_bits signatures cnt_bits old_cnt_bits + NEQ // public_keys cnt hash cnt_bits signatures should_check + s1 s4 XCHG // public_keys signatures hash cnt_bits cnt should_check + SUB // public_keys signatures hash cnt_bits cnt + s3 PUSH // public_keys signatures hash cnt_bits cnt signatures + ISNULL // public_keys signatures hash cnt_bits cnt _37 + }> // public_keys signatures hash cnt_bits cnt + s2 POP + s2 POP + s2 POP // cnt cnt_bits + }> + recv_internal PROC:<{ + // in_msg + DROP // + }> + unpack_query_data PROCREF:<{ + // in_msg n query found? + IFJMP:<{ // in_msg n query + 1 LDI // in_msg n _5 query + SWAP // in_msg n query _5 + 35 THROWIFNOT + 8 LDU // in_msg n _12 query + ROT // in_msg _12 query n + LDUX // in_msg cnt cnt_bits msg + DUP // in_msg cnt cnt_bits msg msg + HASHSU // in_msg cnt cnt_bits msg _18 + s0 s4 XCHG // _18 cnt cnt_bits msg in_msg + HASHSU // _18 cnt cnt_bits msg _19 + s1 s4 XCHG // msg cnt cnt_bits _18 _19 + EQUAL // msg cnt cnt_bits _20 + 36 THROWIFNOT + ROT // cnt cnt_bits msg + }> // in_msg n query + 2DROP // in_msg + 0 PUSHINT // in_msg _22=0 + s0 s1 PUXC // _22=0 _23=0 in_msg + }> + try_init PROCREF:<{ + // + unpack_state INLINECALLDICT // n k last_cleaned public_keys pending_queries + s0 s2 XCHG // n k pending_queries public_keys last_cleaned + 37 THROWIF + ACCEPT + 2SWAP + 1 PUSHINT + s0 s2 XCHG // pending_queries public_keys _9=1 k n + pack_state INLINECALLDICT // _10 + c4 POP + }> + update_pending_queries PROCREF:<{ + // pending_queries msg query_id cnt cnt_bits n k + s3 s(-1) PUXC // pending_queries msg query_id cnt cnt_bits n cnt k + GEQ // pending_queries msg query_id cnt cnt_bits n _7 + IF:<{ // pending_queries msg query_id cnt cnt_bits n + 3 BLKDROP // pending_queries msg query_id + WHILE:<{ + OVER // pending_queries msg query_id msg + SREFS // pending_queries msg query_id _8 + }>DO<{ // pending_queries msg query_id + SWAP // pending_queries query_id msg + 8 LDU // pending_queries query_id mode msg + LDREF // pending_queries query_id mode _13 msg + s0 s2 XCHG // pending_queries query_id msg _13 mode + SENDRAWMSG + SWAP // pending_queries msg query_id + }> // pending_queries msg query_id + NIP // pending_queries query_id + 0 PUSHINT // pending_queries query_id _17=0 + NEWC // pending_queries query_id _17=0 _18 + 1 STI // pending_queries query_id _20 + s0 s2 XCHG + 64 PUSHINT // _20 query_id pending_queries _21=64 + DICTUSETB // pending_queries + }>ELSE<{ // pending_queries msg query_id cnt cnt_bits n + 1 PUSHINT // pending_queries msg query_id cnt cnt_bits n _24=1 + NEWC // pending_queries msg query_id cnt cnt_bits n _24=1 _25 + 1 STU // pending_queries msg query_id cnt cnt_bits n _27 + s1 s3 XCHG // pending_queries msg query_id n cnt_bits cnt _27 + 8 STU // pending_queries msg query_id n cnt_bits _29 + ROT // pending_queries msg query_id cnt_bits _29 n + STUX // pending_queries msg query_id _30 + ROT // pending_queries query_id _30 msg + STSLICER // pending_queries query_id _31 + s0 s2 XCHG + 64 PUSHINT // _31 query_id pending_queries _32=64 + DICTUSETB // pending_queries + }> + }> + recv_external PROC:<{ + // in_msg + DUP // in_msg in_msg + SEMPTY // in_msg _1 + IFJMP:<{ // in_msg + DROP // + try_init INLINECALLDICT + }> // in_msg + 9 PUSHPOW2 // in_msg _5=512 + LDSLICEX // root_signature in_msg + DUP // root_signature in_msg in_msg + HASHSU // root_signature in_msg root_hash + SWAP // root_signature root_hash in_msg + 8 LDU // root_signature root_hash root_i in_msg + unpack_state INLINECALLDICT // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries + s2 PUSH // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries last_cleaned + 0 EQINT // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries _20 + s1 s3 XCHG // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned _20 + SUB // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned + s6 s1 PUSH2 + 8 PUSHINT // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned root_i public_keys _24=8 + DICTUGET + NULLSWAPIFNOT // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned public_key found? + 31 THROWIFNOT + 256 PLDU // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned _30 + s8 s9 s0 XCHG3 // last_cleaned public_keys root_i in_msg n k pending_queries root_hash root_signature _30 + CHKSIGNU // last_cleaned public_keys root_i in_msg n k pending_queries _31 + 32 THROWIFNOT + s0 s3 XCHG // last_cleaned public_keys root_i pending_queries n k in_msg + LDDICT // last_cleaned public_keys root_i pending_queries n k signatures in_msg + DUP // last_cleaned public_keys root_i pending_queries n k signatures in_msg in_msg + HASHSU // last_cleaned public_keys root_i pending_queries n k signatures in_msg hash + SWAP // last_cleaned public_keys root_i pending_queries n k signatures hash in_msg + 64 LDU // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg + NOW // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg _43 + 32 LSHIFT# // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound + s2 s0 PUSH2 // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query_id bound + LESS // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound _47 + 33 THROWIF + s2 s7 PUSH2 + 64 PUSHINT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query_id pending_queries _51=64 + DICTUGET + NULLSWAPIFNOT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query found? + s2 s3 XCHG + s8 s(-1) s(-1) PUXC2 // last_cleaned public_keys root_i pending_queries n k signatures hash query_id bound in_msg n query found? + unpack_query_data INLINECALLDICT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id bound cnt cnt_bits msg + s0 s10 XCHG // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits root_i + POW2 // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask + 2DUP // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask cnt_bits mask + AND // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask _61 + 34 THROWIF + OR // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits + SWAP // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt_bits cnt + INC // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt_bits cnt + ACCEPT + s8 s9 s3 XCPU2 + s10 s3 s9 PUSH3 + s11 PUSH // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries msg query_id cnt cnt_bits n k + update_pending_queries INLINECALLDICT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries + s0 s10 s11 PUSH3 + s9 s10 PUSH2 // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries pending_queries public_keys last_cleaned k n + pack_state INLINECALLDICT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries _68 + c4 POP + COMMIT + 0 PUSHINT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 + s6 PUSH // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 signatures + ISNULL // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73 + s10 s8 PUSH2 // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73 cnt k + GEQ // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73 _74 + OR // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _75 + IFNOT:<{ // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 + DROP // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries + s10 PUSH + s6 s5 s3 XCHG3 + s0 s6 XCHG // last_cleaned public_keys msg cnt n k bound pending_queries query_id public_keys signatures hash cnt_bits + check_signatures INLINECALLDICT // last_cleaned public_keys msg cnt n k bound pending_queries query_id new_cnt cnt_bits + s7 s7 XCHG2 // last_cleaned public_keys msg cnt_bits n k bound pending_queries query_id cnt new_cnt + ADD // last_cleaned public_keys msg cnt_bits n k bound pending_queries query_id cnt + s2 s4 XCHG + s3 s7 XCHG + s1 s0 s6 XCHG3 + s5 s6 PUSH2 // last_cleaned public_keys bound k n pending_queries msg query_id cnt cnt_bits n k + update_pending_queries INLINECALLDICT // last_cleaned public_keys bound k n pending_queries + -1 PUSHINT // last_cleaned public_keys bound k n pending_queries need_save=-1 + }>ELSE<{ + s3 s10 XCHG + s7 s9 XCHG + s7 s6 XCHG2 + 6 BLKDROP // last_cleaned public_keys bound k n pending_queries need_save + }> + s0 s4 XCHG + 38 PUSHPOW2 // last_cleaned public_keys need_save k n pending_queries bound _83 + SUB // last_cleaned public_keys need_save k n pending_queries bound + UNTIL:<{ + OVER + 64 PUSHINT // last_cleaned public_keys need_save k n pending_queries bound pending_queries _90=64 + DICTUREMMIN + NULLSWAPIFNOT + NULLSWAPIFNOT // last_cleaned public_keys need_save k n pending_queries bound _121 _123 _122 _124 + s2 POP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' f i + s1 s0 XCPU // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f f + IF:<{ // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f + DROP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i + s0 s2 PUSH2 // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i i bound + LESS // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f + }> // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f + DUP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f f + IF:<{ // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f + s4 POP + s6 POP + s7 POP // pending_queries public_keys last_cleaned k n f bound + -1 PUSHINT // pending_queries public_keys last_cleaned k n f bound need_save=-1 + }>ELSE<{ + s4 s9 XCHG + s4 s7 XCHG + s4 s1 s4 XCHG3 + 2DROP // pending_queries public_keys last_cleaned k n f bound need_save + }> + s0 s2 XCHG // pending_queries public_keys last_cleaned k n need_save bound f + NOT // pending_queries public_keys last_cleaned k n need_save bound _96 + s5 s7 XCHG + s2 s5 XCHG // last_cleaned public_keys need_save k n pending_queries bound _96 + }> // last_cleaned public_keys need_save k n pending_queries bound + DROP // last_cleaned public_keys need_save k n pending_queries + s0 s3 XCHG // last_cleaned public_keys pending_queries k n need_save + IF:<{ // last_cleaned public_keys pending_queries k n + s2 s4 XCHG // pending_queries public_keys last_cleaned k n + pack_state INLINECALLDICT // _97 + c4 POP + }>ELSE<{ + 5 BLKDROP // + }> + }> + get_query_state PROC:<{ + // query_id + unpack_state INLINECALLDICT // query_id _25 _26 _27 _28 _29 + NIP + s2 POP // query_id n pending_queries last_cleaned + 64 PUSHINT // query_id n pending_queries last_cleaned _9=64 + s4 s2 s2 PUXC2 // query_id n last_cleaned query_id pending_queries _9=64 + DICTUGET + NULLSWAPIFNOT // query_id n last_cleaned cs found + IFJMP:<{ // query_id n last_cleaned cs + NIP + s2 POP // cs n + SWAP // n cs + 1 LDI // n _11 cs + SWAP // n cs _11 + IFJMP:<{ // n cs + 8 LDU // n _35 _34 + NIP // n cs + 0 PUSHINT // n cs _17=0 + s0 s2 XCHG // _17=0 cs n + LDUX // _17=0 _37 _36 + DROP // _17=0 _18 + }> // n cs + 2DROP // + -1 PUSHINT // _20=-1 + 0 PUSHINT // _20=-1 _21=0 + }> // query_id n last_cleaned cs + DROP + NIP // query_id last_cleaned + LEQ // _22 + NEGATE // _23 + 0 PUSHINT // _23 _24=0 + }> + processed? PROC:<{ + // query_id + get_query_state CALLDICT // _4 _5 + DROP // x + }> + create_init_state PROC:<{ + // n k public_keys + NEWDICT // n k public_keys _3 + s2 s3 XCHG2 + 0 PUSHINT + -ROT // _3 public_keys _4=0 k n + pack_state INLINECALLDICT // _5 + }> + merge_list PROC:<{ + // a b + OVER // a b a + ISNULL // a b _2 + IFJMP:<{ // a b + NIP // b + }> // a b + DUP // a b b + ISNULL // a b _3 + IFJMP:<{ // a b + DROP // a + }> // a b + SWAP // b a + CTOS // b as + DUP // b as as + SREFS // b as _6 + 0 NEQINT // b as _8 + IFJMP:<{ // b as + LDREF // b _10 as + s0 s2 XCHG // as _10 b + merge_list CALLDICT // as tail + NEWC // as tail _13 + ROT // tail _13 as + STSLICER // tail _14 + STREF // _15 + ENDC // _16 + }> // b as + 1 PUSHINT // b as _18=1 + SDSKIPLAST // b as + NEWC // b as _20 + SWAP // b _20 as + STSLICER // b _21 + STDICT // _22 + ENDC // _23 + }> + get_public_keys PROC:<{ + // + unpack_state INLINECALLDICT // _6 _7 _8 _9 _10 + s1 s4 XCHG + 4 BLKDROP // public_keys + }> + check_query_signatures PROC:<{ + // query + CTOS // cs + 9 PUSHPOW2 // cs _5=512 + LDSLICEX // root_signature cs + DUP // root_signature cs cs + HASHSU // root_signature cs root_hash + SWAP // root_signature root_hash cs + 8 LDU // root_signature root_hash root_i cs + get_public_keys CALLDICT // root_signature root_hash root_i cs public_keys + s2 s0 PUSH2 + 8 PUSHINT // root_signature root_hash root_i cs public_keys root_i public_keys _17=8 + DICTUGET + NULLSWAPIFNOT // root_signature root_hash root_i cs public_keys public_key found? + 31 THROWIFNOT + 256 PLDU // root_signature root_hash root_i cs public_keys _23 + 5 1 REVERSE // public_keys cs root_i root_hash root_signature _23 + CHKSIGNU // public_keys cs root_i _24 + 32 THROWIFNOT + POW2 // public_keys cs mask + SWAP // public_keys mask cs + LDDICT // public_keys mask signatures cs + OVER // public_keys mask signatures cs signatures + ISNULL // public_keys mask signatures cs _32 + IFJMP:<{ // public_keys mask signatures cs + s2 s3 XCHG + 3 BLKDROP // mask + 1 PUSHINT // mask _33=1 + SWAP // _33=1 mask + }> // public_keys mask signatures cs + HASHSU // public_keys mask signatures _35 + ROT // public_keys signatures _35 mask + check_signatures INLINECALLDICT // cnt mask + SWAP // mask cnt + INC // mask _38 + SWAP // _38 mask + }> + messages_by_mask PROC:<{ + // mask + unpack_state INLINECALLDICT // mask _29 _30 _31 _32 _33 + s0 s3 XCHG + 3 BLKDROP // mask n pending_queries + -1 PUSHINT // mask n pending_queries i=-1 + NEWDICT // mask n pending_queries i=-1 a + UNTIL:<{ + s1 s2 XCPU + 64 PUSHINT // mask n pending_queries a i pending_queries _13=64 + DICTUGETNEXT + NULLSWAPIFNOT + NULLSWAPIFNOT // mask n pending_queries a cs i f + DUP // mask n pending_queries a cs i f f + IF:<{ // mask n pending_queries a cs i f + s0 s2 XCHG // mask n pending_queries a f i cs + 1 LDI // mask n pending_queries a f i _15 cs + SWAP // mask n pending_queries a f i cs _15 + IF:<{ // mask n pending_queries a f i cs + DUP + 8 PUSHINT // mask n pending_queries a f i cs cs _19=8 + SDSKIPFIRST // mask n pending_queries a f i cs _20 + s6 PUSH // mask n pending_queries a f i cs _20 n + PLDUX // mask n pending_queries a f i cs cnt_bits + s7 PUSH // mask n pending_queries a f i cs cnt_bits mask + AND // mask n pending_queries a f i cs _22 + IF:<{ // mask n pending_queries a f i cs + NEWC // mask n pending_queries a f i cs _24 + SWAP // mask n pending_queries a f i _24 cs + STSLICER // mask n pending_queries a f i _25 + SWAP + 64 PUSHINT + s1 s4 s4 PUXC2 // mask n pending_queries i f _25 i a _26=64 + DICTUSETB // mask n pending_queries i f a + }>ELSE<{ + s1 s3 XCHG + DROP // mask n pending_queries i f a + }> + }>ELSE<{ + s1 s3 XCHG + DROP // mask n pending_queries i f a + }> + }>ELSE<{ + 2SWAP + DROP // mask n pending_queries i f a + }> + SWAP // mask n pending_queries i a f + NOT // mask n pending_queries i a _28 + }> // mask n pending_queries i a + s0 s4 XCHG + 4 BLKDROP // a + }> + get_messages_unsigned_by_id PROC:<{ + // id + POW2 // _2 + messages_by_mask CALLDICT // _3 + }> + get_messages_unsigned PROC:<{ + // + 0 PUSHINT // _0=0 + NOT // _1 + messages_by_mask CALLDICT // _2 + }> + get_n_k PROC:<{ + // + unpack_state INLINECALLDICT // _6 _7 _8 _9 _10 + 3 BLKDROP // n k + }> + merge_inner_queries PROC:<{ + // a b + SWAP // b a + CTOS // b ca + SWAP // ca b + CTOS // ca cb + SWAP // cb ca + LDDICT // cb list_a ca + s0 s2 XCHG // ca list_a cb + LDDICT // ca list_a list_b cb + s3 PUSH // ca list_a list_b cb ca + HASHSU // ca list_a list_b cb _13 + SWAP // ca list_a list_b _13 cb + HASHSU // ca list_a list_b _13 _14 + EQUAL // ca list_a list_b _15 + 31 THROWIFNOT + merge_list CALLDICT // ca _17 + NEWC // ca _17 _18 + STDICT // ca _19 + SWAP // _19 ca + STSLICER // _20 + ENDC // _21 + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.cpp new file mode 100644 index 0000000000..1391da27b8 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.cpp @@ -0,0 +1 @@ +with_tvm_code("restricted-wallet", "te6ccgECDQEAAQgAART/APSkE/Sg8sgLAQIBIAIDAgFIBAUB+vKDCNcYINMf0x/4IxK78mPtRNDTH9P/0VMxuvKhA54xMjL4AKTIyx/L/8ntVOED+QFUEEL5EPKi+ACA8/gzIG6SMH+X0NcLH/gjvOJx+DPQ1wv/BJMg10qOldMH1H8kjoUwUxbbPN6TAvsAkjIw4ugxMwLRpMjLH8v/ye1UDAICzgYHAgEgCgsCASAICQEBSAwAAwwgACUgPP4MyBukjB/l9DXCx/4I7zigABG+ZL9qJoa4WPwAOby2BAefwZkDdJGD/L6GuFj/wR3nFIuEp8EzeIcUADIB0NMDAXiwklt/4PpAMfpAMPpEAcD/Arqw"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.fif new file mode 100644 index 0000000000..6582706c2b --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet-code.fif @@ -0,0 +1,144 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/restricted-wallet-code.fc` +PROGRAM{ + DECLPROC recv_internal + DECLPROC restricted? + DECLPROC check_destination + DECLPROC recv_external + 85143 DECLMETHOD seqno + 104128 DECLMETHOD balance + recv_internal PROC:<{ + // in_msg + DROP // + }> + restricted? PROC:<{ + // + -13 PUSHINT // _1=-13 + CONFIGOPTPARAM // p + DUP // p p + ISNULL // p _3 + IF:<{ // p + DROP // + TRUE // _4 + }>ELSE<{ // p + CTOS // _6 + 32 PLDU // _8 + NOW // _8 _9 + GREATER // _4 + }> + }> + check_destination PROCREF:<{ + // msg dest + SWAP // dest msg + CTOS // dest cs + 4 LDU // dest flags cs + SWAP + 8 PUSHINT // dest cs flags _8=8 + AND // dest cs _9 + IFJMP:<{ // dest cs + 2DROP // + TRUE // _10 + }> // dest cs + LDMSGADDR // dest _27 _26 + NIP // dest cs + LDMSGADDR // dest _29 _28 + DROP // dest d_addr + REWRITESTDADDR // dest dest_wc dest_addr + SWAP // dest dest_addr dest_wc + -1 EQINT // dest dest_addr _21 + s0 s2 XCHG // _21 dest_addr dest + EQUAL // _21 _22 + AND // _23 + }> + recv_external PROC:<{ + // in_msg + 9 PUSHPOW2 // in_msg _3=512 + LDSLICEX // signature in_msg + DUP // signature in_msg cs + 32 LDU // signature in_msg _8 cs + 32 LDU // signature in_msg msg_seqno valid_until cs + NOW // signature in_msg msg_seqno valid_until cs _15 + s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15 + LEQ // signature in_msg msg_seqno cs _16 + 35 THROWIF + c4 PUSH // signature in_msg msg_seqno cs _19 + CTOS // signature in_msg msg_seqno cs ds + 32 LDU // signature in_msg msg_seqno cs _23 ds + 256 LDU // signature in_msg msg_seqno cs stored_seqno public_key ds + ENDS + s3 s1 PUSH2 // signature in_msg msg_seqno cs stored_seqno public_key msg_seqno stored_seqno + EQUAL // signature in_msg msg_seqno cs stored_seqno public_key _31 + 33 THROWIFNOT + s0 s3 XCHG // signature in_msg public_key cs stored_seqno msg_seqno + IFNOTJMP:<{ // signature in_msg public_key cs stored_seqno + NIP + s2 POP + s2 POP // public_key stored_seqno + ACCEPT + INC // public_key _35 + NEWC // public_key _35 _36 + 32 STU // public_key _38 + 256 STU // _40 + ENDC // _41 + c4 POP + }> // signature in_msg public_key cs stored_seqno + s0 s3 XCHG // signature stored_seqno public_key cs in_msg + HASHSU // signature stored_seqno public_key cs _44 + s0 s4 s2 XC2PU // cs stored_seqno public_key _44 signature public_key + CHKSIGNU // cs stored_seqno public_key _45 + 34 THROWIFNOT + ACCEPT + restricted? INLINECALLDICT // cs stored_seqno public_key restrict + 1 PUSHINT // cs stored_seqno public_key restrict _51=1 + CONFIGOPTPARAM // cs stored_seqno public_key restrict _52 + CTOS // cs stored_seqno public_key restrict _53 + 256 PLDU // cs stored_seqno public_key restrict elector + s0 s4 XCHG // elector stored_seqno public_key restrict cs + WHILE:<{ + DUP // elector stored_seqno public_key restrict cs cs + SREFS // elector stored_seqno public_key restrict cs _58 + }>DO<{ // elector stored_seqno public_key restrict cs + 8 LDU // elector stored_seqno public_key restrict mode cs + LDREF // elector stored_seqno public_key restrict mode msg cs + TRUE // elector stored_seqno public_key restrict mode msg cs ok + s4 PUSH // elector stored_seqno public_key restrict mode msg cs ok restrict + IF:<{ // elector stored_seqno public_key restrict mode msg cs ok + DROP // elector stored_seqno public_key restrict mode msg cs + s1 s6 PUSH2 // elector stored_seqno public_key restrict mode msg cs msg elector + check_destination INLINECALLDICT // elector stored_seqno public_key restrict mode msg cs ok + }> // elector stored_seqno public_key restrict mode msg cs ok + IF:<{ // elector stored_seqno public_key restrict mode msg cs + s0 s2 XCHG // elector stored_seqno public_key restrict cs msg mode + SENDRAWMSG + }>ELSE<{ + s2 POP + DROP // elector stored_seqno public_key restrict cs + }> + }> // elector stored_seqno public_key restrict cs + NIP + s3 POP // cs stored_seqno public_key + s0 s2 XCHG // public_key stored_seqno cs + ENDS + INC // public_key _72 + NEWC // public_key _72 _73 + 32 STU // public_key _75 + 256 STU // _77 + ENDC // _78 + c4 POP + }> + seqno PROC:<{ + // + c4 PUSH // _0 + CTOS // _1 + 32 PLDU // _3 + }> + balance PROC:<{ + // + restricted? INLINECALLDICT // _0 + IF:<{ // + 0 PUSHINT // _1=0 + }>ELSE<{ // + BALANCE // _3 + FIRST // _1 + }> + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.cpp new file mode 100644 index 0000000000..a95ad749d2 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.cpp @@ -0,0 +1 @@ +with_tvm_code("restricted-wallet2", "te6ccgECDAEAAR0AART/APSkE/Sg8sgLAQIBIAIDAgFIBAUBAvIKAgLPBgcCASAICQADDCAAMyA8/gzIG6SMH+e+CMB0NcLH6GCAVGAqQTigABG+ZL9qJoa4WPwAf7y2B2omhAgJBrkPoCaMB5/BmQN0kYP898EYDoa4WP0MEAqMBUgnF8EzeIAUAIej230LfQmMv9ABhQuFsEyJhxQB/oMI1xgg0x/TH/gjErvyY+1E0NMf0//0BNFTQrryoQSOEjIzM/gAAaTIyx8Sy//0AMntVOEE+QFUEFT5EPKi+ACA8/gzIG6SMH+e+CMB0NcLH6GCAVGAqQTiIoAQ9HtvoW+hMZb6ADBy+wKRMOKTINdKltMH1AL7AOjRAqTIyx8LAA7L//QAye1U"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.fif new file mode 100644 index 0000000000..112e8c6228 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/restricted-wallet2-code.fif @@ -0,0 +1,140 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/restricted-wallet2-code.fc` +PROGRAM{ + DECLPROC recv_internal + DECLPROC days_passed + DECLPROC recv_external + 85143 DECLMETHOD seqno + 104128 DECLMETHOD balance + recv_internal PROC:<{ + // in_msg + DROP // + }> + days_passed PROC:<{ + // + -13 PUSHINT // _1=-13 + CONFIGOPTPARAM // p + DUP // p p + ISNULL // p _3 + IF:<{ // p + DROP // + -1 PUSHINT // _4=-1 + }>ELSE<{ // p + NOW // p _6 + SWAP // _6 p + CTOS // _6 _7 + 32 PLDU // _6 _9 + SUB // _10 + 86400 PUSHINT // _10 _11=86400 + DIV // _4 + }> + }> + recv_external PROC:<{ + // in_msg + 9 PUSHPOW2 // in_msg _3=512 + LDSLICEX // signature in_msg + DUP // signature in_msg cs + 32 LDU // signature in_msg _8 cs + 32 LDU // signature in_msg msg_seqno valid_until cs + NOW // signature in_msg msg_seqno valid_until cs _15 + s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15 + LEQ // signature in_msg msg_seqno cs _16 + 35 THROWIF + c4 PUSH // signature in_msg msg_seqno cs _19 + CTOS // signature in_msg msg_seqno cs ds + 32 LDU // signature in_msg msg_seqno cs _24 ds + 256 LDU // signature in_msg msg_seqno cs _24 _27 ds + LDDICT // signature in_msg msg_seqno cs stored_seqno public_key rdict ds + ENDS + s4 s2 PUSH2 // signature in_msg msg_seqno cs stored_seqno public_key rdict msg_seqno stored_seqno + EQUAL // signature in_msg msg_seqno cs stored_seqno public_key rdict _34 + 33 THROWIFNOT + s0 s4 XCHG // signature in_msg rdict cs stored_seqno public_key msg_seqno + IFNOTJMP:<{ // signature in_msg rdict cs stored_seqno public_key + s2 POP + s3 POP + s3 POP // public_key stored_seqno rdict + ACCEPT + SWAP // public_key rdict stored_seqno + INC // public_key rdict _38 + NEWC // public_key rdict _38 _39 + 32 STU // public_key rdict _41 + s1 s2 XCHG // rdict public_key _41 + 256 STU // rdict _43 + STDICT // _44 + ENDC // _45 + c4 POP + }> // signature in_msg rdict cs stored_seqno public_key + s0 s4 XCHG // signature public_key rdict cs stored_seqno in_msg + HASHSU // signature public_key rdict cs stored_seqno _48 + s0 s5 s4 XC2PU // stored_seqno public_key rdict cs _48 signature public_key + CHKSIGNU // stored_seqno public_key rdict cs _49 + 34 THROWIFNOT + ACCEPT + days_passed INLINECALLDICT // stored_seqno public_key rdict cs ts + s2 PUSH + 16 PUSHINT // stored_seqno public_key rdict cs ts rdict _57=16 + DICTIGETPREVEQ + NULLSWAPIFNOT + NULLSWAPIFNOT // stored_seqno public_key rdict cs _98 _97 _99 + NIP // stored_seqno public_key rdict cs value found + IF:<{ // stored_seqno public_key rdict cs value + LDGRAMS // stored_seqno public_key rdict cs _101 _100 + DROP // stored_seqno public_key rdict cs _59 + 2 PUSHINT // stored_seqno public_key rdict cs _59 _61=2 + RAWRESERVE + }>ELSE<{ + DROP // stored_seqno public_key rdict cs + }> // stored_seqno public_key rdict cs + WHILE:<{ + DUP // stored_seqno public_key rdict cs cs + SREFS // stored_seqno public_key rdict cs _65 + }>DO<{ // stored_seqno public_key rdict cs + 8 LDU // stored_seqno public_key rdict mode cs + LDREF // stored_seqno public_key rdict mode msg cs + s0 s2 XCHG // stored_seqno public_key rdict cs msg mode + SENDRAWMSG + }> // stored_seqno public_key rdict cs + ENDS + s0 s2 XCHG // rdict public_key stored_seqno + INC // rdict public_key _76 + NEWC // rdict public_key _76 _77 + 32 STU // rdict public_key _79 + 256 STU // rdict _81 + STDICT // _82 + ENDC // _83 + c4 POP + }> + seqno PROC:<{ + // + c4 PUSH // _0 + CTOS // _1 + 32 PLDU // _3 + }> + balance PROC:<{ + // + c4 PUSH // _1 + CTOS // _2 + 288 PUSHINT // _2 _5 + SDSKIPFIRST // ds + LDDICT // rdict ds + ENDS + days_passed INLINECALLDICT // rdict ts + BALANCE // rdict ts _14 + FIRST // rdict ts balance + s0 s2 XCHG + 16 PUSHINT // balance ts rdict _19=16 + DICTIGETPREVEQ + NULLSWAPIFNOT + NULLSWAPIFNOT // balance _29 _28 _30 + NIP // balance value found + IF:<{ // balance value + LDGRAMS // balance _32 _31 + DROP // balance _21 + SUB // _23 + 0 PUSHINT // _23 _24=0 + MAX // balance + }>ELSE<{ + DROP // balance + }> + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.cpp new file mode 100644 index 0000000000..ea4603f0ae --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.cpp @@ -0,0 +1 @@ +with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9KDyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U"); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.fif new file mode 100644 index 0000000000..c052d4b656 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-code.fif @@ -0,0 +1,45 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/simple-wallet-code.fc` +PROGRAM{ + DECLPROC recv_internal + DECLPROC recv_external + recv_internal PROC:<{ + // in_msg + DROP // + }> + recv_external PROC:<{ + // in_msg + 9 PUSHPOW2 // in_msg _3=512 + LDSLICEX // signature in_msg + DUP // signature in_msg cs + 32 LDU // signature in_msg msg_seqno cs + c4 PUSH // signature in_msg msg_seqno cs _11 + CTOS // signature in_msg msg_seqno cs cs2 + 32 LDU // signature in_msg msg_seqno cs stored_seqno cs2 + 256 LDU // signature in_msg msg_seqno cs stored_seqno public_key cs2 + ENDS + s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno + EQUAL // signature in_msg public_key cs stored_seqno _23 + 33 THROWIFNOT + s0 s3 XCHG // signature stored_seqno public_key cs in_msg + HASHSU // signature stored_seqno public_key cs _26 + s0 s4 s2 XC2PU // cs stored_seqno public_key _26 signature public_key + CHKSIGNU // cs stored_seqno public_key _27 + 34 THROWIFNOT + ACCEPT + s2 s0 XCPU // public_key stored_seqno cs cs + SREFS // public_key stored_seqno cs _32 + IF:<{ // public_key stored_seqno cs + 8 LDU // public_key stored_seqno mode cs + LDREF // public_key stored_seqno mode _37 cs + s0 s2 XCHG // public_key stored_seqno cs _37 mode + SENDRAWMSG + }> // public_key stored_seqno cs + ENDS + INC // public_key _42 + NEWC // public_key _42 _43 + 32 STU // public_key _45 + 256 STU // _47 + ENDC // _48 + c4 POP + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.cpp new file mode 100644 index 0000000000..ad546b2894 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.cpp @@ -0,0 +1 @@ +with_tvm_code("simple-wallet-ext", "te6ccgEBFgEAzwABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQA08vACVDIS8AT4ACDXSpbTB9QC+wDe0aQB8AMCAs0GBwIBIA4PAgEgCAkAKdAUGEa4wQaY+CXXlQ/ICgCfyIeVFAIBIAoLAgEgDA0AAwwgAA8yBLLH8v/yYAARO1E0NMf0/8wgAAk8AHtVIAIBIBARAgEgFBUADbvtlwAfABgCASASEwARtZL9qJoa4WPwAA22l54AXgCQACG40BggFMl+1D2IIByODtQ9iAAVuI4MjLHxLLB8zJg="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.fif new file mode 100644 index 0000000000..b403131e07 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/simple-wallet-ext-code.fif @@ -0,0 +1,104 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/simple-wallet-ext-code.fc` +PROGRAM{ + DECLPROC create_state + DECLPROC load_state + DECLPROC save_state + DECLPROC recv_internal + DECLPROC do_verify_message + DECLPROC recv_external + 85143 DECLMETHOD seqno + 81625 DECLMETHOD create_init_state + 116960 DECLMETHOD prepare_send_message_with_seqno + 101633 DECLMETHOD prepare_send_message + 95420 DECLMETHOD verify_message + create_state PROC:<{ + // seqno public_key + NEWC // seqno public_key _2 + s1 s2 XCHG // public_key seqno _2 + 32 STU // public_key _4 + 256 STU // _6 + ENDC // _7 + }> + load_state PROC:<{ + // + c4 PUSH // _1 + CTOS // cs2 + 32 LDU // _3 cs2 + 256 LDU // _3 _12 _11 + DROP // _3 _6 + }> + save_state PROC:<{ + // seqno public_key + create_state CALLDICT // _2 + c4 POP + }> + recv_internal PROC:<{ + // in_msg + DROP // + }> + do_verify_message PROC:<{ + // in_msg seqno public_key + s0 s2 XCHG + 9 PUSHPOW2 // public_key seqno in_msg _5=512 + LDSLICEX // public_key seqno signature in_msg + DUP // public_key seqno signature in_msg cs + 32 LDU // public_key seqno signature in_msg msg_seqno cs + s0 s4 XCHG // public_key cs signature in_msg msg_seqno seqno + EQUAL // public_key cs signature in_msg _13 + 33 THROWIFNOT + HASHSU // public_key cs signature _16 + s0 s1 s3 XCHG3 // cs _16 signature public_key + CHKSIGNU // cs _17 + 34 THROWIFNOT + }> + recv_external PROC:<{ + // in_msg + load_state CALLDICT // in_msg stored_seqno public_key + s2 s1 s2 XCPU2 // public_key stored_seqno in_msg stored_seqno public_key + do_verify_message CALLDICT // public_key stored_seqno cs + ACCEPT // public_key stored_seqno cs + DUP // public_key stored_seqno cs cs + SREFS // public_key stored_seqno cs _9 + IF:<{ // public_key stored_seqno cs + 8 LDU // public_key stored_seqno mode cs + LDREF // public_key stored_seqno mode _14 cs + s0 s2 XCHG // public_key stored_seqno cs _14 mode + SENDRAWMSG + }> // public_key stored_seqno cs + ENDS + INC // public_key _19 + SWAP // _19 public_key + save_state CALLDICT + }> + seqno PROC:<{ + // + c4 PUSH // _0 + CTOS // _1 + 32 PLDU // _3 + }> + create_init_state PROC:<{ + // public_key + 0 PUSHINT // public_key _1=0 + SWAP // _1=0 public_key + create_state CALLDICT // _2 + }> + prepare_send_message_with_seqno PROC:<{ + // mode msg seqno + NEWC // mode msg seqno _3 + 32 STU // mode msg _5 + s1 s2 XCHG // msg mode _5 + 8 STU // msg _7 + STREF // _8 + ENDC // _9 + }> + prepare_send_message PROC:<{ + // mode msg + seqno CALLDICT // mode msg _2 + prepare_send_message_with_seqno CALLDICT // _3 + }> + verify_message PROC:<{ + // msg + load_state CALLDICT // msg stored_seqno public_key + do_verify_message CALLDICT // _4 + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.cpp b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.cpp new file mode 100644 index 0000000000..52fefeeb07 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.cpp @@ -0,0 +1 @@ +with_tvm_code("wallet", "te6ccgEBBgEAaAABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQCA8oMI1xgg0x/TH/gjErvyY+1E0NMf0//RUTG68qED+QFUEEL5EPKi+AACkyDXSpbTB9QC+wDo0aTIyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw=="); diff --git a/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.fif new file mode 100644 index 0000000000..cd9fa5d0f8 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/auto/wallet-code.fif @@ -0,0 +1,59 @@ +// automatically generated from `smartcont/stdlib.fc` `smartcont/wallet-code.fc` +PROGRAM{ + DECLPROC recv_internal + DECLPROC recv_external + 85143 DECLMETHOD seqno + recv_internal PROC:<{ + // in_msg + DROP // + }> + recv_external PROC:<{ + // in_msg + 9 PUSHPOW2 // in_msg _3=512 + LDSLICEX // signature in_msg + DUP // signature in_msg cs + 32 LDU // signature in_msg _8 cs + 32 LDU // signature in_msg msg_seqno valid_until cs + NOW // signature in_msg msg_seqno valid_until cs _15 + s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15 + LEQ // signature in_msg msg_seqno cs _16 + 35 THROWIF + c4 PUSH // signature in_msg msg_seqno cs _19 + CTOS // signature in_msg msg_seqno cs ds + 32 LDU // signature in_msg msg_seqno cs _23 ds + 256 LDU // signature in_msg msg_seqno cs stored_seqno public_key ds + ENDS + s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno + EQUAL // signature in_msg public_key cs stored_seqno _31 + 33 THROWIFNOT + s0 s3 XCHG // signature stored_seqno public_key cs in_msg + HASHSU // signature stored_seqno public_key cs _34 + s0 s4 s2 XC2PU // cs stored_seqno public_key _34 signature public_key + CHKSIGNU // cs stored_seqno public_key _35 + 34 THROWIFNOT + ACCEPT + s0 s2 XCHG // public_key stored_seqno cs + WHILE:<{ + DUP // public_key stored_seqno cs cs + SREFS // public_key stored_seqno cs _40 + }>DO<{ // public_key stored_seqno cs + 8 LDU // public_key stored_seqno mode cs + LDREF // public_key stored_seqno mode _45 cs + s0 s2 XCHG // public_key stored_seqno cs _45 mode + SENDRAWMSG + }> // public_key stored_seqno cs + ENDS + INC // public_key _50 + NEWC // public_key _50 _51 + 32 STU // public_key _53 + 256 STU // _55 + ENDC // _56 + c4 POP + }> + seqno PROC:<{ + // + c4 PUSH // _0 + CTOS // _1 + 32 PLDU // _3 + }> +}END>c diff --git a/submodules/ton/tonlib-src/crypto/smartcont/config-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/config-code.fc index 5e0508f537..c9c09a9596 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/config-code.fc +++ b/submodules/ton/tonlib-src/crypto/smartcont/config-code.fc @@ -86,6 +86,39 @@ .end_cell(), 0); } +() after_code_upgrade(slice param, cell old_code) impure method_id(1666) { +} + +_ perform_action(cfg_dict, public_key, action, cs) { + if (action == 0x43665021) { + ;; change one configuration parameter + var param_index = cs~load_uint(32); + var param_value = cs~load_ref(); + cs.end_parse(); + cfg_dict~idict_set_ref(32, param_index, param_value); + } elseif (action == 0x4e436f64) { + ;; change configuration smart contract code + var new_code = cs~load_ref(); + set_code(new_code); + ifnot(cs.slice_empty?()) { + var old_code = get_c3(); + set_c3(new_code); + after_code_upgrade(cs, old_code); + set_c3(old_code); + } + } elseif (action == 0x50624b21) { + ;; change configuration master public key + public_key = cs~load_uint(256); + cs.end_parse(); + } elseif (action == 0x4e43ef05) { + ;; change election smart contract code + change_elector_code(cs); + } else { + throw_if(32, action); + } + return (cfg_dict, public_key); +} + () recv_external(slice in_msg) impure { var signature = in_msg~load_bits(512); var cs = in_msg; @@ -101,27 +134,7 @@ throw_unless(33, msg_seqno == stored_seqno); throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); accept_message(); - if (action == 0x43665021) { - ;; change one configuration parameter - var param_index = cs~load_uint(32); - var param_value = cs~load_ref(); - cs.end_parse(); - cfg_dict~idict_set_ref(32, param_index, param_value); - } elseif (action == 0x4e436f64) { - ;; change configuration smart contract code - var new_code = cs~load_ref(); - cs.end_parse(); - set_code(new_code); - } elseif (action == 0x50624b21) { - ;; change configuration master public key - public_key = cs~load_uint(256); - cs.end_parse(); - } elseif (action == 0x4e43ef05) { - ;; change election smart contract code - change_elector_code(cs); - } else { - throw_if(32, action); - } + (cfg_dict, public_key) = perform_action(cfg_dict, public_key, action, cs); set_data(begin_cell().store_ref(cfg_dict).store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); } diff --git a/submodules/ton/tonlib-src/crypto/smartcont/elector-code.fif b/submodules/ton/tonlib-src/crypto/smartcont/elector-code.fif index 08184e6f43..d964063b2e 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/elector-code.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/elector-code.fif @@ -354,104 +354,105 @@ PROGRAM{ }> unfreeze_without_bonuses PROC:<{ // credits freeze_dict tot_stakes - 0 PUSHINT // credits freeze_dict tot_stakes recovered=0 - DUP // credits freeze_dict tot_stakes recovered=0 total=0 - -1 PUSHINT // credits freeze_dict tot_stakes recovered=0 total=0 pubkey=-1 + 0 PUSHINT // credits freeze_dict tot_stakes _5=0 + DUP // credits freeze_dict tot_stakes total=0 recovered=0 + -1 PUSHINT // credits freeze_dict tot_stakes total=0 recovered=0 pubkey=-1 UNTIL:<{ s4 PUSH - 8 PUSHPOW2 // credits freeze_dict tot_stakes recovered total pubkey freeze_dict _10=256 + 8 PUSHPOW2 // credits freeze_dict tot_stakes total recovered pubkey freeze_dict _10=256 DICTUGETNEXT NULLSWAPIFNOT - NULLSWAPIFNOT // credits freeze_dict tot_stakes recovered total cs pubkey f - DUP // credits freeze_dict tot_stakes recovered total cs pubkey f f - IF:<{ // credits freeze_dict tot_stakes recovered total cs pubkey f - s0 s2 XCHG // credits freeze_dict tot_stakes recovered total f pubkey cs - 256 LDU // credits freeze_dict tot_stakes recovered total f pubkey _16 cs - 64 LDU // credits freeze_dict tot_stakes recovered total f pubkey _16 _42 _41 - NIP // credits freeze_dict tot_stakes recovered total f pubkey _16 cs - LDGRAMS // credits freeze_dict tot_stakes recovered total f pubkey _16 _22 cs - 1 LDI // credits freeze_dict tot_stakes recovered total f pubkey addr stake banned cs + NULLSWAPIFNOT // credits freeze_dict tot_stakes total recovered cs pubkey f + DUP // credits freeze_dict tot_stakes total recovered cs pubkey f f + IF:<{ // credits freeze_dict tot_stakes total recovered cs pubkey f + s0 s2 XCHG // credits freeze_dict tot_stakes total recovered f pubkey cs + 256 LDU // credits freeze_dict tot_stakes total recovered f pubkey _16 cs + 64 LDU // credits freeze_dict tot_stakes total recovered f pubkey _16 _42 _41 + NIP // credits freeze_dict tot_stakes total recovered f pubkey _16 cs + LDGRAMS // credits freeze_dict tot_stakes total recovered f pubkey _16 _22 cs + 1 LDI // credits freeze_dict tot_stakes total recovered f pubkey addr stake banned cs ENDS - IF:<{ // credits freeze_dict tot_stakes recovered total f pubkey addr stake - NIP // credits freeze_dict tot_stakes recovered total f pubkey stake - s4 s4 XCPU // credits freeze_dict tot_stakes stake total f pubkey recovered stake - ADD // credits freeze_dict tot_stakes stake total f pubkey recovered - }>ELSE<{ // credits freeze_dict tot_stakes recovered total f pubkey addr stake - s8 s8 s8 XC2PU // stake freeze_dict tot_stakes recovered total f pubkey credits addr stake - ~credit_to CALLDICT // stake freeze_dict tot_stakes recovered total f pubkey credits + IF:<{ // credits freeze_dict tot_stakes total recovered f pubkey addr stake + NIP // credits freeze_dict tot_stakes total recovered f pubkey stake + s3 s3 XCPU // credits freeze_dict tot_stakes total stake f pubkey recovered stake + ADD // credits freeze_dict tot_stakes total stake f pubkey recovered + }>ELSE<{ // credits freeze_dict tot_stakes total recovered f pubkey addr stake + s8 s8 s8 XC2PU // stake freeze_dict tot_stakes total recovered f pubkey credits addr stake + ~credit_to CALLDICT // stake freeze_dict tot_stakes total recovered f pubkey credits s0 s7 XCHG - s0 s4 XCHG // credits freeze_dict tot_stakes stake total f pubkey recovered + s0 s3 XCHG // credits freeze_dict tot_stakes total stake f pubkey recovered }> - s3 s4 XCHG2 // credits freeze_dict tot_stakes recovered pubkey f total stake - ADD // credits freeze_dict tot_stakes recovered pubkey f total + s4 s3 XCHG2 // credits freeze_dict tot_stakes pubkey recovered f total stake + ADD // credits freeze_dict tot_stakes pubkey recovered f total }>ELSE<{ - 2SWAP - DROP // credits freeze_dict tot_stakes recovered pubkey f total + s4 s2 XCHG2 + DROP // credits freeze_dict tot_stakes pubkey recovered f total }> - SWAP // credits freeze_dict tot_stakes recovered pubkey total f - NOT // credits freeze_dict tot_stakes recovered pubkey total _32 - s1 s2 XCHG // credits freeze_dict tot_stakes recovered total pubkey _32 - }> // credits freeze_dict tot_stakes recovered total pubkey + SWAP // credits freeze_dict tot_stakes pubkey recovered total f + NOT // credits freeze_dict tot_stakes pubkey recovered total _32 + s1 s3 XCHG // credits freeze_dict tot_stakes total recovered pubkey _32 + }> // credits freeze_dict tot_stakes total recovered pubkey DROP - s3 POP // credits total tot_stakes recovered - -ROT // credits recovered total tot_stakes + s3 POP // credits recovered tot_stakes total + SWAP // credits recovered total tot_stakes EQUAL // credits recovered _34 59 THROWIFNOT }> unfreeze_with_bonuses PROC:<{ // credits freeze_dict tot_stakes tot_bonuses - 0 PUSHINT // credits freeze_dict tot_stakes tot_bonuses returned_bonuses=0 - s0 s0 PUSH2 // credits freeze_dict tot_stakes tot_bonuses returned_bonuses=0 recovered=0 total=0 - -1 PUSHINT // credits freeze_dict tot_stakes tot_bonuses returned_bonuses=0 recovered=0 total=0 pubkey=-1 + 0 PUSHINT // credits freeze_dict tot_stakes tot_bonuses _7=0 + s0 s0 PUSH2 // credits freeze_dict tot_stakes tot_bonuses total=0 returned_bonuses=0 recovered=0 + -1 PUSHINT // credits freeze_dict tot_stakes tot_bonuses total=0 returned_bonuses=0 recovered=0 pubkey=-1 UNTIL:<{ s6 PUSH - 8 PUSHPOW2 // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total pubkey freeze_dict _12=256 + 8 PUSHPOW2 // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey freeze_dict _12=256 DICTUGETNEXT NULLSWAPIFNOT - NULLSWAPIFNOT // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total cs pubkey f - DUP // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total cs pubkey f f - IF:<{ // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total cs pubkey f - s0 s2 XCHG // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey cs - 256 LDU // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey _18 cs - 64 LDU // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey _18 _52 _51 - NIP // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey _18 cs - LDGRAMS // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey _18 _24 cs - 1 LDI // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey addr stake banned cs + NULLSWAPIFNOT // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f + DUP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f f + IF:<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered cs pubkey f + s0 s2 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey cs + 256 LDU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 cs + 64 LDU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 _52 _51 + NIP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 cs + LDGRAMS // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey _18 _24 cs + 1 LDI // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake banned cs ENDS - IF:<{ // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey addr stake - NIP // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey stake - s4 s4 XCPU // credits freeze_dict tot_stakes tot_bonuses returned_bonuses stake total f pubkey recovered stake - ADD // credits freeze_dict tot_stakes tot_bonuses returned_bonuses stake total f pubkey recovered - }>ELSE<{ // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey addr stake - s7 s0 s8 PUSH3 // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey addr stake tot_bonuses stake tot_stakes - MULDIV // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey addr stake bonus - s7 s7 XCPU // credits freeze_dict tot_stakes tot_bonuses bonus recovered total f pubkey addr stake returned_bonuses bonus - ADD // credits freeze_dict tot_stakes tot_bonuses bonus recovered total f pubkey addr stake returned_bonuses - s1 s7 PUXC // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey addr stake stake bonus - ADD // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey addr stake _35 - s11 s11 s0 XCHG3 // stake freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey credits addr _35 - ~credit_to CALLDICT // stake freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total f pubkey credits + IF:<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake + NIP // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey stake + s3 s3 XCPU // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered stake + ADD // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered + }>ELSE<{ // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake + s7 s0 s8 PUSH3 // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake tot_bonuses stake tot_stakes + MULDIV // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake bonus + s6 s6 XCPU // credits freeze_dict tot_stakes tot_bonuses total bonus recovered f pubkey addr stake returned_bonuses bonus + ADD // credits freeze_dict tot_stakes tot_bonuses total bonus recovered f pubkey addr stake returned_bonuses + s1 s6 PUXC // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake stake bonus + ADD // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey addr stake _35 + s11 s11 s0 XCHG3 // stake freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey credits addr _35 + ~credit_to CALLDICT // stake freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered f pubkey credits s0 s9 XCHG - s0 s4 XCHG // credits freeze_dict tot_stakes tot_bonuses returned_bonuses stake total f pubkey recovered + s0 s3 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses stake f pubkey recovered }> - s3 s4 XCHG2 // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered pubkey f total stake - ADD // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered pubkey f total + s5 s3 XCHG2 // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total stake + ADD // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total }>ELSE<{ - 2SWAP - DROP // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered pubkey f total + s5 s2 XCHG2 + DROP // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered f total }> - SWAP // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered pubkey total f - NOT // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered pubkey total _38 - s1 s2 XCHG // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total pubkey _38 - }> // credits freeze_dict tot_stakes tot_bonuses returned_bonuses recovered total pubkey + SWAP // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered total f + NOT // credits freeze_dict tot_stakes tot_bonuses pubkey returned_bonuses recovered total _38 + s1 s4 XCHG // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey _38 + }> // credits freeze_dict tot_stakes tot_bonuses total returned_bonuses recovered pubkey DROP - s5 POP // credits total tot_stakes tot_bonuses returned_bonuses recovered - s4 s3 XCHG2 // credits returned_bonuses recovered tot_bonuses total tot_stakes - EQUAL // credits returned_bonuses recovered tot_bonuses _40 - s3 s1 PUSH2 // credits returned_bonuses recovered tot_bonuses _40 returned_bonuses tot_bonuses - LEQ // credits returned_bonuses recovered tot_bonuses _40 _41 - AND // credits returned_bonuses recovered tot_bonuses _42 + s5 POP // credits recovered tot_stakes tot_bonuses total returned_bonuses + s0 s3 XCHG // credits recovered returned_bonuses tot_bonuses total tot_stakes + EQUAL // credits recovered returned_bonuses tot_bonuses _40 + s2 s1 PUSH2 // credits recovered returned_bonuses tot_bonuses _40 returned_bonuses tot_bonuses + LEQ // credits recovered returned_bonuses tot_bonuses _40 _41 + AND // credits recovered returned_bonuses tot_bonuses _42 59 THROWIFNOT + s1 s2 XCHG // credits returned_bonuses recovered tot_bonuses ADD // credits returned_bonuses _44 SWAP // credits _44 returned_bonuses SUB // credits _45 diff --git a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate-test.fif b/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate-test.fif index 2e6d87a75e..6fe3fbed03 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate-test.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate-test.fif @@ -121,7 +121,7 @@ dup make_special dup constant smc3_addr ."address = " x. cr // SmartContract #4 (elector) -"elector-code.fif" include // code in separate source file +"auto/elector-code.fif" include // code in separate source file // data GR$10 // balance: 10 grams 0 // split_depth diff --git a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate.fif b/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate.fif index e66bb4f572..70abe412e0 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/gen-zerostate.fif @@ -133,7 +133,7 @@ dup make_special dup constant smc3_addr * SmartContract #4 (elector) * */ -"elector-code.fif" include // code in separate source file +"auto/elector-code.fif" include // code in separate source file // data: dict dict dict grams uint32 uint256 empty_cell // libraries GR$10 // balance: 10 grams @@ -173,7 +173,7 @@ config.special! // gas_price gas_limit special_gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit flat_gas_limit flat_gas_price -- 1000 sg* 1 *M dup 10000 10 *M GR$0.1 GR$1.0 100 100000 config.gas_prices! -10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 0 0 config.mc_gas_prices! +10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 100 1000000 config.mc_gas_prices! // lump_price bit_price cell_price ihr_factor first_frac next_frac 1000000 1000 sg* 100000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.fwd_prices! 10000000 10000 sg* 1000000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.mc_fwd_prices! @@ -202,8 +202,7 @@ smc1_addr config.minter_smc! // 17 add-validator // newkeypair nip dup ."Validator #2 public key = " Bx. cr // 239 add-validator -// 100000 =: orig_vset_valid_for -100 =: orig_vset_valid_for // original validator set valid 100 seconds only (DEBUG) +100000 =: orig_vset_valid_for // original validator set valid 100000 seconds now dup orig_vset_valid_for + 0 config.validators! /* @@ -211,7 +210,7 @@ now dup orig_vset_valid_for + 0 config.validators! * SmartContract #5 (Configuration smart contract) * */ -"config-code.fif" include // code in separate source file +"auto/config-code.fif" include // code in separate source file []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet.fif old mode 100644 new mode 100755 index ab69fdf368..e851016cc9 --- a/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/highload-wallet.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/multisig-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/multisig-code.fc new file mode 100644 index 0000000000..cbe2d30feb --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/multisig-code.fc @@ -0,0 +1,265 @@ +;; Simple wallet smart contract + +_ unpack_state() inline_ref { + var ds = begin_parse(get_data()); + var res = (ds~load_uint(8), ds~load_uint(8), ds~load_uint(64), ds~load_dict(), ds~load_dict()); + ds.end_parse(); + return res; +} + +_ pack_state(cell pending_queries, cell public_keys, int last_cleaned, int k, int n) inline_ref { + return begin_cell() + .store_uint(n, 8) + .store_uint(k, 8) + .store_uint(last_cleaned, 64) + .store_dict(public_keys) + .store_dict(pending_queries) + .end_cell(); +} + +(int, int) check_signatures(cell public_keys, cell signatures, int hash, int cnt_bits) inline_ref { + int cnt = 0; + + do { + slice cs = signatures.begin_parse(); + slice signature = cs~load_bits(512); + + int i = cs~load_uint(8); + signatures = cs~load_dict(); + + (slice public_key, var found?) = public_keys.udict_get?(8, i); + throw_unless(37, found?); + throw_unless(38, check_signature(hash, signature, public_key.preload_uint(256))); + + int mask = (1 << i); + int old_cnt_bits = cnt_bits; + cnt_bits |= mask; + int should_check = cnt_bits != old_cnt_bits; + cnt -= should_check; + } until (cell_null?(signatures)); + + return (cnt, cnt_bits); +} + + +() recv_internal(slice in_msg) impure { + ;; do nothing for internal messages +} + +(int, int, slice) unpack_query_data(slice in_msg, int n, slice query, var found?) inline_ref { + if (found?) { + throw_unless(35, query~load_int(1)); + (int cnt, int cnt_bits, slice msg) = (query~load_uint(8), query~load_uint(n), query); + throw_unless(36, slice_hash(msg) == slice_hash(in_msg)); + return (cnt, cnt_bits, msg); + } + return (0, 0, in_msg); +} + +() try_init() impure inline_ref { + ;; first query without signatures is always accepted + (int n, int k, int last_cleaned, cell public_keys, cell pending_queries) = unpack_state(); + throw_if(37, last_cleaned); + accept_message(); + set_data(pack_state(pending_queries, public_keys, 1, k, n)); +} + +cell update_pending_queries(cell pending_queries, slice msg, int query_id, int cnt, int cnt_bits, int n, int k) impure inline_ref { + if (cnt >= k) { + while (msg.slice_refs()) { + var mode = msg~load_uint(8); + send_raw_message(msg~load_ref(), mode); + } + pending_queries~udict_set_builder(64, query_id, begin_cell().store_int(0, 1)); + } else { + pending_queries~udict_set_builder(64, query_id, begin_cell() + .store_uint(1, 1) + .store_uint(cnt, 8) + .store_uint(cnt_bits, n) + .store_slice(msg)); + } + return pending_queries; +} + +() recv_external(slice in_msg) impure { + ;; empty message triggers init + if (slice_empty?(in_msg)) { + return try_init(); + } + + ;; Check root signature + slice root_signature = in_msg~load_bits(512); + int root_hash = slice_hash(in_msg); + int root_i = in_msg~load_uint(8); + + (int n, int k, int last_cleaned, cell public_keys, cell pending_queries) = unpack_state(); + last_cleaned -= last_cleaned == 0; + + (slice public_key, var found?) = public_keys.udict_get?(8, root_i); + throw_unless(31, found?); + throw_unless(32, check_signature(root_hash, root_signature, public_key.preload_uint(256))); + + cell signatures = in_msg~load_dict(); + + var hash = slice_hash(in_msg); + int query_id = in_msg~load_uint(64); + + var bound = (now() << 32); + throw_if(33, query_id < bound); + + (slice query, var found?) = pending_queries.udict_get?(64, query_id); + (int cnt, int cnt_bits, slice msg) = unpack_query_data(in_msg, n, query, found?); + int mask = 1 << root_i; + throw_if(34, cnt_bits & mask); + cnt_bits |= mask; + cnt += 1; + + ;; TODO: reserve some gas or FAIL + accept_message(); + + pending_queries = update_pending_queries(pending_queries, msg, query_id, cnt, cnt_bits, n, k); + set_data(pack_state(pending_queries, public_keys, last_cleaned, k, n)); + + commit(); + + int need_save = 0; + ifnot (cell_null?(signatures) | (cnt >= k)) { + (int new_cnt, cnt_bits) = check_signatures(public_keys, signatures, hash, cnt_bits); + cnt += new_cnt; + pending_queries = update_pending_queries(pending_queries, msg, query_id, cnt, cnt_bits, n, k); + need_save = -1; + } + + bound -= (64 << 32); ;; clean up records expired more than 64 seconds ago + int old_last_cleaned = last_cleaned; + do { + var (pending_queries', i, _, f) = pending_queries.udict_delete_get_min(64); + f~touch(); + if (f) { + f = (i < bound); + } + if (f) { + pending_queries = pending_queries'; + last_cleaned = i; + need_save = -1; + } + } until (~ f); + + if (need_save) { + set_data(pack_state(pending_queries, public_keys, last_cleaned, k, n)); + } +} + +;; Get methods +;; returns -1 for processed queries, 0 for unprocessed, 1 for unknown (forgotten) +(int, int) get_query_state(int query_id) method_id { + (int n, _, int last_cleaned, _, cell pending_queries) = unpack_state(); + (slice cs, var found) = pending_queries.udict_get?(64, query_id); + if (found) { + if (cs~load_int(1)) { + cs~load_uint(8); + return (0, cs~load_uint(n)); + } else { + return (-1, 0); + } + } else { + return (-(query_id <= last_cleaned), 0); + } +} + +int processed?(int query_id) method_id { + (int x, _) = get_query_state(query_id); + return x; +} + +cell create_init_state(int n, int k, cell public_keys) method_id { + return pack_state(new_dict(), public_keys, 0, k, n); +} + +cell merge_list(cell a, cell b) { + if (cell_null?(a)) { + return b; + } + if (cell_null?(b)) { + return a; + } + slice as = a.begin_parse(); + if (as.slice_refs() != 0) { + cell tail = merge_list(as~load_ref(), b); + return begin_cell().store_slice(as).store_ref(tail).end_cell(); + } + + as~skip_last_bits(1); + ;; as~skip_bits(1); + return begin_cell().store_slice(as).store_dict(b).end_cell(); + +} + +cell get_public_keys() method_id { + (_, _, _, cell public_keys, _) = unpack_state(); + return public_keys; +} + +(int, int) check_query_signatures(cell query) method_id { + slice cs = query.begin_parse(); + slice root_signature = cs~load_bits(512); + int root_hash = slice_hash(cs); + int root_i = cs~load_uint(8); + + cell public_keys = get_public_keys(); + (slice public_key, var found?) = public_keys.udict_get?(8, root_i); + throw_unless(31, found?); + throw_unless(32, check_signature(root_hash, root_signature, public_key.preload_uint(256))); + + int mask = 1 << root_i; + + cell signatures = cs~load_dict(); + if (cell_null?(signatures)) { + return (1, mask); + } + (int cnt, mask) = check_signatures(public_keys, signatures, slice_hash(cs), mask); + return (cnt + 1, mask); +} + +cell messages_by_mask(int mask) method_id { + (int n, _, _, _, cell pending_queries) = unpack_state(); + int i = -1; + cell a = new_dict(); + do { + (i, var cs, var f) = pending_queries.udict_get_next?(64, i); + if (f) { + if (cs~load_int(1)) { + int cnt_bits = cs.skip_bits(8).preload_uint(n); + if (cnt_bits & mask) { + a~udict_set_builder(64, i, begin_cell().store_slice(cs)); + } + } + } + } until (~ f); + return a; +} + +cell get_messages_unsigned_by_id(int id) method_id { + return messages_by_mask(1 << id); +} + +cell get_messages_unsigned() method_id { + return messages_by_mask(~ 0); +} + +(int, int) get_n_k() method_id { + (int n, int k, _, _, _) = unpack_state(); + return (n, k); +} + +cell merge_inner_queries(cell a, cell b) method_id { + slice ca = a.begin_parse(); + slice cb = b.begin_parse(); + cell list_a = ca~load_dict(); + cell list_b = cb~load_dict(); + throw_unless(31, slice_hash(ca) == slice_hash(cb)); + return begin_cell() + .store_dict(merge_list(list_a, list_b)) + .store_slice(ca) + .end_cell(); +} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet-v2.fif old mode 100644 new mode 100755 index df386cc72a..d0183b2250 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet-v2.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/new-highload-wallet-v2.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include "Asm.fif" include @@ -19,8 +19,8 @@ def? $3 { @' $3 } { "new-wallet" } cond constant file-base ."Creating new v2 high-load wallet in workchain " wc . ."with subwallet id " subwallet-id . cr -// Create new high-load wallet; source code included from `highload-wallet-v2-code.fif` -"highload-wallet-v2-code.fif" include +// Create new high-load wallet; source code included from `auto/highload-wallet-v2-code.fif` +"auto/highload-wallet-v2-code.fif" include // code []" cr + ."Creates a restricted wallet in the masterchain controlled by the private key corresponding to the specified public key" cr + ."and saves its address into .addr ('rwallet.addr' by default)" cr 1 halt +} : usage +$# 1- -2 and ' usage if + +-1 =: wc +$1 parse-pubkey =: PubKey +def? $2 { @' $2 } { "rwallet" } cond constant file-base + +."Creating new restricted wallet in workchain " wc . ."controlled by public key " PubKey .pubkey cr + +// Create new restricted wallet; code taken from `auto/restricted-wallet-code.fif` +"auto/restricted-wallet-code.fif" include // code + // data +null // no libraries + // create StateInit +dup ."StateInit: " +dup ."External message for initialization is " B dup Bx. cr +file-base +"-query.boc" tuck B>file +."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet2.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet2.fif new file mode 100644 index 0000000000..8f95e4c1cc --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/new-restricted-wallet2.fif @@ -0,0 +1,47 @@ +#!/usr/bin/fift -s +"TonUtil.fif" include +"Asm.fif" include + +{ ."usage: " @' $0 type ." []" cr + ."Creates a restricted lockup wallet in the masterchain controlled by the private key corresponding to the specified public key" cr + ."and saves its address into .addr ('rwallet.addr' by default)" cr 1 halt +} : usage +$# 2- -2 and ' usage if + +-1 =: wc +$1 parse-pubkey =: PubKey +$2 $>GR =: amount +def? $3 { @' $3 } { "rwallet" } cond constant file-base + +."Creating new restricted lockup wallet in workchain " wc . ."controlled by public key " PubKey .pubkey +." with nominal amount " amount .GR cr + +// D x t -- D' +{ idict! not abort"cannot add value" +} : rdict-entry +// balance -- dict +{ dictnew + over -32768 rdict-entry + over 3/4 */ 92 rdict-entry + over 1/2 */ 183 rdict-entry + swap 1/4 */ 366 rdict-entry + 0 548 rdict-entry +} : make-rdict + +// Create new restricted wallet; code taken from `auto/restricted-wallet2-code.fif` +"auto/restricted-wallet-code.fif" include // code + // data +null // no libraries + // create StateInit +dup ."StateInit: " +dup ."External message for initialization is " B dup Bx. cr +file-base +"-query.boc" tuck B>file +."(Saved wallet creating query to file " type .")" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-testgiver.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-testgiver.fif old mode 100644 new mode 100755 index 504a81bdeb..ad9789fa2f --- a/submodules/ton/tonlib-src/crypto/smartcont/new-testgiver.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/new-testgiver.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include "Asm.fif" include diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif old mode 100644 new mode 100755 index 39bb421bf9..d59c6c5201 --- a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet-v2.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include "Asm.fif" include @@ -13,7 +13,7 @@ def? $2 { @' $2 } { "new-wallet" } cond constant file-base ."Creating new advanced wallet in workchain " wc . cr -// Create new advanced wallet; code adapted from `wallet-code.fif` +// Create new advanced wallet; code adapted from `auto/wallet-code.fif` <{ SETCP0 DUP IFNOTRET // return if recv_internal DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method DROP c4 PUSHCTR CTOS 32 PLDU // cnt diff --git a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet.fif old mode 100644 new mode 100755 index 9bdb0bdb38..ac8d4a0e3a --- a/submodules/ton/tonlib-src/crypto/smartcont/new-wallet.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/new-wallet.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include "Asm.fif" include diff --git a/submodules/ton/tonlib-src/crypto/smartcont/recover-stake.fif b/submodules/ton/tonlib-src/crypto/smartcont/recover-stake.fif old mode 100644 new mode 100755 index 573cb336a2..871b3855bc --- a/submodules/ton/tonlib-src/crypto/smartcont/recover-stake.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/recover-stake.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet-code.fc new file mode 100644 index 0000000000..83639dfdff --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet-code.fc @@ -0,0 +1,67 @@ +;; Restricted wallet (a variant of wallet-code.fc) +;; until configuration parameter -13 is set, accepts messages only to elector smc + +() recv_internal(slice in_msg) impure { + ;; do nothing for internal messages +} + +_ restricted?() inline { + var p = config_param(-13); + return null?(p) ? true : begin_parse(p).preload_uint(32) > now(); +} + +_ check_destination(msg, dest) inline_ref { + var cs = msg.begin_parse(); + var flags = cs~load_uint(4); + if (flags & 8) { + ;; external messages are always valid + return true; + } + var (s_addr, d_addr) = (cs~load_msg_addr(), cs~load_msg_addr()); + var (dest_wc, dest_addr) = parse_std_addr(d_addr); + return (dest_wc == -1) & (dest_addr == dest); +} + +() recv_external(slice in_msg) impure { + var signature = in_msg~load_bits(512); + var cs = in_msg; + var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32)); + throw_if(35, valid_until <= now()); + var ds = get_data().begin_parse(); + var (stored_seqno, public_key) = (ds~load_uint(32), ds~load_uint(256)); + ds.end_parse(); + throw_unless(33, msg_seqno == stored_seqno); + ifnot (msg_seqno) { + accept_message(); + set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); + return (); + } + throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); + accept_message(); + var restrict = restricted?(); + var elector = config_param(1).begin_parse().preload_uint(256); + cs~touch(); + while (cs.slice_refs()) { + var mode = cs~load_uint(8); + var msg = cs~load_ref(); + var ok = true; + if (restrict) { + ok = check_destination(msg, elector); + } + if (ok) { + send_raw_message(msg, mode); + } + } + cs.end_parse(); + set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell()); +} + +;; Get methods + +int seqno() method_id { + return get_data().begin_parse().preload_uint(32); +} + +int balance() method_id { + return restricted?() ? 0 : get_balance().first(); +} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet2-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet2-code.fc new file mode 100644 index 0000000000..fa57e77d24 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/restricted-wallet2-code.fc @@ -0,0 +1,69 @@ +;; Restricted wallet (a variant of wallet-code.fc) +;; until configuration parameter -13 is set, accepts messages only to elector smc + +() recv_internal(slice in_msg) impure { + ;; do nothing for internal messages +} + +_ days_passed() inline { + var p = config_param(-13); + return null?(p) ? -1 : (now() - begin_parse(p).preload_uint(32)) / 86400; +} + +() recv_external(slice in_msg) impure { + var signature = in_msg~load_bits(512); + var cs = in_msg; + var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32)); + throw_if(35, valid_until <= now()); + var ds = get_data().begin_parse(); + var (stored_seqno, public_key, rdict) = (ds~load_uint(32), ds~load_uint(256), ds~load_dict()); + ds.end_parse(); + throw_unless(33, msg_seqno == stored_seqno); + ifnot (msg_seqno) { + accept_message(); + set_data(begin_cell() + .store_uint(stored_seqno + 1, 32) + .store_uint(public_key, 256) + .store_dict(rdict) + .end_cell()); + return (); + } + throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); + accept_message(); + var ts = days_passed(); + var (_, value, found) = rdict.idict_get_preveq?(16, ts); + if (found) { + raw_reserve(value~load_grams(), 2); + } + cs~touch(); + while (cs.slice_refs()) { + var mode = cs~load_uint(8); + var msg = cs~load_ref(); + send_raw_message(msg, mode); + } + cs.end_parse(); + set_data(begin_cell() + .store_uint(stored_seqno + 1, 32) + .store_uint(public_key, 256) + .store_dict(rdict) + .end_cell()); +} + +;; Get methods + +int seqno() method_id { + return get_data().begin_parse().preload_uint(32); +} + +int balance() method_id { + var ds = get_data().begin_parse().skip_bits(32 + 256); + var rdict = ds~load_dict(); + ds.end_parse(); + var ts = days_passed(); + var balance = get_balance().first(); + var (_, value, found) = rdict.idict_get_preveq?(16, ts); + if (found) { + balance = max(balance - value~load_grams(), 0); + } + return balance; +} diff --git a/submodules/ton/tonlib-src/crypto/smartcont/show-addr.fif b/submodules/ton/tonlib-src/crypto/smartcont/show-addr.fif old mode 100644 new mode 100755 index 74536528f8..5d3094644f --- a/submodules/ton/tonlib-src/crypto/smartcont/show-addr.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/show-addr.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." " cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-ext-code.fc b/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-ext-code.fc new file mode 100644 index 0000000000..a20b96a861 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smartcont/simple-wallet-ext-code.fc @@ -0,0 +1,67 @@ +;; Simple wallet smart contract + +cell create_state(int seqno, int public_key) { + return begin_cell().store_uint(seqno, 32).store_uint(public_key, 256).end_cell(); +} + +(int, int) load_state() { + var cs2 = begin_parse(get_data()); + return (cs2~load_uint(32), cs2~load_uint(256)); +} + +() save_state(int seqno, int public_key) impure { + set_data(create_state(seqno, public_key)); +} + +() recv_internal(slice in_msg) impure { + ;; do nothing for internal messages +} + +slice do_verify_message(slice in_msg, int seqno, int public_key) { + var signature = in_msg~load_bits(512); + var cs = in_msg; + int msg_seqno = cs~load_uint(32); + throw_unless(33, msg_seqno == seqno); + throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key)); + return cs; +} + +() recv_external(slice in_msg) impure { + (int stored_seqno, int public_key) = load_state(); + var cs = do_verify_message(in_msg, stored_seqno, public_key); + accept_message(); + cs~touch_slice(); + if (cs.slice_refs()) { + var mode = cs~load_uint(8); + send_raw_message(cs~load_ref(), mode); + } + cs.end_parse(); + save_state(stored_seqno + 1, public_key); +} + +;; Get methods + +int seqno() method_id { + return get_data().begin_parse().preload_uint(32); +} + +cell create_init_state(int public_key) method_id { + return create_state(0, public_key); +} + +cell prepare_send_message_with_seqno(int mode, cell msg, int seqno) method_id { + return begin_cell().store_uint(seqno, 32).store_uint(mode, 8).store_ref(msg).end_cell(); +} + +cell prepare_send_message(int mode, cell msg) method_id { + return prepare_send_message_with_seqno(mode, msg, seqno()); +} + + +slice verify_message(slice msg) method_id { + var (stored_seqno, public_key) = load_state(); + return do_verify_message(msg, stored_seqno, public_key); +} + + + diff --git a/submodules/ton/tonlib-src/crypto/smartcont/stdlib.fc b/submodules/ton/tonlib-src/crypto/smartcont/stdlib.fc index fb9b49f56a..d78f9ef1a5 100644 --- a/submodules/ton/tonlib-src/crypto/smartcont/stdlib.fc +++ b/submodules/ton/tonlib-src/crypto/smartcont/stdlib.fc @@ -1,8 +1,25 @@ ;; Standard library for funC ;; +forall X -> tuple cons(X head, tuple tail) asm "CONS"; +forall X -> (X, tuple) uncons(tuple list) asm "UNCONS"; +forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS"; +forall X -> X car(tuple list) asm "CAR"; +tuple cdr(tuple list) asm "CDR"; +forall X, Y -> tuple pair(X x, Y y) asm "PAIR"; +forall X, Y -> (X, Y) unpair(tuple t) asm "UNPAIR"; +forall X, Y, Z -> tuple triple(X x, Y y, Z z) asm "TRIPLE"; +forall X, Y, Z -> (X, Y, Z) untriple(tuple t) asm "UNTRIPLE"; +forall X, Y, Z, W -> tuple tuple4(X x, Y y, Z z, W w) asm "4 TUPLE"; +forall X, Y, Z, W -> (X, Y, Z, W) untuple4(tuple t) asm "4 UNTUPLE"; +forall X -> X first(tuple t) asm "FIRST"; +forall X -> X second(tuple t) asm "SECOND"; +forall X -> X third(tuple t) asm "THIRD"; +forall X -> X fourth(tuple t) asm "3 INDEX"; + int now() asm "NOW"; slice my_address() asm "MYADDR"; +tuple get_balance() asm "BALANCE"; int cell_hash(cell c) asm "HASHCU"; int slice_hash(slice s) asm "HASHSU"; @@ -17,8 +34,10 @@ int check_data_signature(slice data, slice signature, int public_key) asm "CHKSI cell get_data() asm "c4 PUSH"; () set_data(cell c) impure asm "c4 POP"; +cell get_c3() impure asm "c3 PUSH"; () set_c3(cell c) impure asm "c3 POP"; () accept_message() impure asm "ACCEPT"; +() commit() impure asm "COMMIT"; int min(int x, int y) asm "MIN"; int max(int x, int y) asm "MAX"; @@ -36,6 +55,7 @@ cell preload_ref(slice s) asm "PLDREF"; (slice, int) load_grams(slice s) asm( -> 1 0) "LDGRAMS"; slice skip_bits(slice s, int len) asm "SDSKIPFIRST"; slice first_bits(slice s, int len) asm "SDCUTFIRST"; +(slice, ()) skip_last_bits(slice s, int len) asm "SDSKIPLAST"; (slice, cell) load_dict(slice s) asm( -> 1 0) "LDDICT"; cell preload_dict(slice s) asm "PLDDICT"; slice skip_dict(slice s) asm "SKIPDICT"; @@ -63,15 +83,30 @@ tuple parse_addr(slice s) asm "PARSEMSGADDR"; cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; (cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF"; +cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF"; +(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF"; cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF"; +cell udict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETOPTREF"; (cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF"; +(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF"; (cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL"; +(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDEL"; (slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT"; (slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGET" "NULLSWAPIFNOT"; (cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT"; (cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT"; (cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT"; (cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT"; +cell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET"; +(cell, ()) ~udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET"; +cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET"; +(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET"; +cell dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET"; +(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET"; +(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUADD"; +(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACE"; +(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIADD"; +(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACE"; cell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB"; (cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB"; cell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB"; @@ -80,14 +115,28 @@ cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(va (cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB"; (cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUADDB"; (cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEB"; +(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIADDB"; +(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEB"; (cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; (cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, (int, slice, int)) ~idict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; (cell, slice, slice, int) dict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; (cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, (int, slice, int)) ~udict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; (int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; (int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; (int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; (int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; +(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT"; cell new_dict() asm "NEWDICT"; int dict_empty?(cell c) asm "DICTEMPTY"; diff --git a/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif b/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif old mode 100644 new mode 100755 index fe812487a5..c48735aca1 --- a/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/testgiver.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/update-config-smc.fif b/submodules/ton/tonlib-src/crypto/smartcont/update-config-smc.fif old mode 100644 new mode 100755 index 22f01f0456..33e5fbcebc --- a/submodules/ton/tonlib-src/crypto/smartcont/update-config-smc.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/update-config-smc.fif @@ -1,8 +1,8 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr - ."Creates a request to simple configuration smart contract requesting to change configuration smart contract code to the one currently stored in config-code.fif, " + ."Creates a request to simple configuration smart contract requesting to change configuration smart contract code to the one currently stored in auto/config-code.fif, " ."with private key loaded from file .pk, " ."and saves it into .boc ('config-query.boc' by default)" cr 1 halt } : usage @@ -12,7 +12,7 @@ $# dup 2 < swap 3 > or ' usage if 0 constant seqno -1 constant idx true constant bounce -"config-code.fif" constant config-source +"auto/config-code.fif" constant config-source 100 constant interval // valid for 100 seconds $1 =: file-base diff --git a/submodules/ton/tonlib-src/crypto/smartcont/update-config.fif b/submodules/ton/tonlib-src/crypto/smartcont/update-config.fif old mode 100644 new mode 100755 index f58b5cf4f1..fcb8cf161b --- a/submodules/ton/tonlib-src/crypto/smartcont/update-config.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/update-config.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/update-elector-smc.fif b/submodules/ton/tonlib-src/crypto/smartcont/update-elector-smc.fif old mode 100644 new mode 100755 index 2531345e1e..b9ce501f3f --- a/submodules/ton/tonlib-src/crypto/smartcont/update-elector-smc.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/update-elector-smc.fif @@ -1,8 +1,8 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr - ."Creates a request to simple configuration smart contract requesting to change elector smart contract code to the one currently stored in elector-code.fif, " + ."Creates a request to simple configuration smart contract requesting to change elector smart contract code to the one currently stored in auto/elector-code.fif, " ."with private key loaded from file .pk, " ."and saves it into .boc ('config-query.boc' by default)" cr 1 halt } : usage @@ -12,7 +12,7 @@ $# dup 2 < swap 3 > or ' usage if 0 constant seqno -1 constant idx true constant bounce -"elector-code.fif" constant elector-source +"auto/elector-code.fif" constant elector-source 100 constant interval // valid for 100 seconds $1 =: file-base diff --git a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-req.fif b/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-req.fif old mode 100644 new mode 100755 index c2aca4b5b6..215fe9c15c --- a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-req.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-req.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-signed.fif b/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-signed.fif old mode 100644 new mode 100755 index 9755bfac67..55e3d9ddac --- a/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-signed.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/validator-elect-signed.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet-v2.fif b/submodules/ton/tonlib-src/crypto/smartcont/wallet-v2.fif old mode 100644 new mode 100755 index 910f7d41f1..3d36643b45 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet-v2.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/wallet-v2.fif @@ -1,4 +1,4 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include { ."usage: " @' $0 type ." [-B ] []" cr diff --git a/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif b/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif old mode 100644 new mode 100755 index 59dbf71c28..f4eb280255 --- a/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif +++ b/submodules/ton/tonlib-src/crypto/smartcont/wallet.fif @@ -1,12 +1,17 @@ -#!/usr/bin/env fift -s +#!/usr/bin/fift -s "TonUtil.fif" include -{ ."usage: " @' $0 type ." [-B ] []" cr +{ ."usage: " @' $0 type ." [-B ] [-C ] []" cr ."Creates a request to simple wallet created by new-wallet.fif, with private key loaded from file .pk " ."and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" cr 1 halt } : usage -def? $6 { @' $5 "-B" $= { @' $6 =: body-boc-file [forget] $6 def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond - @' $# 2- =: $# } if } if +"" =: comment // comment for simple transfers +def? $6 { @' $5 dup "-B" $= swap "-C" $= tuck or + { @' $6 swap { =: comment } { =: body-boc-file } cond [forget] $6 + def? $7 { @' $7 =: $5 [forget] $7 } { [forget] $5 } cond + @' $# 2- =: $# + } if +} if $# dup 4 < swap 5 > or ' usage if true constant bounce @@ -17,13 +22,14 @@ $3 parse-int =: seqno $4 $>GR =: amount def? $5 { @' $5 } { "wallet-query" } cond constant savefile 3 constant send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors +// "" 1 { 69091 * 1+ 65535 and tuck 2521 / 65 + hold swap } 1000 times drop =: comment file-base +".addr" load-address 2dup 2constant wallet_addr ."Source wallet address = " 2dup .addr cr 6 .Addr cr file-base +".pk" load-keypair nip constant wallet_pk -def? body-boc-file { @' body-boc-file file>B B>boc } { } cond +def? body-boc-file { @' body-boc-file file>B B>boc } { comment simple-transfer-body } cond constant body-cell ."Transferring " amount .GR ."to account " diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.cpp new file mode 100644 index 0000000000..20750fcbad --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.cpp @@ -0,0 +1,99 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "GenericAccount.h" + +#include "block/block-auto.h" +#include "block/block-parse.h" +namespace ton { +td::Ref GenericAccount::get_init_state(td::Ref code, td::Ref data) noexcept { + return vm::CellBuilder() + .store_zeroes(2) + .store_ones(2) + .store_zeroes(1) + .store_ref(std::move(code)) + .store_ref(std::move(data)) + .finalize(); +} +block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id, + const td::Ref& init_state) noexcept { + return block::StdAddress(workchain_id, init_state->get_hash().bits(), true /*bounce*/); +} + +void GenericAccount::store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms) { + td::BigInt256 dest_addr; + dest_addr.import_bits(dest_address.addr.as_bitslice()); + cb.store_zeroes(1) + .store_ones(1) + .store_long(dest_address.bounceable, 1) + .store_zeroes(3) + .store_ones(1) + .store_zeroes(2) + .store_long(dest_address.workchain, 8) + .store_int256(dest_addr, 256); + block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms)); + cb.store_zeroes(9 + 64 + 32 + 1 + 1); +} + +td::Ref GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref new_state, + td::Ref body) noexcept { + block::gen::Message::Record message; + /*info*/ { + block::gen::CommonMsgInfo::Record_ext_in_msg_info info; + /* src */ + tlb::csr_pack(info.src, block::gen::MsgAddressExt::Record_addr_none{}); + /* dest */ { + block::gen::MsgAddressInt::Record_addr_std dest; + dest.anycast = vm::CellBuilder().store_zeroes(1).as_cellslice_ref(); + dest.workchain_id = address.workchain; + dest.address = address.addr; + + tlb::csr_pack(info.dest, dest); + } + /* import_fee */ { + vm::CellBuilder cb; + block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(0)); + info.import_fee = cb.as_cellslice_ref(); + } + + tlb::csr_pack(message.info, info); + } + /* init */ { + if (new_state.not_null()) { + // Just(Left(new_state)) + message.init = vm::CellBuilder() + .store_ones(1) + .store_zeroes(1) + .append_cellslice(vm::load_cell_slice(new_state)) + .as_cellslice_ref(); + } else { + message.init = vm::CellBuilder().store_zeroes(1).as_cellslice_ref(); + CHECK(message.init.not_null()); + } + } + /* body */ { + message.body = vm::CellBuilder().store_zeroes(1).append_cellslice(vm::load_cell_slice_ref(body)).as_cellslice_ref(); + } + + td::Ref res; + tlb::type_pack_cell(res, block::gen::t_Message_Any, message); + CHECK(res.not_null()); + + return res; +} +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.h b/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.h new file mode 100644 index 0000000000..003b8e1b76 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/GenericAccount.h @@ -0,0 +1,31 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once +#include "vm/cells.h" +#include "block/block.h" +namespace ton { +class GenericAccount { + public: + static td::Ref get_init_state(td::Ref code, td::Ref data) noexcept; + static block::StdAddress get_address(ton::WorkchainId workchain_id, const td::Ref& init_state) noexcept; + static td::Ref create_ext_message(const block::StdAddress& address, td::Ref new_state, + td::Ref body) noexcept; + static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms); +}; +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.cpp new file mode 100644 index 0000000000..36830179c5 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.cpp @@ -0,0 +1,171 @@ +#include "MultisigWallet.h" + +#include "SmartContractCode.h" + +#include "vm/dict.h" + +#include "td/utils/misc.h" + +namespace ton { + +MultisigWallet::QueryBuilder::QueryBuilder(td::int64 query_id, td::Ref msg, int mode) { + msg_ = vm::CellBuilder().store_long(query_id, 64).store_long(mode, 8).store_ref(std::move(msg)).finalize(); +} +void MultisigWallet::QueryBuilder::sign(td::int32 id, td::Ed25519::PrivateKey& pk) { + CHECK(id < td::narrow_cast(mask_.size())); + auto signature = pk.sign(msg_->get_hash().as_slice()).move_as_ok(); + mask_.set(id); + vm::CellBuilder cb; + cb.store_bytes(signature.as_slice()); + cb.store_long(id, 8); + cb.ensure_throw(cb.store_maybe_ref(std::move(dict_))); + dict_ = cb.finalize(); +} + +td::Ref MultisigWallet::QueryBuilder::create_inner() const { + vm::CellBuilder cb; + cb.ensure_throw(cb.store_maybe_ref(dict_)); + return cb.append_cellslice(vm::load_cell_slice(msg_)).finalize(); +} + +td::Ref MultisigWallet::QueryBuilder::create(td::int32 id, td::Ed25519::PrivateKey& pk) const { + auto cell = create_inner(); + vm::CellBuilder cb; + cb.store_long(id, 8); + cb.append_cellslice(vm::load_cell_slice(cell)); + cell = cb.finalize(); + + auto signature = pk.sign(cell->get_hash().as_slice()).move_as_ok(); + vm::CellBuilder cb2; + cb2.store_bytes(signature.as_slice()); + cb2.append_cellslice(vm::load_cell_slice(cell)); + return cb2.finalize(); +} + +td::Ref MultisigWallet::create(td::Ref data) { + return td::Ref(true, State{ton::SmartContractCode::multisig(), std::move(data)}); +} + +int MultisigWallet::processed(td::uint64 query_id) const { + auto res = run_get_method("processed?", {td::make_refint(query_id)}); + return res.stack.write().pop_smallint_range(1, -1); +} + +MultisigWallet::QueryState MultisigWallet::get_query_state(td::uint64 query_id) const { + auto ans = run_get_method("get_query_state", {td::make_refint(query_id)}); + + auto mask = ans.stack.write().pop_int(); + auto state = ans.stack.write().pop_smallint_range(1, -1); + + QueryState res; + if (state == 1) { + res.state = QueryState::Unknown; + } else if (state == 0) { + res.state = QueryState::NotReady; + for (size_t i = 0; i < res.mask.size(); i++) { + if (mask->get_bit(static_cast(i))) { + res.mask.set(i); + } + } + } else { + res.state = QueryState::Sent; + } + return res; +} + +std::vector MultisigWallet::get_public_keys() const { + auto ans = run_get_method("get_public_keys"); + auto dict_root = ans.stack.write().pop_cell(); + vm::Dictionary dict(std::move(dict_root), 8); + std::vector res; + dict.check_for_each([&](auto cs, auto x, auto y) { + td::SecureString key(32); + cs->prefetch_bytes(key.as_mutable_slice().ubegin(), td::narrow_cast(key.size())); + res.push_back(std::move(key)); + return true; + }); + return res; +} + +td::Ref MultisigWallet::create_init_data(std::vector public_keys, int k) const { + vm::Dictionary pk(8); + for (size_t i = 0; i < public_keys.size(); i++) { + auto key = pk.integer_key(td::make_refint(i), 8, false); + pk.set_builder(key.bits(), 8, vm::CellBuilder().store_bytes(public_keys[i].as_slice())); + } + auto res = run_get_method("create_init_state", + {td::make_refint(public_keys.size()), td::make_refint(k), pk.get_root_cell()}); + CHECK(res.code == 0); + return res.stack.write().pop_cell(); +} + +td::Ref MultisigWallet::create_init_data_fast(std::vector public_keys, int k) { + vm::Dictionary pk(8); + for (size_t i = 0; i < public_keys.size(); i++) { + auto key = pk.integer_key(td::make_refint(i), 8, false); + pk.set_builder(key.bits(), 8, vm::CellBuilder().store_bytes(public_keys[i].as_slice())); + } + + vm::CellBuilder cb; + cb.store_long(public_keys.size(), 8).store_long(k, 8).store_long(0, 64); + cb.ensure_throw(cb.store_maybe_ref(pk.get_root_cell())); + cb.ensure_throw(cb.store_maybe_ref({})); + return cb.finalize(); +} + +td::Ref MultisigWallet::merge_queries(td::Ref a, td::Ref b) const { + auto res = run_get_method("merge_queries", {a, b}); + return res.stack.write().pop_cell(); +} + +MultisigWallet::Mask MultisigWallet::to_mask(td::RefInt256 mask) const { + Mask res_mask; + for (size_t i = 0; i < res_mask.size(); i++) { + if (mask->get_bit(static_cast(i))) { + res_mask.set(i); + } + } + return res_mask; +} + +std::pair MultisigWallet::check_query_signatures(td::Ref a) const { + auto ans = run_get_method("check_query_signatures", {a}); + + auto mask = ans.stack.write().pop_int(); + auto cnt = ans.stack.write().pop_smallint_range(128); + return std::make_pair(cnt, to_mask(mask)); +} + +std::pair MultisigWallet::get_n_k() const { + auto ans = run_get_method("get_n_k"); + auto k = ans.stack.write().pop_smallint_range(128); + auto n = ans.stack.write().pop_smallint_range(128); + return std::make_pair(n, k); +} + +std::vector MultisigWallet::get_unsigned_messaged(int id) const { + SmartContract::Answer ans; + if (id == -1) { + ans = run_get_method("get_messages_unsigned"); + } else { + ans = run_get_method("get_messages_unsigned_by_id", {td::make_refint(id)}); + } + auto n_k = get_n_k(); + + auto cell = ans.stack.write().pop_maybe_cell(); + vm::Dictionary dict(std::move(cell), 64); + std::vector res; + dict.check_for_each([&](auto cs, auto ptr, auto ptr_bits) { + cs.write().skip_first(8); + Message message; + td::BigInt256 query_id; + query_id.import_bits(ptr, ptr_bits, false); + message.query_id = static_cast(query_id.to_long()); + message.signed_by = to_mask(cs.write().fetch_int256(n_k.first, false)); + message.message = cs.write().fetch_ref(); + res.push_back(std::move(message)); + return true; + }); + return res; +} +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.h b/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.h new file mode 100644 index 0000000000..10c6d07604 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/MultisigWallet.h @@ -0,0 +1,64 @@ +#pragma once +#include "vm/cells.h" + +#include "SmartContract.h" +#include "Ed25519.h" + +#include + +namespace ton { +class MultisigWallet : public ton::SmartContract { + public: + MultisigWallet(State state) : SmartContract(std::move(state)) { + } + + using Mask = std::bitset<128>; + struct QueryState { + enum State { Unknown, NotReady, Sent } state = Unknown; + Mask mask; + }; + + class QueryBuilder { + public: + QueryBuilder(td::int64 query_id, td::Ref msg, int mode = 3); + void sign(td::int32 id, td::Ed25519::PrivateKey& pk); + + td::Ref create_inner() const; + td::Ref create(td::int32 id, td::Ed25519::PrivateKey& pk) const; + Mask get_mask() const { + return mask_; + } + + private: + vm::Ref dict_; + td::Ref msg_; + Mask mask_; + }; + + MultisigWallet* make_copy() const override { + return new MultisigWallet{state_}; + } + + // creation + static td::Ref create(td::Ref data = {}); + + td::Ref create_init_data(std::vector public_keys, int k) const; + static td::Ref create_init_data_fast(std::vector public_keys, int k); + + // get methods + int processed(td::uint64 query_id) const; + QueryState get_query_state(td::uint64 query_id) const; + std::vector get_public_keys() const; + td::Ref merge_queries(td::Ref a, td::Ref b) const; + std::pair check_query_signatures(td::Ref a) const; + std::pair get_n_k() const; + Mask to_mask(td::RefInt256 mask) const; + + struct Message { + td::uint64 query_id; + Mask signed_by; + td::Ref message; + }; + std::vector get_unsigned_messaged(int id = -1) const; +}; +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.cpp new file mode 100644 index 0000000000..ea76423763 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.cpp @@ -0,0 +1,188 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "SmartContract.h" + +#include "GenericAccount.h" + +#include "block/block.h" +#include "block/block-auto.h" +#include "vm/cellslice.h" +#include "vm/cp0.h" +#include "vm/continuation.h" + +#include "td/utils/crypto.h" + +namespace ton { +namespace { +td::int32 get_method_id(td::Slice method_name) { + unsigned crc = td::crc16(method_name); + return (crc & 0xffff) | 0x10000; +} +td::Ref prepare_vm_stack(td::Ref body) { + td::Ref stack_ref{true}; + td::RefInt256 acc_addr{true}; + //CHECK(acc_addr.write().import_bits(account.addr.cbits(), 256)); + vm::Stack& stack = stack_ref.write(); + stack.push_int(td::RefInt256{true, 10000000000}); + stack.push_int(td::RefInt256{true, 10000000000}); + stack.push_cell(vm::CellBuilder().finalize()); + stack.push_cellslice(std::move(body)); + return stack_ref; +} + +td::Ref prepare_vm_c7() { + // TODO: fix initialization of c7 + td::BitArray<256> rand_seed; + rand_seed.as_slice().fill(0); + td::RefInt256 rand_seed_int{true}; + rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false); + auto tuple = vm::make_tuple_ref( + td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea + td::make_refint(0), // actions:Integer + td::make_refint(0), // msgs_sent:Integer + td::make_refint(0), // unixtime:Integer + td::make_refint(0), // block_lt:Integer + td::make_refint(0), // trans_lt:Integer + std::move(rand_seed_int), // rand_seed:Integer + block::CurrencyCollection(1000000000).as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)] + vm::load_cell_slice_ref(vm::CellBuilder().finalize()) // myself:MsgAddressInt + //vm::StackEntry::maybe(td::Ref()) + ); // global_config:(Maybe Cell) ] = SmartContractInfo; + //LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string(); + return vm::make_tuple_ref(std::move(tuple)); +} + +SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref stack, td::Ref c7, + vm::GasLimits gas, bool ignore_chksig) { + auto gas_credit = gas.gas_credit; + vm::init_op_cp0(); + vm::DictionaryBase::get_empty_dictionary(); + + class Logger : public td::LogInterface { + public: + void append(td::CSlice slice) override { + res.append(slice.data(), slice.size()); + } + std::string res; + }; + Logger logger; + vm::VmLog log{&logger, td::LogOptions::plain()}; + + if (GET_VERBOSITY_LEVEL() >= VERBOSITY_NAME(DEBUG)) { + log.log_options.level = 4; + log.log_options.fix_newlines = true; + log.log_mask |= vm::VmLog::DumpStack; + } else { + log.log_options.level = 0; + log.log_mask = 0; + } + + SmartContract::Answer res; + vm::VmState vm{state.code, std::move(stack), gas, 1, state.data, log}; + vm.set_c7(std::move(c7)); + vm.set_chksig_always_succeed(ignore_chksig); + try { + res.code = ~vm.run(); + } catch (...) { + LOG(FATAL) << "catch unhandled exception"; + } + res.new_state = std::move(state); + res.stack = vm.get_stack_ref(); + gas = vm.get_gas_limits(); + res.gas_used = gas.gas_consumed(); + res.accepted = gas.gas_credit == 0; + res.success = (res.accepted && (unsigned)res.code <= 1); + if (GET_VERBOSITY_LEVEL() >= VERBOSITY_NAME(DEBUG)) { + LOG(DEBUG) << "VM log\n" << logger.res; + std::ostringstream os; + res.stack->dump(os); + LOG(DEBUG) << "VM stack:\n" << os.str(); + LOG(DEBUG) << "VM exit code: " << res.code; + LOG(DEBUG) << "VM accepted: " << res.accepted; + LOG(DEBUG) << "VM success: " << res.success; + } + if (res.success) { + res.new_state.data = vm.get_c4(); + res.actions = vm.get_d(5); + } + LOG_IF(ERROR, gas_credit != 0 && (res.accepted && !res.success)) + << "Accepted but failed with code " << res.code << "\n" + << res.gas_used << "\n"; + return res; +} +} // namespace + +td::Ref SmartContract::empty_slice() { + return vm::load_cell_slice_ref(vm::CellBuilder().finalize()); +} + +size_t SmartContract::code_size() const { + return vm::std_boc_serialize(state_.code).ok().size(); +} +size_t SmartContract::data_size() const { + return vm::std_boc_serialize(state_.data).ok().size(); +} + +block::StdAddress SmartContract::get_address(WorkchainId workchain_id) const { + return GenericAccount::get_address(workchain_id, get_init_state()); +} + +td::Ref SmartContract::get_init_state() const { + return GenericAccount::get_init_state(get_state().code, get_state().data); +} + +SmartContract::Answer SmartContract::run_method(Args args) { + if (!args.c7) { + args.c7 = prepare_vm_c7(); + } + if (!args.limits) { + args.limits = vm::GasLimits{(long long)0, (long long)1000000, (long long)10000}; + } + CHECK(args.stack); + CHECK(args.method_id); + args.stack.value().write().push_smallint(args.method_id.unwrap()); + auto res = + run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig); + state_ = res.new_state; + return res; +} + +SmartContract::Answer SmartContract::run_get_method(Args args) const { + if (!args.c7) { + args.c7 = prepare_vm_c7(); + } + if (!args.limits) { + args.limits = vm::GasLimits{1000000}; + } + if (!args.stack) { + args.stack = td::Ref(true); + } + CHECK(args.method_id); + args.stack.value().write().push_smallint(args.method_id.unwrap()); + return run_smartcont(get_state(), args.stack.unwrap(), args.c7.unwrap(), args.limits.unwrap(), args.ignore_chksig); +} + +SmartContract::Answer SmartContract::run_get_method(td::Slice method, Args args) const { + return run_get_method(args.set_method_id(method)); +} + +SmartContract::Answer SmartContract::send_external_message(td::Ref cell, Args args) { + return run_method(args.set_stack(prepare_vm_stack(vm::load_cell_slice_ref(cell))).set_method_id(-1)); +} +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.h b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.h new file mode 100644 index 0000000000..d586436195 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContract.h @@ -0,0 +1,116 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once + +#include "vm/cells.h" +#include "vm/stack.hpp" +#include "vm/continuation.h" + +#include "td/utils/optional.h" +#include "td/utils/crypto.h" + +#include "block/block.h" + +namespace ton { +class SmartContract : public td::CntObject { + static td::Ref empty_slice(); + + public: + struct State { + td::Ref code; + td::Ref data; + }; + + SmartContract(State state) : state_(std::move(state)) { + } + + struct Answer { + SmartContract::State new_state; + bool accepted; + bool success; + td::Ref stack; + td::Ref actions; + td::int32 code; + td::int64 gas_used; + }; + + struct Args { + td::optional method_id; + td::optional limits; + td::optional> c7; + td::optional> stack; + bool ignore_chksig{false}; + + Args() { + } + Args(std::initializer_list stack) + : stack(td::Ref(true, std::vector(std::move(stack)))) { + } + Args&& set_method_id(td::Slice method_name) { + unsigned crc = td::crc16(method_name); + return set_method_id((crc & 0xffff) | 0x10000); + } + Args&& set_method_id(td::int32 method_id) { + this->method_id = method_id; + return std::move(*this); + } + Args&& set_limits(vm::GasLimits limits) { + this->limits = std::move(limits); + return std::move(*this); + } + Args&& set_c7(td::Ref c7) { + this->c7 = std::move(c7); + return std::move(*this); + } + Args&& set_stack(std::vector stack) { + this->stack = td::Ref(true, std::move(stack)); + return std::move(*this); + } + Args&& set_stack(td::Ref stack) { + this->stack = std::move(stack); + return std::move(*this); + } + Args&& set_ignore_chksig(bool ignore_chksig) { + this->ignore_chksig = ignore_chksig; + return std::move(*this); + } + }; + + Answer run_method(Args args = {}); + Answer run_get_method(Args args = {}) const; + Answer run_get_method(td::Slice method, Args args = {}) const; + Answer send_external_message(td::Ref cell, Args args = {}); + + size_t code_size() const; + size_t data_size() const; + static td::Ref create(State state) { + return td::Ref{true, std::move(state)}; + } + + block::StdAddress get_address(WorkchainId workchain_id = basechainId) const; + td::Ref get_init_state() const; + + const State& get_state() const { + return state_; + } + + protected: + State state_; +}; +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.cpp new file mode 100644 index 0000000000..c187131d71 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.cpp @@ -0,0 +1,72 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "SmartContractCode.h" + +#include "vm/boc.h" +#include + +#include "td/utils/base64.h" + +namespace ton { +namespace { +const auto& get_map() { + static auto map = [] { + class Cmp : public std::less<> { + public: + using is_transparent = void; + }; + std::map, Cmp> map; + auto with_tvm_code = [&](auto name, td::Slice code_str) { + map[name] = vm::std_boc_deserialize(td::base64_decode(code_str).move_as_ok()).move_as_ok(); + }; +#include "smartcont/auto/multisig-code.cpp" +#include "smartcont/auto/simple-wallet-ext-code.cpp" +#include "smartcont/auto/simple-wallet-code.cpp" +#include "smartcont/auto/wallet-code.cpp" + return map; + }(); + return map; +} +} // namespace + +td::Result> SmartContractCode::load(td::Slice name) { + auto& map = get_map(); + auto it = map.find(name); + if (it == map.end()) { + return td::Status::Error(PSLICE() << "Can't load td::refsecond; +} +td::Ref SmartContractCode::multisig() { + auto res = load("multisig").move_as_ok(); + return res; +} +td::Ref SmartContractCode::wallet() { + auto res = load("wallet").move_as_ok(); + return res; +} +td::Ref SmartContractCode::simple_wallet() { + auto res = load("simple-wallet").move_as_ok(); + return res; +} +td::Ref SmartContractCode::simple_wallet_ext() { + static auto res = load("simple-wallet-ext").move_as_ok(); + return res; +} +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.h b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.h new file mode 100644 index 0000000000..059215e445 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/SmartContractCode.h @@ -0,0 +1,30 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "vm/cells.h" + +namespace ton { +class SmartContractCode { + public: + static td::Result> load(td::Slice name); + static td::Ref multisig(); + static td::Ref wallet(); + static td::Ref simple_wallet(); + static td::Ref simple_wallet_ext(); +}; +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.cpp new file mode 100644 index 0000000000..2d44d73073 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.cpp @@ -0,0 +1,62 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "TestGiver.h" +#include "GenericAccount.h" + +#include "td/utils/base64.h" + +namespace ton { +const block::StdAddress& TestGiver::address() noexcept { + static block::StdAddress res = + block::StdAddress::parse("kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny").move_as_ok(); + //static block::StdAddress res = + //block::StdAddress::parse("kf9tswzQaryeJ4aAYLy_phLhx4afF1aEvpUVak-2BuA0CmZi").move_as_ok(); + return res; +} + +vm::CellHash TestGiver::get_init_code_hash() noexcept { + return vm::CellHash::from_slice(td::base64_decode("wDkZp0yR4xo+9+BnuAPfGVjBzK6FPzqdv2DwRq3z3KE=").move_as_ok()); + //return vm::CellHash::from_slice(td::base64_decode("YV/IANhoI22HVeatFh6S5LbCHp+5OilARfzW+VQPZgQ=").move_as_ok()); +} + +td::Ref TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message, + const block::StdAddress& dest_address) noexcept { + vm::CellBuilder cb; + GenericAccount::store_int_message(cb, dest_address, gramms); + cb.store_bytes("\0\0\0\0", 4); + vm::CellString::store(cb, message, 35 * 8).ensure(); + auto message_inner = cb.finalize(); + return vm::CellBuilder().store_long(seqno, 32).store_long(1, 8).store_ref(message_inner).finalize(); +} + +td::Result TestGiver::get_seqno() const { + return TRY_VM(get_seqno_or_throw()); +} + +td::Result TestGiver::get_seqno_or_throw() const { + if (state_.data.is_null()) { + return 0; + } + auto seqno = vm::load_cell_slice(state_.data).fetch_ulong(32); + if (seqno == vm::CellSlice::fetch_ulong_eof) { + return td::Status::Error("Failed to parse seq_no"); + } + return static_cast(seqno); +} +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.h b/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.h new file mode 100644 index 0000000000..210b691240 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/TestGiver.h @@ -0,0 +1,39 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once +#include "SmartContract.h" +#include "block/block.h" +#include "vm/cells/CellString.h" +namespace ton { +class TestGiver : public SmartContract { + public: + explicit TestGiver(State state) : ton::SmartContract(std::move(state)) { + } + static constexpr unsigned max_message_size = vm::CellString::max_bytes; + static const block::StdAddress& address() noexcept; + static vm::CellHash get_init_code_hash() noexcept; + static td::Ref make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message, + const block::StdAddress& dest_address) noexcept; + + td::Result get_seqno() const; + + private: + td::Result get_seqno_or_throw() const; +}; +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.cpp new file mode 100644 index 0000000000..1edf59f911 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.cpp @@ -0,0 +1,91 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . +Copyright 2017-2019 Telegram Systems LLP +*/ +#include "TestWallet.h" +#include "GenericAccount.h" + +#include "vm/boc.h" +#include "td/utils/base64.h" + +namespace ton { +td::Ref TestWallet::get_init_state(const td::Ed25519::PublicKey& public_key) noexcept { + auto code = get_init_code(); + auto data = get_init_data(public_key); + return GenericAccount::get_init_state(std::move(code), std::move(data)); +} + +td::Ref TestWallet::get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept { + std::string seq_no(4, 0); + auto signature = + private_key.sign(vm::CellBuilder().store_bytes(seq_no).finalize()->get_hash().as_slice()).move_as_ok(); + return vm::CellBuilder().store_bytes(signature).store_bytes(seq_no).finalize(); +} + +td::Ref TestWallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, + td::int64 gramms, td::Slice message, + const block::StdAddress& dest_address) noexcept { + td::int32 send_mode = 3; + if (gramms == -1) { + gramms = 0; + send_mode += 128; + } + vm::CellBuilder cb; + GenericAccount::store_int_message(cb, dest_address, gramms); + cb.store_bytes("\0\0\0\0", 4); + vm::CellString::store(cb, message, 35 * 8).ensure(); + auto message_inner = cb.finalize(); + auto message_outer = + vm::CellBuilder().store_long(seqno, 32).store_long(send_mode, 8).store_ref(message_inner).finalize(); + auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); + return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); +} + +td::Ref TestWallet::get_init_code() noexcept { + static auto res = [] { + auto serialized_code = td::base64_decode( + "te6ccgEEAQEAAAAAUwAAov8AIN0gggFMl7qXMO1E0NcLH+Ck8mCBAgDXGCDXCx/tRNDTH9P/" + "0VESuvKhIvkBVBBE+RDyovgAAdMfMSDXSpbTB9QC+wDe0aTIyx/L/8ntVA==") + .move_as_ok(); + return vm::std_boc_deserialize(serialized_code).move_as_ok(); + }(); + return res; +} + +vm::CellHash TestWallet::get_init_code_hash() noexcept { + return get_init_code()->get_hash(); +} + +td::Ref TestWallet::get_init_data(const td::Ed25519::PublicKey& public_key) noexcept { + return vm::CellBuilder().store_long(0, 32).store_bytes(public_key.as_octet_string()).finalize(); +} + +td::Result TestWallet::get_seqno() const { + return TRY_VM(get_seqno_or_throw()); +} + +td::Result TestWallet::get_seqno_or_throw() const { + if (state_.data.is_null()) { + return 0; + } + auto seqno = vm::load_cell_slice(state_.data).fetch_ulong(32); + if (seqno == vm::CellSlice::fetch_ulong_eof) { + return td::Status::Error("Failed to parse seq_no"); + } + return static_cast(seqno); +} + +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.h b/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.h new file mode 100644 index 0000000000..161aef58b5 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/TestWallet.h @@ -0,0 +1,48 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once + +#include "smc-envelope/SmartContract.h" +#include "vm/cells.h" +#include "Ed25519.h" +#include "block/block.h" +#include "vm/cells/CellString.h" + +namespace ton { +class TestWallet : public ton::SmartContract { + public: + explicit TestWallet(State state) : ton::SmartContract(std::move(state)) { + } + static constexpr unsigned max_message_size = vm::CellString::max_bytes; + static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key) noexcept; + static td::Ref get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept; + static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, + td::int64 gramms, td::Slice message, + const block::StdAddress& dest_address) noexcept; + + static td::Ref get_init_code() noexcept; + static vm::CellHash get_init_code_hash() noexcept; + static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key) noexcept; + + td::Result get_seqno() const; + + private: + td::Result get_seqno_or_throw() const; +}; +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.cpp b/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.cpp new file mode 100644 index 0000000000..61958ed959 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.cpp @@ -0,0 +1,100 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "Wallet.h" +#include "GenericAccount.h" + +#include "vm/boc.h" +#include "vm/cells/CellString.h" +#include "td/utils/base64.h" + +#include + +namespace ton { +td::Ref Wallet::get_init_state(const td::Ed25519::PublicKey& public_key) noexcept { + auto code = get_init_code(); + auto data = get_init_data(public_key); + return GenericAccount::get_init_state(std::move(code), std::move(data)); +} + +td::Ref Wallet::get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept { + td::uint32 seqno = 0; + td::uint32 valid_until = std::numeric_limits::max(); + auto signature = + private_key + .sign(vm::CellBuilder().store_long(seqno, 32).store_long(valid_until, 32).finalize()->get_hash().as_slice()) + .move_as_ok(); + return vm::CellBuilder().store_bytes(signature).store_long(seqno, 32).store_long(valid_until, 32).finalize(); +} + +td::Ref Wallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, + td::uint32 valid_until, td::int64 gramms, td::Slice message, + const block::StdAddress& dest_address) noexcept { + td::int32 send_mode = 3; + if (gramms == -1) { + gramms = 0; + send_mode += 128; + } + vm::CellBuilder cb; + GenericAccount::store_int_message(cb, dest_address, gramms); + cb.store_bytes("\0\0\0\0", 4); + vm::CellString::store(cb, message, 35 * 8).ensure(); + auto message_inner = cb.finalize(); + + auto message_outer = vm::CellBuilder() + .store_long(seqno, 32) + .store_long(valid_until, 32) + .store_long(send_mode, 8) + .store_ref(message_inner) + .finalize(); + auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok(); + return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize(); +} + +td::Ref Wallet::get_init_code() noexcept { + static auto res = [] { + auto serialized_code = td::base64_decode( + "te6ccgEEAQEAAAAAVwAAqv8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x8B+CO78mPtRNDTH9P/" + "0VExuvKhA/kBVBBC+RDyovgAApMg10qW0wfUAvsA6NGkyMsfy//J7VQ=") + .move_as_ok(); + return vm::std_boc_deserialize(serialized_code).move_as_ok(); + }(); + return res; +} + +vm::CellHash Wallet::get_init_code_hash() noexcept { + return get_init_code()->get_hash(); +} + +td::Ref Wallet::get_init_data(const td::Ed25519::PublicKey& public_key) noexcept { + return vm::CellBuilder().store_long(0, 32).store_bytes(public_key.as_octet_string()).finalize(); +} + +td::Result Wallet::get_seqno() const { + return TRY_VM(get_seqno_or_throw()); +} + +td::Result Wallet::get_seqno_or_throw() const { + if (state_.data.is_null()) { + return 0; + } + //FIXME use get method + return static_cast(vm::load_cell_slice(state_.data).fetch_ulong(32)); +} + +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.h b/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.h new file mode 100644 index 0000000000..7cd33c81d1 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/smc-envelope/Wallet.h @@ -0,0 +1,48 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once + +#include "smc-envelope/SmartContract.h" +#include "vm/cells.h" +#include "Ed25519.h" +#include "block/block.h" +#include "vm/cells/CellString.h" + +namespace ton { +class Wallet : ton::SmartContract { + public: + explicit Wallet(State state) : ton::SmartContract(std::move(state)) { + } + static constexpr unsigned max_message_size = vm::CellString::max_bytes; + static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key) noexcept; + static td::Ref get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept; + static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno, + td::uint32 valid_until, td::int64 gramms, td::Slice message, + const block::StdAddress& dest_address) noexcept; + + static td::Ref get_init_code() noexcept; + static vm::CellHash get_init_code_hash() noexcept; + static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key) noexcept; + + td::Result get_seqno() const; + + private: + td::Result get_seqno_or_throw() const; +}; +} // namespace ton diff --git a/submodules/ton/tonlib-src/crypto/test/Ed25519.cpp b/submodules/ton/tonlib-src/crypto/test/Ed25519.cpp index 4d943abbfd..f4509791c4 100644 --- a/submodules/ton/tonlib-src/crypto/test/Ed25519.cpp +++ b/submodules/ton/tonlib-src/crypto/test/Ed25519.cpp @@ -21,8 +21,12 @@ #include "td/utils/misc.h" #include "td/utils/Slice.h" #include "td/utils/tests.h" +#include "td/utils/JsonBuilder.h" + +#include "wycheproof.h" #include +#include unsigned char fixed_privkey[32] = "abacabadabacabaeabacabadabacaba"; unsigned char fixed_pubkey[32] = {0x6f, 0x9e, 0x5b, 0xde, 0xce, 0x87, 0x21, 0xeb, 0x57, 0x37, 0xfb, @@ -142,3 +146,74 @@ TEST(Crypto, ed25519) { assert(!std::memcmp(secret12, secret21, 32)); */ } + +TEST(Crypto, wycheproof) { + std::vector> bad_tests; + auto json_str = wycheproof_ed25519(); + auto value = td::json_decode(json_str).move_as_ok(); + auto &root = value.get_object(); + auto test_groups_o = get_json_object_field(root, "testGroups", td::JsonValue::Type::Array, false).move_as_ok(); + auto &test_groups = test_groups_o.get_array(); + auto from_hexc = [](char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + return c - 'a' + 10; + }; + auto from_hex = [&](td::Slice s) { + CHECK(s.size() % 2 == 0); + std::string res(s.size() / 2, 0); + for (size_t i = 0; i < s.size(); i += 2) { + res[i / 2] = char(from_hexc(s[i]) * 16 + from_hexc(s[i + 1])); + } + return res; + }; + for (auto &test_o : test_groups) { + auto &test = test_o.get_object(); + auto key_o = get_json_object_field(test, "key", td::JsonValue::Type::Object, false).move_as_ok(); + auto sk_str = td::get_json_object_string_field(key_o.get_object(), "sk", false).move_as_ok(); + auto pk_str = td::get_json_object_string_field(key_o.get_object(), "pk", false).move_as_ok(); + auto pk = td::Ed25519::PublicKey(td::SecureString(from_hex(pk_str))); + auto sk = td::Ed25519::PrivateKey(td::SecureString(from_hex(sk_str))); + CHECK(sk.get_public_key().move_as_ok().as_octet_string().as_slice() == pk.as_octet_string().as_slice()); + + //auto key = + //td::Ed25519::PrivateKey::from_pem( + //td::SecureString(td::get_json_object_string_field(test, "keyPem", false).move_as_ok()), td::SecureString()) + //.move_as_ok(); + + auto tests_o = get_json_object_field(test, "tests", td::JsonValue::Type::Array, false).move_as_ok(); + auto &tests = tests_o.get_array(); + for (auto &test_o : tests) { + auto &test = test_o.get_object(); + auto id = td::get_json_object_string_field(test, "tcId", false).move_as_ok(); + auto comment = td::get_json_object_string_field(test, "comment", false).move_as_ok(); + auto sig = from_hex(td::get_json_object_string_field(test, "sig", false).move_as_ok()); + auto msg = from_hex(td::get_json_object_string_field(test, "msg", false).move_as_ok()); + auto result = td::get_json_object_string_field(test, "result", false).move_as_ok(); + auto has_result = pk.verify_signature(msg, sig).is_ok() ? "valid" : "invalid"; + if (result != has_result) { + bad_tests.push_back({id, comment}); + } + } + } + if (bad_tests.empty()) { + return; + } + LOG(ERROR) << "FAILED: " << td::format::as_array(bad_tests); +} + +TEST(Crypto, almost_zero) { + td::SecureString pub(32); + td::SecureString sig(64); + td::SecureString msg(1); + + pub.as_mutable_slice()[31] = (char)128; + for (td::int32 j = 0; j < 256; j++) { + msg.as_mutable_slice()[0] = (char)j; + if (td::Ed25519::PublicKey(pub.copy()).verify_signature(msg, sig).is_ok()) { + LOG(ERROR) << "FAILED: " << j; + break; + } + } +} diff --git a/submodules/ton/tonlib-src/crypto/test/fift.cpp b/submodules/ton/tonlib-src/crypto/test/fift.cpp index 59b912c34e..694dc7a83c 100644 --- a/submodules/ton/tonlib-src/crypto/test/fift.cpp +++ b/submodules/ton/tonlib-src/crypto/test/fift.cpp @@ -90,3 +90,23 @@ TEST(Fift, test) { TEST(Fift, bug_div) { run_fift("bug_div.fif"); } + +TEST(Fift, bug_ufits) { + run_fift("bug_ufits.fif"); +} + +TEST(Fift, test_dict) { + run_fift("testdict.fif"); +} + +TEST(Fift, test_fixed) { + run_fift("fixed.fif"); +} + +TEST(Fift, test_sort) { + run_fift("sort.fif"); +} + +TEST(Fift, test_sort2) { + run_fift("sort2.fif"); +} diff --git a/submodules/ton/tonlib-src/crypto/test/fift/bug_ufits.fif b/submodules/ton/tonlib-src/crypto/test/fift/bug_ufits.fif new file mode 100644 index 0000000000..6c607ea220 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/test/fift/bug_ufits.fif @@ -0,0 +1 @@ +100000000000000000 dup =: amount 56 ufits . amount 56 ufits . diff --git a/submodules/ton/tonlib-src/crypto/test/fift/testvm2.fif b/submodules/ton/tonlib-src/crypto/test/fift/testvm2.fif index 523c6a7d27..7e91a87701 100644 --- a/submodules/ton/tonlib-src/crypto/test/fift/testvm2.fif +++ b/submodules/ton/tonlib-src/crypto/test/fift/testvm2.fif @@ -17,6 +17,6 @@ x{917720ED50D8} runvmcode drop .s 20 x{9720C11401C20CB0D8} runvmcode drop .s x{E3C03077F001A4} x{3020A8} |_ runvmdict drop .s x{71B0E30277F001A4} x{20A8} |_ runvmdict .s -17 x{30ED44D0D71131A020C8CB3FC9ED54} runvm .s +17 0 x{30ED44D0D71131A020C8CB3FC9ED54} runvm .s 100 19 7 x{92A9069620C004F2F571F321A0} runvmcode .s 19 0 x{92A9069620C004F2F571F321A0} runvmcode .s diff --git a/submodules/ton/tonlib-src/crypto/test/test-db.cpp b/submodules/ton/tonlib-src/crypto/test/test-db.cpp index 28f05ff8e5..148a185494 100644 --- a/submodules/ton/tonlib-src/crypto/test/test-db.cpp +++ b/submodules/ton/tonlib-src/crypto/test/test-db.cpp @@ -51,34 +51,6 @@ #include -struct Step { - std::function func; - td::uint32 weight; -}; -class RandomSteps { - public: - RandomSteps(std::vector steps) : steps_(std::move(steps)) { - for (auto &step : steps_) { - steps_sum_ += step.weight; - } - } - template - void step(Random &rnd) { - auto w = rnd() % steps_sum_; - for (auto &step : steps_) { - if (w < step.weight) { - step.func(); - break; - } - w -= step.weight; - } - } - - private: - std::vector steps_; - td::int32 steps_sum_ = 0; -}; - namespace vm { std::vector do_get_serialization_modes() { @@ -879,7 +851,7 @@ TEST(TonDb, DynamicBoc2) { VLOG(boc) << " OK"; }; - RandomSteps steps({{new_root, 10}, {delete_root, 9}, {commit, 2}, {reset, 1}}); + td::RandomSteps steps({{new_root, 10}, {delete_root, 9}, {commit, 2}, {reset, 1}}); while (first_root_id != total_roots) { VLOG(boc) << first_root_id << " " << last_root_id << " " << kv->count("").ok(); steps.step(rnd); @@ -1732,7 +1704,7 @@ TEST(TonDb, CompactArray) { fast_array = vm::FastCompactArray(size); }; - RandomSteps steps({{reset_array, 1}, {set_value, 1000}, {validate, 10}, {validate_full, 2}, {flush_to_db, 1}}); + td::RandomSteps steps({{reset_array, 1}, {set_value, 1000}, {validate, 10}, {validate_full, 2}, {flush_to_db, 1}}); for (size_t t = 0; t < 100000; t++) { if (t % 10000 == 0) { LOG(ERROR) << t; diff --git a/submodules/ton/tonlib-src/crypto/test/test-smartcont.cpp b/submodules/ton/tonlib-src/crypto/test/test-smartcont.cpp new file mode 100644 index 0000000000..f9dd86522f --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/test/test-smartcont.cpp @@ -0,0 +1,524 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "vm/dict.h" +#include "common/bigint.hpp" + +#include "Ed25519.h" + +#include "block/block.h" + +#include "fift/Fift.h" +#include "fift/words.h" +#include "fift/utils.h" + +#include "smc-envelope/GenericAccount.h" +#include "smc-envelope/MultisigWallet.h" +#include "smc-envelope/SmartContract.h" +#include "smc-envelope/SmartContractCode.h" +#include "smc-envelope/TestGiver.h" +#include "smc-envelope/TestWallet.h" +#include "smc-envelope/Wallet.h" + +#include "td/utils/base64.h" +#include "td/utils/crypto.h" +#include "td/utils/Random.h" +#include "td/utils/tests.h" +#include "td/utils/ScopeGuard.h" +#include "td/utils/StringBuilder.h" +#include "td/utils/Timer.h" +#include "td/utils/PathView.h" +#include "td/utils/filesystem.h" +#include "td/utils/port/path.h" + +#include +#include +#include + +std::string current_dir() { + return td::PathView(td::realpath(__FILE__).move_as_ok()).parent_dir().str(); +} + +std::string load_source(std::string name) { + return td::read_file_str(current_dir() + "../../crypto/" + name).move_as_ok(); +} + +td::Ref get_test_wallet_source() { + std::string code = R"ABCD( +SETCP0 DUP IFNOTRET // return if recv_internal +DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method + DROP c4 PUSHCTR CTOS 32 PLDU // cnt +}> +INC 32 THROWIF // fail unless recv_external +512 INT LDSLICEX DUP 32 PLDU // sign cs cnt +c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk +s1 s2 XCPU // sign cs cnt pubk cnt' cnt +EQUAL 33 THROWIFNOT // ( seqno mismatch? ) +s2 PUSH HASHSU // sign cs cnt pubk hash +s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk +CHKSIGNU // pubk cs cnt ? +34 THROWIFNOT // signature mismatch +ACCEPT +SWAP 32 LDU NIP +DUP SREFS IF:<{ + // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance + 8 LDU LDREF // pubk cnt mode msg cs + s0 s2 XCHG SENDRAWMSG // pubk cnt cs ; ( message sent ) +}> +ENDS +INC NEWC 32 STU 256 STU ENDC c4 POPCTR +)ABCD"; + return fift::compile_asm(code).move_as_ok(); +} + +td::Ref get_wallet_source() { + std::string code = R"ABCD( +SETCP0 DUP IFNOTRET // return if recv_internal + DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method + DROP c4 PUSHCTR CTOS 32 PLDU // cnt + }> + INC 32 THROWIF // fail unless recv_external + 9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU // signature in_msg msg_seqno valid_until cs + SWAP NOW LEQ 35 THROWIF // signature in_msg msg_seqno cs + c4 PUSH CTOS 32 LDU 256 LDU ENDS // signature in_msg msg_seqno cs stored_seqno public_key + s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno + EQUAL 33 THROWIFNOT // signature in_msg public_key cs stored_seqno + s0 s3 XCHG HASHSU // signature stored_seqno public_key cs hash + s0 s4 s2 XC2PU CHKSIGNU 34 THROWIFNOT // cs stored_seqno public_key + ACCEPT + s0 s2 XCHG // public_key stored_seqno cs + WHILE:<{ + DUP SREFS // public_key stored_seqno cs _40 + }>DO<{ // public_key stored_seqno cs + // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance + 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno cs _45 mode + SENDRAWMSG // public_key stored_seqno cs + }> + ENDS INC // public_key seqno' + NEWC 32 STU 256 STU ENDC c4 POP +)ABCD"; + return fift::compile_asm(code).move_as_ok(); +} + +TEST(Tonlib, TestWallet) { + LOG(ERROR) << td::base64_encode(std_boc_serialize(get_test_wallet_source()).move_as_ok()); + CHECK(get_test_wallet_source()->get_hash() == ton::TestWallet::get_init_code()->get_hash()); + auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet.fif"), {"aba", "0"}).move_as_ok(); + + auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; + auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data; + auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data; + + td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; + auto pub_key = priv_key.get_public_key().move_as_ok(); + auto init_state = ton::TestWallet::get_init_state(pub_key); + auto init_message = ton::TestWallet::get_init_message(priv_key); + auto address = ton::GenericAccount::get_address(0, init_state); + + CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); + + td::Ref res = ton::GenericAccount::create_ext_message(address, init_state, init_message); + + LOG(ERROR) << "-------"; + vm::load_cell_slice(res).print_rec(std::cerr); + LOG(ERROR) << "-------"; + vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); + CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); + + fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet.fif")).ensure(); + auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); + fift_output = fift::mem_run_fift(std::move(fift_output.source_lookup), + {"aba", "new-wallet", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "123", + "321", "-C", "TEST"}) + .move_as_ok(); + auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; + auto gift_message = ton::GenericAccount::create_ext_message( + address, {}, ton::TestWallet::make_a_gift_message(priv_key, 123, 321000000000ll, "TEST", dest)); + LOG(ERROR) << "-------"; + vm::load_cell_slice(gift_message).print_rec(std::cerr); + LOG(ERROR) << "-------"; + vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); + CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); +} + +td::Ref get_wallet_source_fc() { + return fift::compile_asm(load_source("smartcont/wallet-code.fif"), "", false).move_as_ok(); +} + +TEST(Tonlib, Wallet) { + LOG(ERROR) << td::base64_encode(std_boc_serialize(get_wallet_source()).move_as_ok()); + CHECK(get_wallet_source()->get_hash() == ton::Wallet::get_init_code()->get_hash()); + + auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet-v2.fif"), {"aba", "0"}).move_as_ok(); + + auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; + auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data; + auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data; + + td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; + auto pub_key = priv_key.get_public_key().move_as_ok(); + auto init_state = ton::Wallet::get_init_state(pub_key); + auto init_message = ton::Wallet::get_init_message(priv_key); + auto address = ton::GenericAccount::get_address(0, init_state); + + CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); + + td::Ref res = ton::GenericAccount::create_ext_message(address, init_state, init_message); + + LOG(ERROR) << "-------"; + vm::load_cell_slice(res).print_rec(std::cerr); + LOG(ERROR) << "-------"; + vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); + CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); + + fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet-v2.fif")).ensure(); + class ZeroOsTime : public fift::OsTime { + public: + td::uint32 now() override { + return 0; + } + }; + fift_output.source_lookup.set_os_time(std::make_unique()); + auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); + fift_output = + fift::mem_run_fift(std::move(fift_output.source_lookup), + {"aba", "new-wallet", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "123", "321"}) + .move_as_ok(); + auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; + auto gift_message = ton::GenericAccount::create_ext_message( + address, {}, ton::Wallet::make_a_gift_message(priv_key, 123, 60, 321000000000ll, "TESTv2", dest)); + LOG(ERROR) << "-------"; + vm::load_cell_slice(gift_message).print_rec(std::cerr); + LOG(ERROR) << "-------"; + vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); + CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); +} + +TEST(Tonlib, TestGiver) { + auto address = + block::StdAddress::parse("-1:60c04141c6a7b96d68615e7a91d265ad0f3a9a922e9ae9c901d4fa83f5d3c0d0").move_as_ok(); + LOG(ERROR) << address.bounceable; + auto fift_output = fift::mem_run_fift(load_source("smartcont/testgiver.fif"), + {"aba", address.rserialize(), "0", "6.666", "wallet-query"}) + .move_as_ok(); + LOG(ERROR) << fift_output.output; + + auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; + + auto res = ton::GenericAccount::create_ext_message( + ton::TestGiver::address(), {}, + ton::TestGiver::make_a_gift_message(0, 1000000000ll * 6666 / 1000, "GIFT", address)); + vm::CellSlice(vm::NoVm(), res).print_rec(std::cerr); + CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == res->get_hash()); +} + +class SimpleWallet : public ton::SmartContract { + public: + SimpleWallet(State state) : SmartContract(std::move(state)) { + } + + const State& get_state() const { + return state_; + } + SimpleWallet* make_copy() const override { + return new SimpleWallet{state_}; + } + + static td::Ref create_empty() { + return td::Ref(true, State{ton::SmartContractCode::simple_wallet_ext(), {}}); + } + static td::Ref create(td::Ref data) { + return td::Ref(true, State{ton::SmartContractCode::simple_wallet_ext(), std::move(data)}); + } + static td::Ref create_fast(td::Ref data) { + return td::Ref(true, State{ton::SmartContractCode::simple_wallet(), std::move(data)}); + } + + td::int32 seqno() const { + auto res = run_get_method("seqno"); + return res.stack.write().pop_smallint_range(1000000000); + } + + td::Ref create_init_state(td::Slice public_key) const { + td::RefInt256 pk{true}; + pk.write().import_bytes(public_key.ubegin(), public_key.size(), false); + auto res = run_get_method("create_init_state", {pk}); + return res.stack.write().pop_cell(); + } + + td::Ref prepare_send_message(td::Ref msg, td::int8 mode = 3) const { + auto res = run_get_method("prepare_send_message", {td::make_refint(mode), msg}); + return res.stack.write().pop_cell(); + } + + static td::Ref sign_message(vm::Ref body, const td::Ed25519::PrivateKey& pk) { + auto signature = pk.sign(body->get_hash().as_slice()).move_as_ok(); + return vm::CellBuilder().store_bytes(signature.as_slice()).append_cellslice(vm::load_cell_slice(body)).finalize(); + } +}; + +TEST(Smartcon, Simple) { + auto private_key = td::Ed25519::generate_private_key().move_as_ok(); + auto public_key = private_key.get_public_key().move_as_ok().as_octet_string(); + + auto w_lib = SimpleWallet::create_empty(); + auto init_data = w_lib->create_init_state(public_key); + + auto w = SimpleWallet::create(init_data); + LOG(ERROR) << w->code_size(); + auto fw = SimpleWallet::create_fast(init_data); + LOG(ERROR) << fw->code_size(); + LOG(ERROR) << w->seqno(); + + for (int i = 0; i < 20; i++) { + auto msg = w->sign_message(w->prepare_send_message(vm::CellBuilder().finalize()), private_key); + w.write().send_external_message(msg); + fw.write().send_external_message(msg); + } + ASSERT_EQ(20, w->seqno()); + CHECK(w->get_state().data->get_hash() == fw->get_state().data->get_hash()); +} + +namespace std { // ouch +bool operator<(const ton::MultisigWallet::Mask& a, const ton::MultisigWallet::Mask& b) { + for (size_t i = 0; i < a.size(); i++) { + if (a[i] != b[i]) { + return a[i] < b[i]; + } + } + return false; +} +} // namespace std + +TEST(Smartcon, Multisig) { + auto ms_lib = ton::MultisigWallet::create(); + + int n = 100; + int k = 99; + std::vector keys; + for (int i = 0; i < n; i++) { + keys.push_back(td::Ed25519::generate_private_key().move_as_ok()); + } + auto init_state = ms_lib->create_init_data( + td::transform(keys, [](auto& key) { return key.get_public_key().ok().as_octet_string(); }), k); + auto ms = ton::MultisigWallet::create(init_state); + + td::uint64 query_id = 123; + ton::MultisigWallet::QueryBuilder qb(query_id, vm::CellBuilder().finalize()); + // first empty query (init) + CHECK(ms.write().send_external_message(vm::CellBuilder().finalize()).code == 0); + // first empty query + CHECK(ms.write().send_external_message(vm::CellBuilder().finalize()).code > 0); + + for (int i = 0; i < 10; i++) { + auto query = qb.create(i, keys[i]); + auto ans = ms.write().send_external_message(query); + LOG(INFO) << "CODE: " << ans.code; + LOG(INFO) << "GAS: " << ans.gas_used; + } + for (int i = 0; i + 1 < 50; i++) { + qb.sign(i, keys[i]); + } + auto query = qb.create(49, keys[49]); + + CHECK(ms->get_n_k() == std::make_pair(n, k)); + auto ans = ms.write().send_external_message(query); + LOG(INFO) << "CODE: " << ans.code; + LOG(INFO) << "GAS: " << ans.gas_used; + CHECK(ans.success); + ASSERT_EQ(0, ms->processed(query_id)); + CHECK(ms.write().send_external_message(query).code > 0); + ASSERT_EQ(0, ms->processed(query_id)); + + { + ton::MultisigWallet::QueryBuilder qb(query_id, vm::CellBuilder().finalize()); + for (int i = 50; i + 1 < 100; i++) { + qb.sign(i, keys[i]); + } + query = qb.create(99, keys[99]); + } + + ans = ms.write().send_external_message(query); + LOG(INFO) << "CODE: " << ans.code; + LOG(INFO) << "GAS: " << ans.gas_used; + ASSERT_EQ(-1, ms->processed(query_id)); +} + +TEST(Smartcont, MultisigStress) { + int n = 10; + int k = 5; + + std::vector keys; + for (int i = 0; i < n; i++) { + keys.push_back(td::Ed25519::generate_private_key().move_as_ok()); + } + auto public_keys = td::transform(keys, [](auto& key) { return key.get_public_key().ok().as_octet_string(); }); + auto ms_lib = ton::MultisigWallet::create(); + auto init_state_old = + ms_lib->create_init_data_fast(td::transform(public_keys, [](auto& key) { return key.copy(); }), k); + auto init_state = ms_lib->create_init_data(td::transform(public_keys, [](auto& key) { return key.copy(); }), k); + CHECK(init_state_old->get_hash() == init_state->get_hash()); + auto ms = ton::MultisigWallet::create(init_state); + CHECK(ms->get_public_keys() == public_keys); + + td::int32 now = 0; + td::int32 qid = 1; + using Mask = std::bitset<128>; + struct Query { + td::int64 id; + td::Ref message; + Mask signed_mask; + }; + + std::vector queries; + int max_queries = 300; + + td::Random::Xorshift128plus rnd(123); + + auto new_query = [&] { + if (qid > max_queries) { + return; + } + Query query; + query.id = (static_cast(now) << 32) | qid++; + query.message = vm::CellBuilder().store_bytes(td::rand_string('a', 'z', rnd.fast(0, 100))).finalize(); + queries.push_back(std::move(query)); + }; + + auto verify = [&] { + auto messages = ms->get_unsigned_messaged(); + std::set> s; + std::set> t; + + for (auto& m : messages) { + auto x = std::make_tuple(m.query_id, m.signed_by, m.message->get_hash().as_slice().str()); + s.insert(std::move(x)); + } + + for (auto& q : queries) { + if (q.signed_mask.none()) { + continue; + } + t.insert(std::make_tuple(q.id, q.signed_mask, q.message->get_hash().as_slice().str())); + } + ASSERT_EQ(t.size(), s.size()); + CHECK(s == t); + }; + + auto sign_query = [&](Query& query, Mask mask) { + auto qb = ton::MultisigWallet::QueryBuilder(query.id, query.message); + int first_i = -1; + for (int i = 0; i < (int)mask.size(); i++) { + if (mask.test(i)) { + if (first_i == -1) { + first_i = i; + } else { + qb.sign(i, keys[i]); + } + } + } + return qb.create(first_i, keys[first_i]); + }; + + auto send_signature = [&](td::Ref query) { + auto ans = ms.write().send_external_message(query); + LOG(ERROR) << "GAS: " << ans.gas_used; + return ans.code == 0; + }; + + auto is_ready = [&](Query& query) { return ms->processed(query.id) == -1; }; + + auto gen_query = [&](Query& query) { + auto x = rnd.fast(1, n); + Mask mask; + for (int t = 0; t < x; t++) { + mask.set(rnd() % n); + } + + auto signature = sign_query(query, mask); + return std::make_pair(signature, mask); + }; + + auto rand_sign = [&] { + if (queries.empty()) { + return; + } + + size_t query_i = rnd() % queries.size(); + auto& query = queries[query_i]; + + Mask mask; + td::Ref signature; + std::tie(signature, mask) = gen_query(query); + if (false && rnd() % 6 == 0) { + Mask mask2; + td::Ref signature2; + std::tie(signature2, mask2) = gen_query(query); + for (int i = 0; i < (int)keys.size(); i++) { + if (mask[i]) { + signature = ms->merge_queries(std::move(signature), std::move(signature2)); + break; + } + if (mask2[i]) { + signature = ms->merge_queries(std::move(signature2), std::move(signature)); + break; + } + } + //signature = ms->merge_queries(std::move(signature), std::move(signature2)); + mask |= mask2; + } + + int got_cnt; + Mask got_cnt_bits; + std::tie(got_cnt, got_cnt_bits) = ms->check_query_signatures(signature); + CHECK(mask == got_cnt_bits); + + bool expect_ok = true; + { + auto new_mask = mask & ~query.signed_mask; + expect_ok &= new_mask.any(); + for (size_t i = 0; i < mask.size(); i++) { + if (mask[i]) { + expect_ok &= new_mask[i]; + break; + } + } + } + + ASSERT_EQ(expect_ok, send_signature(std::move(signature))); + if (expect_ok) { + query.signed_mask |= mask; + } + auto expect_is_ready = query.signed_mask.count() >= (size_t)k; + auto state = ms->get_query_state(query.id); + ASSERT_EQ(expect_is_ready, (state.state == ton::MultisigWallet::QueryState::Sent)); + CHECK(expect_is_ready || state.mask == query.signed_mask); + ASSERT_EQ(expect_is_ready, is_ready(query)); + if (expect_is_ready) { + queries.erase(queries.begin() + query_i); + } + verify(); + }; + td::RandomSteps steps({{rand_sign, 2}, {new_query, 1}}); + while (!queries.empty() || qid <= max_queries) { + steps.step(rnd); + //LOG(ERROR) << ms->data_size(); + } + LOG(INFO) << "Final code size: " << ms->code_size(); + LOG(INFO) << "Final data size: " << ms->data_size(); +} diff --git a/submodules/ton/tonlib-src/crypto/test/wycheproof.h b/submodules/ton/tonlib-src/crypto/test/wycheproof.h new file mode 100644 index 0000000000..e94559da90 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/test/wycheproof.h @@ -0,0 +1,1160 @@ +#pragma once + +#include + +std::string wycheproof_ed25519() { + return + R"abcd({ + "algorithm" : "EDDSA", + "generatorVersion" : "0.4.12", + "notes" : { + "SignatureMalleability" : "EdDSA signatures are non-malleable, if implemented accordingly. Failing to check the range of S allows to modify signatures. See RFC 8032, Section 5.2.7 and Section 8.4." + }, + "numberOfTests" : 111, + "header" : [], + "testGroups" : [ + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", + "sk" : "add4bb8103785baf9ac534258e8aaf65f5f1adb5ef5f3df19bb80ab989c4d64b", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b65700321007d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAfU0Of2FTpptiQrUiq77mhf2kQg+INLEIw72uNp71Sfo=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 1, + "comment" : "", + "msg" : "", + "sig" : "d4fbdb52bfa726b44d1786a8c0d171c3e62ca83c9e5bbe63de0bb2483f8fd6cc1429ab72cafc41ab56af02ff8fcc43b99bfe4c7ae940f60f38ebaa9d311c4007", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 2, + "comment" : "", + "msg" : "78", + "sig" : "d80737358ede548acb173ef7e0399f83392fe8125b2ce877de7975d8b726ef5b1e76632280ee38afad12125ea44b961bf92f1178c9fa819d020869975bcbe109", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 3, + "comment" : "", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 4, + "comment" : "", + "msg" : "48656c6c6f", + "sig" : "1c1ad976cbaae3b31dee07971cf92c928ce2091a85f5899f5e11ecec90fc9f8e93df18c5037ec9b29c07195ad284e63d548cd0a6fe358cc775bd6c1608d2c905", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 5, + "comment" : "", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bf0cf5b3a289976458a1be6277a5055545253b45b07dcc1abd96c8b989c00f301", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 6, + "comment" : "", + "msg" : "000000000000000000000000", + "sig" : "d46543bfb892f84ec124dcdfc847034c19363bf3fc2fa89b1267833a14856e52e60736918783f950b6f1dd8d40dc343247cd43ce054c2d68ef974f7ed0f3c60f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 7, + "comment" : "", + "msg" : "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", + "sig" : "879350045543bc14ed2c08939b68c30d22251d83e018cacbaf0c9d7a48db577e80bdf76ce99e5926762bc13b7b3483260a5ef63d07e34b58eb9c14621ac92f00", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 8, + "comment" : "", + "msg" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60", + "sig" : "7bdc3f9919a05f1d5db4a3ada896094f6871c1f37afc75db82ec3147d84d6f237b7e5ecc26b59cfea0c7eaf1052dc427b0f724615be9c3d3e01356c65b9b5109", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 9, + "comment" : "", + "msg" : "ffffffffffffffffffffffffffffffff", + "sig" : "5dbd7360e55aa38e855d6ad48c34bd35b7871628508906861a7c4776765ed7d1e13d910faabd689ec8618b78295c8ab8f0e19c8b4b43eb8685778499e943ae04", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 10, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 11, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 12, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "0000000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 13, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "0000000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 14, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "0000000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 15, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 16, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "01000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 17, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "0100000000000000000000000000000000000000000000000000000000000000ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 18, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "0100000000000000000000000000000000000000000000000000000000000000edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 19, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "0100000000000000000000000000000000000000000000000000000000000000edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 20, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 21, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edd3f55c1a631258d69cf7a2def9de14000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 22, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010ecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 23, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 24, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 25, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 26, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f0100000000000000000000000000000000000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 27, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fecd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 28, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 29, + "comment" : "special values for r and s", + "msg" : "3f", + "sig" : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 30, + "comment" : "empty signature", + "msg" : "54657374", + "sig" : "", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 31, + "comment" : "s missing", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 32, + "comment" : "signature too short", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 33, + "comment" : "signature too long", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d2020", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 34, + "comment" : "include pk in signature", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 35, + "comment" : "prepending 0 byte to signature", + "msg" : "54657374", + "sig" : "007c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 36, + "comment" : "prepending 0 byte to s", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0007a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 37, + "comment" : "appending 0 byte to signature", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d00", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 38, + "comment" : "removing 0 byte from signature", + "msg" : "546573743137", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b3", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 39, + "comment" : "removing 0 byte from signature", + "msg" : "54657374313236", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab09155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 40, + "comment" : "removing leading 0 byte from signature", + "msg" : "546573743530", + "sig" : "38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 41, + "comment" : "dropping byte from signature", + "msg" : "54657374333437", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab09155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 42, + "comment" : "modified bit 0 in R", + "msg" : "313233343030", + "sig" : "647c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b1d125e5538f38afbcc1c84e489521083041d24bc6240767029da063271a1ff0c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 43, + "comment" : "modified bit 1 in R", + "msg" : "313233343030", + "sig" : "677c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bc108ca4b87a49c9ed2cf383aecad8f54a962b2899da891e12004d7993a627e01", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 44, + "comment" : "modified bit 2 in R", + "msg" : "313233343030", + "sig" : "617c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b9ce23fc6213ed5b87912e9bbf92f5e2c780eae26d15c50a112d1e97d2ea33c06", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 45, + "comment" : "modified bit 7 in R", + "msg" : "313233343030", + "sig" : "e57c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bbb3eb51cd98dddb235a5f46f2bded6af184a58d09cce928bda43f41d69118a03", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 46, + "comment" : "modified bit 8 in R", + "msg" : "313233343030", + "sig" : "657d1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcd237dda9a116501f67a5705a854b9adc304f34720803a91b324f2c13e0f5a09", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 47, + "comment" : "modified bit 16 in R", + "msg" : "313233343030", + "sig" : "657c1592402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b6b167bbdc0d881cc04d28905552c1876f3709851abc5007376940cc8a435c300", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 48, + "comment" : "modified bit 31 in R", + "msg" : "313233343030", + "sig" : "657c1412402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7fd2ac7da14afffcceeb13f2a0d6b887941cb1a5eb57a52f3cb131a16cce7b0e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 49, + "comment" : "modified bit 32 in R", + "msg" : "313233343030", + "sig" : "657c1492412ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2b7373ba13ebbef99cd2a8ead55ce735c987d85a35320925a8e871702dc7c5c40d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 50, + "comment" : "modified bit 63 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab54e03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bd35bd331c03f0855504ca1cab87b83c36a028425a3cf007ede4f4254c261cb00", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 51, + "comment" : "modified bit 64 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce02e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bcb35101f73cf467deac8c1a03b6c3dc35af544132734b7e57ab20c89b2e4750d", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 52, + "comment" : "modified bit 97 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f2384d051b9cf3570f1207fc78c1bcc98c281c2bb58d2e8878290bff8d3355fdd4ea381924ee578752354eb6dee678ab4011c301", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 53, + "comment" : "modified bit 127 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d851b9cf3570f1207fc78c1bcc98c281c2bb978c866187ffb1cc7b29a0b4045aefc08768df65717194ff0c6e63f4dea0d02", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 54, + "comment" : "modified bit 240 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281d2b0576ecf8eaf675f00f3dfbe19f75b83b7607a6c96414f6821af920a2498d0305", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 55, + "comment" : "modified bit 247 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c289c2be5241a345c7b5428054c74b7c382fa10d4a5f1e8f8b79a71d3fdea2254f1ff0e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 56, + "comment" : "modified bit 248 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2a63950c85cd6dc96364e768de50ff7732b538f8a0b1615d799190ab600849230e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 57, + "comment" : "modified bit 253 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c0b543bd3da0a56a8c9c152f59c9fec12f31fa66434d48b817b30d90cb4efa8b501", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 58, + "comment" : "modified bit 254 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c6b8da07efd07a6dafb015ed6a32fe136319a972ffbc341f3a0beae97ccf8136505", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 59, + "comment" : "modified bit 255 in R", + "msg" : "313233343030", + "sig" : "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281cab227aedf259f910f0f3a759a335062665217925d019173b88917eae294f75d40f", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 60, + "comment" : "R==0", + "msg" : "313233343030", + "sig" : "0000000000000000000000000000000000000000000000000000000000000000e0b8e7770d51c7a36375d006c5bffd6af43ff54aaf47e4330dc118c71d61ec02", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 61, + "comment" : "invalid R", + "msg" : "313233343030", + "sig" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff463a1908382e7eb7693acef9884f7cf931a215e0791876be22c631a59881fd0e", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 62, + "comment" : "all bits flipped in R", + "msg" : "313233343030", + "sig" : "9a83eb6dbfd54a31fc1d3c580fc7b2fae4630ca8f0edf803873e433673d7e3d40e94254586cb6188c5386c3febed477cb9a6cb29e3979adc4cb27cf5278fb70a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 63, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab067654bce3832c2d76f8f6f5dafc08d9339d4eef676573336a5c51eb6f946b31d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + }, + { + "tcId" : 64, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab05439412b5395d42f462c67008eba6ca839d4eef676573336a5c51eb6f946b32d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + }, + { + "tcId" : 65, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab02ee12ce5875bf9dff26556464bae2ad239d4eef676573336a5c51eb6f946b34d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + }, + { + "tcId" : 66, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0e2300459f1e742404cd934d2c595a6253ad4eef676573336a5c51eb6f946b38d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + }, + { + "tcId" : 67, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b32d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + }, + { + "tcId" : 68, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b34d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + }, + { + "tcId" : 69, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + }, + { + "tcId" : 70, + "comment" : "checking malleability ", + "msg" : "54657374", + "sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab0679155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b38d", + "result" : "invalid", + "flags" : [ + "SignatureMalleability" + ] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c", + "sk" : "0a23a20072891237aa0864b5765139514908787878cd77135a0059881d313f00", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAoSwr63cmXyqslTtQCTSdlBVaA62kFqrUUTGUgOmDykw=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 71, + "comment" : "", + "msg" : "", + "sig" : "5056325d2ab440bf30bbf0f7173199aa8b4e6fbc091cf3eb6bc6cf87cd73d992ffc216c85e4ab5b8a0bbc7e9a6e9f8d33b7f6e5ac0ffdc22d9fcaf784af84302", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 72, + "comment" : "", + "msg" : "78", + "sig" : "481fafbf4364d7b682475282f517a3ac0538c9a6b6a562e99a3d8e5afb4f90a559b056b9f07af023905753b02d95eb329a35c77f154b79abbcd291615ce42f02", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 73, + "comment" : "", + "msg" : "54657374", + "sig" : "8a9bb4c465a3863abc9fd0dd35d80bb28f7d33d37d74679802d63f82b20da114b8d765a1206b3e9ad7cf2b2d8d778bb8651f1fa992db293c0039eacb6161480f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 74, + "comment" : "", + "msg" : "48656c6c6f", + "sig" : "d839c20abfda1fd429531831c64f813f84b913e9928540310cf060b44c3dbf9457d44a7721fdc0d67724ff81cb450dd39b10cfb65db15dda4b8bf09d26bd3801", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 75, + "comment" : "", + "msg" : "313233343030", + "sig" : "9bbb1052dcfa8ad2715c2eb716ae4f1902dea353d42ee09fd4c0b4fcb8b52b5219e2200016e1199d0061891c263e31b0bc3b55673c19610c4e0fa5408004160b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 76, + "comment" : "", + "msg" : "000000000000000000000000", + "sig" : "f63b5c0667c7897fc283296416f7f60e84bbde9cbd832e56be463ed9f568069702b17a2f7c341ebf590706a6388ac76ac613c1675ec0f2c7118f2573422a500b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 77, + "comment" : "", + "msg" : "6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", + "sig" : "1bc44d7001e6b5b9090fef34b2ca480f9786bbefa7d279353e5881e8dfb91b803ccd46500e270ef0109bfd741037558832120bc2a4f20fbe7b5fb3c3aaf23e08", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 78, + "comment" : "", + "msg" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f60", + "sig" : "ea8e22143b02372e76e99aece3ed36aec529768a27e2bb49bdc135d44378061e1f62d1ac518f33ebf37b2ee8cc6dde68a4bd7d4a2f4d6cb77f015f71ca9fc30d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 79, + "comment" : "", + "msg" : "ffffffffffffffffffffffffffffffff", + "sig" : "8acd679e1a914fc45d5fa83d3021f0509c805c8d271df54e52f43cfbd00cb6222bf81d58fe1de2de378df67ee9f453786626961fe50a9b05f12b6f0899ebdd0a", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + "sk" : "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 80, + "comment" : "draft-josefsson-eddsa-ed25519-02: Test 1", + "msg" : "", + "sig" : "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + "sk" : "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b65700321003d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAPUAXw+hDiVqStwqnTRt+vJyYLM8uxJaMwM1V8Sr0Zgw=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 81, + "comment" : "draft-josefsson-eddsa-ed25519-02: Test 2", + "msg" : "72", + "sig" : "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + "sk" : "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA/FHNjmIYoaONpH7QAjDwWAgW7RO6MwOsXeuRFUiQgCU=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 82, + "comment" : "draft-josefsson-eddsa-ed25519-02: Test 3", + "msg" : "af82", + "sig" : "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", + "sk" : "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAJ4EX/BRMcjQPZ9DyMW6Dhs7/vyskKMnFH+98WX8dQm4=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 83, + "comment" : "draft-josefsson-eddsa-ed25519-02: Test 1024", + "msg" : "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", + "sig" : "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "8fd659b77b558ed93882c1157438450ac86ec62d421d568e98ee236f3810295a", + "sk" : "d7ad3f1f6bbe0477c3c357a806a19eb41ae3f94025035bc87f281f8ee9fc0e34", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b65700321008fd659b77b558ed93882c1157438450ac86ec62d421d568e98ee236f3810295a", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAj9ZZt3tVjtk4gsEVdDhFCshuxi1CHVaOmO4jbzgQKVo=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 84, + "comment" : "Random test failure 1", + "msg" : "b0729a713593a92e46b56eaa66b9e435f7a09a8e7de03b078f6f282285276635f301e7aaafe42187c45d6f5b13f9f16b11195cc125c05b90d24dfe4c", + "sig" : "7db17557ac470c0eda4eedaabce99197ab62565653cf911f632ee8be0e5ffcfc88fb94276b42e0798fd3aa2f0318be7fc6a29fae75f70c3dcdc414a0ad866601", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "2a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082", + "sk" : "ad9b22793336fcdac10e136c4deea599be187a38eef91c1cf7c7a4ec884dda08", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b65700321002a606bf67ac770c607038b004101b325edb569efd3413d2d1f2c3e6b4e6e3082", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAKmBr9nrHcMYHA4sAQQGzJe21ae/TQT0tHyw+a05uMII=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 85, + "comment" : "Random test failure 2", + "msg" : "a8546e50ba31cae3234310d32672447be213fad91a227a19669c53d309b959782b0e6b71f8791fdb470043b58122003157d2d96a43a6cbd7d3a8d86bf4c97391883e268d50af80e1e6e12939c2bd50ca746cdadfad4edf1bda875299740724148efb1ebe73fb60088cda890317658627a5f7ab5a0c075d9d8f3f97b6492b35519e50ff6b38377432a7081f9176bb1c29a862deac1336ca20b097a47829cec10a6a7cec178eda2d12f6dc6c87f910454af0123555ba184e68804d9cced60fd5c8c90943e56599c8f0ba59a38491ba5e5a53460682474c07e40ca142983314fd762856bb1093f359da6eb0a756bd93a3160c10dd8feea6b97e7c6a17cb54bd5d7649c05c66d7bdee056671dfdaf689fa3945bb8e29a429f4bd5d355dce9687b06f01d5e33e3999f0e8", + "sig" : "67d84d4c3945aaf06e06d524be63acbfb5dbb1988c4aea96a5ee9f7a9b9eecc29df4f66b8aa1d9e8607a58fb1ef0c2ad69aac005b4f58e34103344a9c8871a09", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 86, + "comment" : "Random test failure 24", + "msg" : "b477b0480bb84642608b908d29a51cf2fce63f24ee95", + "sig" : "28fafbb62b4d688fa79e1ac92851f46e319b161f801d4dc09acc21fdd6780a2c4292b8c1003c61c2bcebe7f3f88ccc4bb26d407387c5f27cb8c94cf6ce810405", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051", + "sk" : "04a6553d68a9baef78a2175af375458eaa01cdb77350c61e282ef5f0c7116599", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100c9c946cbc5544ac74eef491f07c5881c16faf7ec31ce4aa91bb60ae7b4539051", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAyclGy8VUSsdO70kfB8WIHBb69+wxzkqpG7YK57RTkFE=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 87, + "comment" : "Random test failure 3", + "msg" : "cd2212eddb0706f62c995cef958634f0cb7793444cbf4d30e81c27c41ebea6cb02607510131f9c015692dfd521b148841e9a2d3564d20ac401f6cb8e40f520fe0cafbeaa88840b83013369d879f013463fe52a13267aa0c8c59c45cde9399cd1e6be8cc64cf48315ac2eb31a1c567a4fb7d601746d1f63b5ac020712adbbe07519bded6f", + "sig" : "24087d47f3e20af51b9668ae0a88ce76586802d0ec75d8c0f28fc30962b5e1d1a1d509571a1624ed125a8df92a6e963728d6b5de99200b8e285f70feb6f05207", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 88, + "comment" : "Random test failure 20", + "msg" : "27d465bc632743522aefa23c", + "sig" : "c2656951e2a0285585a51ff0eda7e9a23c2dfd2ffa273aee7808f4604e8f9a8c8ea49e9fce4eb2d8d75d36b7238fe6fc13b6c5d9427dd58f8c6615d033c0bd0f", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "32ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e", + "sk" : "c367c8d2ebeeecd70c1e8985b70c3808b75657f243b21ba4f322792540e92257", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b657003210032ad026f693d0d2afe7f4388d91c4c964426fcb9e3665c3ebd8650009b815c8e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAMq0Cb2k9DSr+f0OI2RxMlkQm/LnjZlw+vYZQAJuBXI4=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 89, + "comment" : "Random test failure 4", + "msg" : "ec5c7cb078", + "sig" : "d920d421a5956b69bfe1ba834c025e2babb6c7a6d78c97de1d9bb1116dfdd1185147b2887e34e15578172e150774275ea2aad9e02106f7e8ca1caa669a066f0c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 90, + "comment" : "Random test failure 5", + "msg" : "4668c6a76f0e482190a7175b9f3806a5fe4314a004fa69f988373f7a", + "sig" : "4f62daf7f7c162038552ad7d306e195baa37ecf6ca7604142679d7d1128e1f8af52e4cb3545748c44ef1ff1c64e877e4f4d248259b7f6eb56e3ef72097dc8e0c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 91, + "comment" : "Random test failure 8", + "msg" : "5dc9bb87eb11621a93f92abe53515697d2611b2eef73", + "sig" : "deecafb6f2ede73fec91a6f10e45b9c1c61c4b9bfbe6b6147e2de0b1df6938971f7896c3ab83851fb5d9e537037bff0fca0ccb4a3cc38f056f91f7d7a0557e08", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 92, + "comment" : "Random test failure 10", + "msg" : "7dcfe60f881e1285676f35b68a1b2dbcdd7be6f719a288ababc28d36e3a42ac3010a1ca54b32760e74", + "sig" : "7f8663cf98cbd39d5ff553f00bcf3d0d520605794f8866ce75714d77cc51e66c91818b657d7b0dae430a68353506edc4a714c345f5ddb5c8b958ba3d035f7a01", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 93, + "comment" : "Random test failure 12", + "msg" : "58e456064dff471109def4ca27fa8310a1df32739655b624f27e6418d34b7f007173f3faa5", + "sig" : "6aab49e5c0bc309b783378ee03ffda282f0185cdf94c847701ff307a6ee8d0865411c44e0a8206f6a5f606107451940c2593af790ce1860f4c14ab25b2deae08", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 94, + "comment" : "Random test failure 15", + "msg" : "a1", + "sig" : "1a74ed2cbdc7d8f3827014e8e6ecf8fd2698ac8f86833acccdd400df710fe0d6b0543c9cfa00d52bf024ab7ce0d91981944097233ec134d5c7abbd44bfd32d0d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 95, + "comment" : "Random test failure 19", + "msg" : "11cb1eafa4c42a8402c4193c4696f7b2e6d4585e4b42dcf1a8b67a80b2da80bc9d4b649fb2f35eaf1f56c426fd0b", + "sig" : "14ceb2eaf4688d995d482f44852d71ad878cd7c77b41e60b0065fd01a59b054ee74759224187dbde9e59a763a70277c960892ef89fba997aba2576b2c54ba608", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 96, + "comment" : "Random test failure 25", + "msg" : "aa365b442d12b7f3c925", + "sig" : "83c40ce13d483cc58ff65844875862d93df4bd367af77efa469ec06a8ed9e6d7905a04879535708ddf225567a815c9b941d405c98e918fd0c151165cea7fb101", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 97, + "comment" : "Random test failure 28", + "msg" : "475f", + "sig" : "71a4a06a34075f2fd47bc3abf4714d46db7e97b08cb6180d3f1539ac50b18ce51f8af8ae95ed21d4fa0daab7235925631ecea1fd9d0d8a2ba7a7583fd04b900c", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a", + "sk" : "56c1e22d616cbb6dea869288b4b1c02bb98696583c2f6e650013a03e17049c62", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100c29ec1894e06d27b4e40486b4fa5063d66a746c7f9c323b12203c03b72b8b78a", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAwp7BiU4G0ntOQEhrT6UGPWanRsf5wyOxIgPAO3K4t4o=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 98, + "comment" : "Random test failure 6", + "msg" : "0f325ffd87e58131ffa23c05ea4579513b287fdba87b44", + "sig" : "6669acf94667c5b541afe5307bde9476b13ae7e0e6058a772101ac8eb0a94331428eb4db0a2c68a9b6c1763b8624dab259b0876cdcfaeacc17b21a18e3fc010a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 99, + "comment" : "Random test failure 21", + "msg" : "5ffa", + "sig" : "931e5152fcef078c22cc5d6a3a65f06e396289f6f5f2d1efa6340254a53526ef5dc6874eeddf35c3f50991c53cd02bf06313e37d93ee1f7022128ffa3b8f300b", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10", + "sk" : "b7d2f64276df417fed27d8e15b4e90f6fd93dace707294c338bd32bc4bbd8fdb", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100cfda5b899e35764c5229e59295fe1222b7ddce176643697c29e46ecbba10cf10", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAz9pbiZ41dkxSKeWSlf4SIrfdzhdmQ2l8KeRuy7oQzxA=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 100, + "comment" : "Random test failure 7", + "msg" : "ec5c7cb078", + "sig" : "30490c28f806298225df62103521dcee047153912c33ab8ab8bbdd1ffabd70fd4fdb360f05be535b067d1cf4e78c2cb432206bf280aab3bd21aaa1cb894c5b06", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 101, + "comment" : "Random test failure 9", + "msg" : "67484059b2490b1a0a4f8dee77979e26", + "sig" : "4cd4f77ed473a6647387f3163541c67a1708a3c3bd1673247cb87f0cb68b3c56f04bfa72970c8a483efe659c87009ab4020b590b6641316b3deddb5450544e02", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 102, + "comment" : "Random test failure 11", + "msg" : "a020a4381dc9141f47ee508871ab7a8b5a3648727c4281ae9932376f23a8e1bcda0626b7129197d864178631ec89c4332dbb18", + "sig" : "1e41a24fe732bd7cab14c2a2f5134ee8c87fcbd2e987e60957ed9239e5c32404d56977e1b4282871896cb10625a1937468e4dc266e16a9c1b8e9891177eca802", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 103, + "comment" : "Random test failure 14", + "msg" : "a25176b3afea318b2ec11ddacb10caf7179c0b3f8eabbfa2895581138d3c1e0e", + "sig" : "2a833aadecd9f28235cb5896bf3781521dc71f28af2e91dbe1735a61dce3e31ac15ca24b3fc47817a59d386bbbb2ce60a6adc0a2703bb2bdea8f70f91051f706", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 104, + "comment" : "Random test failure 18", + "msg" : "a9e6d94870a67a9fe1cf13b1e6f9150cdd407bf6480ec841ea586ae3935e9787163cf419c1", + "sig" : "c97e3190f83bae7729ba473ad46b420b8aad735f0808ea42c0f898ccfe6addd4fd9d9fa3355d5e67ee21ab7e1f805cd07f1fce980e307f4d7ad36cc924eef00c", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56", + "sk" : "7d597c3b7283929d07ed8f01f31d2596823e5e46ab226c7be4234d1a9dcaef37", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100529919c9c780985a841c42ba6c180ff2d67a276ccfbe281080e47ab71a758f56", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAUpkZyceAmFqEHEK6bBgP8tZ6J2zPvigQgOR6txp1j1Y=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 105, + "comment" : "Random test failure 13", + "msg" : "e1cbf2d86827825613fb7a85811d", + "sig" : "01abfa4d6bbc726b196928ec84fd03f0c953a4fa2b228249562ff1442a4f63a7150b064f3712b51c2af768d2c2711a71aabf8d186833e941a0301b82f0502905", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 106, + "comment" : "Random test failure 22", + "msg" : "25", + "sig" : "e4ae21f7a8f4b3b325c161a8c6e53e2edd7005b9c2f8a2e3b0ac4ba94aa80be6f2ee22ac8d4a96b9a3eb73a825e7bb5aff4a3393bf5b4a38119e9c9b1b041106", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "2252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1", + "sk" : "f401cee4bfb1732f0e9b8d8ba79469565c3115296141dbdf7e9c311a0ac1823b", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b65700321002252b3d57c74cbf8bc460dc2e082847926bc022f09ab6ae95756362bfd1167c1", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAIlKz1Xx0y/i8Rg3C4IKEeSa8Ai8Jq2rpV1Y2K/0RZ8E=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 107, + "comment" : "Random test failure 16", + "msg" : "975ef941710071a9e1e6325a0c860becd7c695b5117c3107b686e330e5", + "sig" : "af0fd9dda7e03e12313410d8d8844ebb6fe6b7f65141f22d7bcba5695a25414a9e54326fb44d59fb14707899a8aae70857b23d4080d7ab2c396ef3a36d45ce02", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 108, + "comment" : "Random test failure 23", + "msg" : "80fdd6218f29c8c8f6bd820945f9b0854e3a8824", + "sig" : "e097e0bd0370bff5bde359175a11b728ee9639095d5df8eda496395565616edfe079977f7d4dc8c75d6113a83d6a55e6e1676408c0967a2906339b43337dcb01", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "c0a773110f975de3732355bb7ec7f0c41c091c0252966070205516693b992a4a", + "sk" : "3d658956410377d0644676d2599542412a4f3b0e4eadfb7f3f836615f42b18bc", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b6570032100c0a773110f975de3732355bb7ec7f0c41c091c0252966070205516693b992a4a", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAwKdzEQ+XXeNzI1W7fsfwxBwJHAJSlmBwIFUWaTuZKko=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 109, + "comment" : "Random test failure 17", + "msg" : "", + "sig" : "0280427e713378f49d478df6373c6cac847b622b567daa2376c839e7ac10e22c380ab0fa8617c9dcfe76c4d9db5459b21dc1413726e46cc8f387d359e344f407", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "54cda623245759ad6d43e620a606908befc633d60792bc7798447a0ef38e7311", + "sk" : "bccb61323840c2a96fc36f7e54ea6c8e55f9d221f7f05791ed60025e06064439", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b657003210054cda623245759ad6d43e620a606908befc633d60792bc7798447a0ef38e7311", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAVM2mIyRXWa1tQ+YgpgaQi+/GM9YHkrx3mER6DvOOcxE=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 110, + "comment" : "Random test failure 26", + "msg" : "27e792b28b2f1702", + "sig" : "14d9b497c19b91d43481c55bb6f5056de252d9ecb637575c807e58e9b4c5eac8b284089d97e2192dc242014363208e2c9a3435edf8928fb1d893553e9be4c703", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "edwards25519", + "keySize" : 255, + "pk" : "2362bac514d5fad33802642e979a1e82de6eb6f1bcbf6a5b304f2bb02b9e57fe", + "sk" : "f2d3023b9c19e241748bc4039a7a43c595701f23675505015213a8a2a0274c1b", + "type" : "EDDSAKeyPair" + }, + "keyDer" : "302a300506032b65700321002362bac514d5fad33802642e979a1e82de6eb6f1bcbf6a5b304f2bb02b9e57fe", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAI2K6xRTV+tM4AmQul5oegt5utvG8v2pbME8rsCueV/4=\n-----END PUBLIC KEY-----\n", + "type" : "EDDSAVer", + "tests" : [ + { + "tcId" : 111, + "comment" : "Random test failure 27", + "msg" : "eef3bb0f617c17d0420c115c21c28e3762edc7b7fb048529b84a9c2bc6", + "sig" : "242ddb3a5d938d07af690b1b0ef0fa75842c5f9549bf39c8750f75614c712e7cbaf2e37cc0799db38b858d41aec5b9dd2fca6a3c8e082c10408e2cf3932b9d08", + "result" : "valid", + "flags" : [] + } + ] + } + ] +})abcd"; +} diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellString.cpp b/submodules/ton/tonlib-src/crypto/vm/cells/CellString.cpp new file mode 100644 index 0000000000..ad2cbf5f8f --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/vm/cells/CellString.cpp @@ -0,0 +1,64 @@ +#include "CellString.h" +#include "td/utils/misc.h" + +#include "vm/cells/CellSlice.h" + +namespace vm { +td::Status CellString::store(CellBuilder &cb, td::Slice slice, unsigned int top_bits) { + td::uint32 size = td::narrow_cast(slice.size() * 8); + return store(cb, td::BitSlice(slice.ubegin(), size), top_bits); +} + +td::Status CellString::store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits) { + if (slice.size() > max_bytes * 8) { + return td::Status::Error("String is too long (1)"); + } + unsigned int head = td::min(slice.size(), td::min(cb.remaining_bits(), top_bits)) / 8 * 8; + auto max_bits = vm::Cell::max_bits / 8 * 8; + auto depth = 1 + (slice.size() - head + max_bits - 1) / max_bits; + if (depth > max_chain_length) { + return td::Status::Error("String is too long (2)"); + } + cb.append_bitslice(slice.subslice(0, head)); + slice.advance(head); + if (slice.size() == 0) { + return td::Status::OK(); + } + CellBuilder child_cb; + store(child_cb, std::move(slice)); + cb.store_ref(child_cb.finalize()); + return td::Status::OK(); +} + +template +void CellString::for_each(F &&f, CellSlice &cs, unsigned int top_bits) { + unsigned int head = td::min(cs.size(), top_bits); + f(cs.prefetch_bits(head)); + if (!cs.have_refs()) { + return; + } + auto ref = cs.prefetch_ref(); + while (true) { + auto cs = vm::load_cell_slice(ref); + f(cs.prefetch_bits(cs.size())); + if (!cs.have_refs()) { + return; + } + ref = cs.prefetch_ref(); + } +} + +td::Result CellString::load(CellSlice &cs, unsigned int top_bits) { + unsigned int size = 0; + for_each([&](auto slice) { size += slice.size(); }, cs, top_bits); + if (size % 8 != 0) { + return td::Status::Error("Size is not divisible by 8"); + } + std::string res(size / 8, 0); + + td::BitPtr to(td::MutableSlice(res).ubegin()); + for_each([&](auto slice) { to.concat(slice); }, cs, top_bits); + CHECK(to.offs == (int)size); + return res; +} +} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/cells/CellString.h b/submodules/ton/tonlib-src/crypto/vm/cells/CellString.h new file mode 100644 index 0000000000..89c933d876 --- /dev/null +++ b/submodules/ton/tonlib-src/crypto/vm/cells/CellString.h @@ -0,0 +1,22 @@ +#pragma once + +#include "td/utils/Status.h" + +#include "vm/cells/CellBuilder.h" + +namespace vm { +class CellString { + public: + static constexpr unsigned int max_bytes = 1024; + static constexpr unsigned int max_chain_length = 16; + + static td::Status store(CellBuilder &cb, td::Slice slice, unsigned int top_bits = Cell::max_bits); + static td::Status store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits = Cell::max_bits); + static td::Result load(CellSlice &cs, unsigned int top_bits = Cell::max_bits); + + private: + template + static void for_each(F &&f, CellSlice &cs, unsigned int top_bits = Cell::max_bits); +}; + +} // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/continuation.cpp b/submodules/ton/tonlib-src/crypto/vm/continuation.cpp index 24157d3b2a..d4952769a5 100644 --- a/submodules/ton/tonlib-src/crypto/vm/continuation.cpp +++ b/submodules/ton/tonlib-src/crypto/vm/continuation.cpp @@ -349,7 +349,7 @@ VmState::VmState(Ref _code) } VmState::VmState(Ref _code, Ref _stack, int flags, Ref _data, VmLog log, - std::vector> _libraries) + std::vector> _libraries, Ref init_c7) : code(std::move(_code)) , stack(std::move(_stack)) , cp(-1) @@ -360,11 +360,14 @@ VmState::VmState(Ref _code, Ref _stack, int flags, Ref _ , libraries(std::move(_libraries)) { ensure_throw(init_cp(0)); set_c4(std::move(_data)); + if (init_c7.not_null()) { + set_c7(std::move(init_c7)); + } init_cregs(flags & 1, flags & 2); } VmState::VmState(Ref _code, Ref _stack, const GasLimits& gas, int flags, Ref _data, VmLog log, - std::vector> _libraries) + std::vector> _libraries, Ref init_c7) : code(std::move(_code)) , stack(std::move(_stack)) , cp(-1) @@ -376,6 +379,9 @@ VmState::VmState(Ref _code, Ref _stack, const GasLimits& gas, , libraries(std::move(_libraries)) { ensure_throw(init_cp(0)); set_c4(std::move(_data)); + if (init_c7.not_null()) { + set_c7(std::move(init_c7)); + } init_cregs(flags & 1, flags & 2); } @@ -738,6 +744,9 @@ int VmState::run() { } } while (!res); // LOG(INFO) << "[EN] data cells: " << DataCell::get_total_data_cells(); + if ((res | 1) == -1) { + commit(); + } return res; } @@ -755,10 +764,15 @@ ControlRegs* force_cregs(Ref& cont) { } int run_vm_code(Ref code, Ref& stack, int flags, Ref* data_ptr, VmLog log, long long* steps, - GasLimits* gas_limits, std::vector> libraries) { - VmState vm{ - code, std::move(stack), gas_limits ? *gas_limits : GasLimits{}, flags, data_ptr ? *data_ptr : Ref{}, - log, std::move(libraries)}; + GasLimits* gas_limits, std::vector> libraries, Ref init_c7) { + VmState vm{code, + std::move(stack), + gas_limits ? *gas_limits : GasLimits{}, + flags, + data_ptr ? *data_ptr : Ref{}, + log, + std::move(libraries), + std::move(init_c7)}; int res = vm.run(); stack = vm.get_stack_ref(); if (res == -1 && data_ptr) { @@ -785,11 +799,11 @@ int run_vm_code(Ref code, Ref& stack, int flags, Ref* da } int run_vm_code(Ref code, Stack& stack, int flags, Ref* data_ptr, VmLog log, long long* steps, - GasLimits* gas_limits, std::vector> libraries) { + GasLimits* gas_limits, std::vector> libraries, Ref init_c7) { Ref stk{true}; stk.unique_write().set_contents(std::move(stack)); stack.clear(); - int res = run_vm_code(code, stk, flags, data_ptr, log, steps, gas_limits, std::move(libraries)); + int res = run_vm_code(code, stk, flags, data_ptr, log, steps, gas_limits, std::move(libraries), std::move(init_c7)); CHECK(stack.is_unique()); if (stk.is_null()) { stack.clear(); diff --git a/submodules/ton/tonlib-src/crypto/vm/continuation.h b/submodules/ton/tonlib-src/crypto/vm/continuation.h index 80f19e156d..c6c9d320ed 100644 --- a/submodules/ton/tonlib-src/crypto/vm/continuation.h +++ b/submodules/ton/tonlib-src/crypto/vm/continuation.h @@ -154,7 +154,7 @@ struct ControlData { class Continuation : public td::CntObject { public: - virtual int jump(VmState* st) const & = 0; + virtual int jump(VmState* st) const& = 0; virtual int jump_w(VmState* st) &; virtual ControlData* get_cdata() { return 0; @@ -184,7 +184,7 @@ class QuitCont : public Continuation { QuitCont(int _code = 0) : exit_code(_code) { } ~QuitCont() override = default; - int jump(VmState* st) const & override { + int jump(VmState* st) const& override { return ~exit_code; } }; @@ -193,7 +193,7 @@ class ExcQuitCont : public Continuation { public: ExcQuitCont() = default; ~ExcQuitCont() override = default; - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; }; class PushIntCont : public Continuation { @@ -204,7 +204,7 @@ class PushIntCont : public Continuation { PushIntCont(int val, Ref _next) : push_val(val), next(_next) { } ~PushIntCont() override = default; - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; int jump_w(VmState* st) & override; }; @@ -217,7 +217,7 @@ class RepeatCont : public Continuation { : body(std::move(_body)), after(std::move(_after)), count(_count) { } ~RepeatCont() override = default; - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; int jump_w(VmState* st) & override; }; @@ -228,7 +228,7 @@ class AgainCont : public Continuation { AgainCont(Ref _body) : body(std::move(_body)) { } ~AgainCont() override = default; - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; int jump_w(VmState* st) & override; }; @@ -239,7 +239,7 @@ class UntilCont : public Continuation { UntilCont(Ref _body, Ref _after) : body(std::move(_body)), after(std::move(_after)) { } ~UntilCont() override = default; - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; int jump_w(VmState* st) & override; }; @@ -252,7 +252,7 @@ class WhileCont : public Continuation { : cond(std::move(_cond)), body(std::move(_body)), after(std::move(_after)), chkcond(_chk) { } ~WhileCont() override = default; - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; int jump_w(VmState* st) & override; }; @@ -268,7 +268,7 @@ class ArgContExt : public Continuation { ArgContExt(const ArgContExt&) = default; ArgContExt(ArgContExt&&) = default; ~ArgContExt() override = default; - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; int jump_w(VmState* st) & override; ControlData* get_cdata() override { return &data; @@ -303,7 +303,7 @@ class OrdCont : public Continuation { td::CntObject* make_copy() const override { return new OrdCont{*this}; } - int jump(VmState* st) const & override; + int jump(VmState* st) const& override; int jump_w(VmState* st) & override; ControlData* get_cdata() override { @@ -321,7 +321,7 @@ class OrdCont : public Continuation { Ref get_stack_ref() const { return data.stack; } - Ref copy_ord() const & { + Ref copy_ord() const& { return Ref{true, *this}; } Ref copy_ord() && { @@ -375,10 +375,16 @@ struct GasLimits { } }; +struct CommittedState { + Ref c4, c5; + bool committed{false}; +}; + class VmState final : public VmStateInterface { Ref code; Ref stack; ControlRegs cr; + CommittedState cstate; int cp; long long steps{0}; const DispatchTable* dispatch; @@ -388,19 +394,25 @@ class VmState final : public VmStateInterface { std::vector> libraries; int stack_trace{0}, debug_off{0}; + bool chksig_always_succeed{false}; + public: static constexpr unsigned cell_load_gas_price = 100, cell_create_gas_price = 500, exception_gas_price = 50, tuple_entry_gas_price = 1; VmState(); VmState(Ref _code); VmState(Ref _code, Ref _stack, int flags = 0, Ref _data = {}, VmLog log = {}, - std::vector> _libraries = {}); + std::vector> _libraries = {}, Ref init_c7 = {}); VmState(Ref _code, Ref _stack, const GasLimits& _gas, int flags = 0, Ref _data = {}, - VmLog log = {}, std::vector> _libraries = {}); + VmLog log = {}, std::vector> _libraries = {}, Ref init_c7 = {}); template VmState(Ref code_cell, Args&&... args) : VmState(convert_code_cell(std::move(code_cell)), std::forward(args)...) { } + VmState(const VmState&) = delete; + VmState(VmState&&) = delete; + VmState& operator=(const VmState&) = delete; + VmState& operator=(VmState&&) = delete; bool set_gas_limits(long long _max, long long _limit, long long _credit = 0); bool final_gas_ok() const { return gas.final_ok(); @@ -408,6 +420,12 @@ class VmState final : public VmStateInterface { long long gas_consumed() const { return gas.gas_consumed(); } + bool committed() const { + return cstate.committed; + } + const CommittedState& get_committed_state() const { + return cstate; + } void consume_gas(long long amount) { gas.consume(amount); } @@ -567,15 +585,29 @@ class VmState final : public VmStateInterface { return cont->is_unique() ? cont.unique_write().jump_w(this) : cont->jump(this); } static Ref convert_code_cell(Ref code_cell); + void commit() { + cstate.c4 = cr.d[0]; + cstate.c5 = cr.d[1]; + cstate.committed = true; + } + + void set_chksig_always_succeed(bool flag) { + chksig_always_succeed = flag; + } + bool get_chksig_always_succeed() const { + return chksig_always_succeed; + } private: void init_cregs(bool same_c3 = false, bool push_0 = true); }; int run_vm_code(Ref _code, Ref& _stack, int flags = 0, Ref* data_ptr = 0, VmLog log = {}, - long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector> libraries = {}); + long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector> libraries = {}, + Ref init_c7 = {}); int run_vm_code(Ref _code, Stack& _stack, int flags = 0, Ref* data_ptr = 0, VmLog log = {}, - long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector> libraries = {}); + long long* steps = nullptr, GasLimits* gas_limits = nullptr, std::vector> libraries = {}, + Ref init_c7 = {}); ControlData* force_cdata(Ref& cont); ControlRegs* force_cregs(Ref& cont); diff --git a/submodules/ton/tonlib-src/crypto/vm/excno.hpp b/submodules/ton/tonlib-src/crypto/vm/excno.hpp index f67d8a4e92..a18f890a36 100644 --- a/submodules/ton/tonlib-src/crypto/vm/excno.hpp +++ b/submodules/ton/tonlib-src/crypto/vm/excno.hpp @@ -18,6 +18,8 @@ */ #pragma once +#include "td/utils/Status.h" + namespace vm { enum class Excno : int { @@ -95,4 +97,19 @@ struct VmVirtError { struct VmFatal {}; +template +auto try_f(F&& f) noexcept -> decltype(f()) { + try { + return f(); + } catch (vm::VmError error) { + return td::Status::Error(PSLICE() << "Got a vm exception: " << error.get_msg()); + } catch (vm::VmVirtError error) { + return td::Status::Error(PSLICE() << "Got a vm virtualization exception: " << error.get_msg()); + } catch (vm::VmNoGas error) { + return td::Status::Error(PSLICE() << "Got a vm no gas exception: " << error.get_msg()); + } +} + +#define TRY_VM(f) ::vm::try_f([&] { return f; }) + } // namespace vm diff --git a/submodules/ton/tonlib-src/crypto/vm/tonops.cpp b/submodules/ton/tonlib-src/crypto/vm/tonops.cpp index 30d3d14b88..e2142f072f 100644 --- a/submodules/ton/tonlib-src/crypto/vm/tonops.cpp +++ b/submodules/ton/tonlib-src/crypto/vm/tonops.cpp @@ -75,10 +75,17 @@ int exec_set_gas_limit(VmState* st) { return exec_set_gas_generic(st, gas); } +int exec_commit(VmState* st) { + VM_LOG(st) << "execute COMMIT"; + st->commit(); + return 0; +} + void register_basic_gas_ops(OpcodeTable& cp0) { using namespace std::placeholders; cp0.insert(OpcodeInstr::mksimple(0xf800, 16, "ACCEPT", exec_accept)) - .insert(OpcodeInstr::mksimple(0xf801, 16, "SETGASLIMIT", exec_set_gas_limit)); + .insert(OpcodeInstr::mksimple(0xf801, 16, "SETGASLIMIT", exec_set_gas_limit)) + .insert(OpcodeInstr::mksimple(0xf80f, 16, "COMMIT", exec_commit)); } void register_ton_gas_ops(OpcodeTable& cp0) { @@ -268,7 +275,7 @@ int exec_ed25519_check_signature(VmState* st, bool from_slice) { } td::Ed25519::PublicKey pub_key{td::SecureString(td::Slice{key, 32})}; auto res = pub_key.verify_signature(td::Slice{data, data_len}, td::Slice{signature, 64}); - stack.push_bool(res.is_ok()); + stack.push_bool(res.is_ok() || st->get_chksig_always_succeed()); return 0; } diff --git a/submodules/ton/tonlib-src/lite-client/lite-client-common.cpp b/submodules/ton/tonlib-src/lite-client/lite-client-common.cpp index cc6949deac..82503faf35 100644 --- a/submodules/ton/tonlib-src/lite-client/lite-client-common.cpp +++ b/submodules/ton/tonlib-src/lite-client/lite-client-common.cpp @@ -4,6 +4,7 @@ #include "tl-utils/lite-utils.hpp" #include "ton/lite-tl.hpp" #include "td/utils/overloaded.h" +#include "td/utils/Random.h" using namespace std::literals::string_literals; @@ -74,4 +75,25 @@ td::Result> deserialize_proof_chain( LOG(DEBUG) << "deserialized a BlkProofChain of " << chain->link_count() << " links"; return std::move(chain); } +td::Ref prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt, td::Ref my_addr, + const block::CurrencyCollection& balance) { + td::BitArray<256> rand_seed; + td::RefInt256 rand_seed_int{true}; + td::Random::secure_bytes(rand_seed.as_slice()); + if (!rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false)) { + return {}; + } + auto tuple = vm::make_tuple_ref(td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea + td::make_refint(0), // actions:Integer + td::make_refint(0), // msgs_sent:Integer + td::make_refint(now), // unixtime:Integer + td::make_refint(lt), // block_lt:Integer + td::make_refint(lt), // trans_lt:Integer + std::move(rand_seed_int), // rand_seed:Integer + balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)] + my_addr, // myself:MsgAddressInt + vm::StackEntry()); // global_config:(Maybe Cell) ] = SmartContractInfo; + LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string(); + return vm::make_tuple_ref(std::move(tuple)); +} } // namespace liteclient diff --git a/submodules/ton/tonlib-src/lite-client/lite-client-common.h b/submodules/ton/tonlib-src/lite-client/lite-client-common.h index cbadd2b429..bca2c3079d 100644 --- a/submodules/ton/tonlib-src/lite-client/lite-client-common.h +++ b/submodules/ton/tonlib-src/lite-client/lite-client-common.h @@ -7,4 +7,7 @@ namespace liteclient { td::Result> deserialize_proof_chain( ton::lite_api::object_ptr f); -} + +td::Ref prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt, td::Ref my_addr, + const block::CurrencyCollection& balance); +} // namespace liteclient diff --git a/submodules/ton/tonlib-src/lite-client/lite-client.cpp b/submodules/ton/tonlib-src/lite-client/lite-client.cpp index 3817e987f8..54eb61b6ac 100644 --- a/submodules/ton/tonlib-src/lite-client/lite-client.cpp +++ b/submodules/ton/tonlib-src/lite-client/lite-client.cpp @@ -58,6 +58,7 @@ #include "vm/continuation.h" #include "vm/cp0.h" #include "ton/ton-shard.h" +#include "openssl/rand.hpp" #if TD_DARWIN || TD_LINUX #include @@ -1153,16 +1154,24 @@ void TestNode::got_account_state(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, t vm::load_cell_slice(info.root).print_rec(outp); out << outp.str(); out << "last transaction lt = " << info.last_trans_lt << " hash = " << info.last_trans_hash.to_hex() << std::endl; + block::gen::Account::Record_account acc; + block::gen::AccountStorage::Record store; + block::CurrencyCollection balance; + if (tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store) && balance.unpack(store.balance)) { + out << "account balance is " << balance.to_str() << std::endl; + } } else { out << "account state is empty" << std::endl; } } else if (info.root.not_null()) { block::gen::Account::Record_account acc; block::gen::AccountStorage::Record store; - if (!(tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store))) { + block::CurrencyCollection balance; + if (!(tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store) && balance.unpack(store.balance))) { LOG(ERROR) << "error unpacking account state"; return; } + out << "account balance is " << balance.to_str() << std::endl; int tag = block::gen::t_AccountState.get_tag(*store.state); switch (tag) { case block::gen::AccountState::account_uninit: @@ -1240,7 +1249,9 @@ void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton: } block::gen::Account::Record_account acc; block::gen::AccountStorage::Record store; - if (!(tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store))) { + block::CurrencyCollection balance; + if (!(tlb::unpack_cell(info.root, acc) && tlb::csr_unpack(acc.storage, store) && + balance.validate_unpack(store.balance))) { LOG(ERROR) << "error unpacking account state"; return; } @@ -1276,6 +1287,8 @@ void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton: vm::GasLimits gas{gas_limit}; LOG(DEBUG) << "creating VM"; vm::VmState vm{code, std::move(stack), gas, 1, data, vm::VmLog()}; + vm.set_c7(liteclient::prepare_vm_c7(info.gen_utime, info.gen_lt, acc.addr, balance)); // tuple with SmartContractInfo + // vm.incr_stack_trace(1); // enable stack dump after each step LOG(INFO) << "starting VM to run method `" << method << "` (" << method_id << ") of smart contract " << workchain << ":" << addr.to_hex(); int exit_code = ~vm.run(); @@ -1680,7 +1693,7 @@ bool TestNode::get_config_params(ton::BlockIdExt blkid, int mode, std::string fi true); LOG(INFO) << "requesting " << params.size() << " configuration parameters with respect to masterchain block " << blkid.to_str(); - return envelope_send_query(std::move(b), [ Self = actor_id(this), mode, filename, + return envelope_send_query(std::move(b), [ Self = actor_id(this), mode, filename, blkid, params = std::move(params) ](td::Result R) mutable { if (R.is_error()) { return; @@ -1690,20 +1703,25 @@ bool TestNode::get_config_params(ton::BlockIdExt blkid, int mode, std::string fi LOG(ERROR) << "cannot parse answer to liteServer.getConfigParams"; } else { auto f = F.move_as_ok(); - td::actor::send_closure_later(Self, &TestNode::got_config_params, ton::create_block_id(f->id_), + td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, ton::create_block_id(f->id_), std::move(f->state_proof_), std::move(f->config_proof_), mode, filename, std::move(params)); } }); } -void TestNode::got_config_params(ton::BlockIdExt blkid, td::BufferSlice state_proof, td::BufferSlice cfg_proof, - int mode, std::string filename, std::vector params) { +void TestNode::got_config_params(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, td::BufferSlice state_proof, + td::BufferSlice cfg_proof, int mode, std::string filename, std::vector params) { LOG(INFO) << "got configuration parameters"; if (!blkid.is_masterchain_ext()) { LOG(ERROR) << "reference block " << blkid.to_str() << " for the configuration is not a valid masterchain block"; return; } + if (blkid != req_blkid) { + LOG(ERROR) << "got configuration parameters with respect to block " << blkid.to_str() << " instead of " + << req_blkid.to_str(); + return; + } auto R = block::check_extract_state_proof(blkid, state_proof.as_slice(), cfg_proof.as_slice()); if (R.is_error()) { LOG(ERROR) << "masterchain state proof for " << blkid.to_str() << " is invalid : " << R.move_as_error().to_string(); diff --git a/submodules/ton/tonlib-src/lite-client/lite-client.h b/submodules/ton/tonlib-src/lite-client/lite-client.h index 19fe481e13..36830e8d5b 100644 --- a/submodules/ton/tonlib-src/lite-client/lite-client.h +++ b/submodules/ton/tonlib-src/lite-client/lite-client.h @@ -122,8 +122,8 @@ class TestNode : public td::actor::Actor { bool get_all_shards(bool use_last = true, ton::BlockIdExt blkid = {}); void got_all_shards(ton::BlockIdExt blk, td::BufferSlice proof, td::BufferSlice data); bool get_config_params(ton::BlockIdExt blkid, int mode = 0, std::string filename = ""); - void got_config_params(ton::BlockIdExt blkid, td::BufferSlice state_proof, td::BufferSlice cfg_proof, int mode, - std::string filename, std::vector params); + void got_config_params(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, td::BufferSlice state_proof, + td::BufferSlice cfg_proof, int mode, std::string filename, std::vector params); bool get_block(ton::BlockIdExt blk, bool dump = false); void got_block(ton::BlockIdExt blkid, td::BufferSlice data, bool dump); bool get_state(ton::BlockIdExt blk, bool dump = false); diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/PromiseFuture.h b/submodules/ton/tonlib-src/tdactor/td/actor/PromiseFuture.h index 1070e482df..cb2016196e 100644 --- a/submodules/ton/tonlib-src/tdactor/td/actor/PromiseFuture.h +++ b/submodules/ton/tonlib-src/tdactor/td/actor/PromiseFuture.h @@ -225,6 +225,7 @@ class Promise { promise_->set_error(std::move(error)); promise_.reset(); } + void set_result(Result &&result) { if (!promise_) { return; @@ -260,6 +261,26 @@ class Promise { explicit operator bool() { return static_cast(promise_); } + template + auto do_wrap(V &&value, F &&func) { + if (value.is_ok()) { + set_result(func(value.move_as_ok())); + } else { + set_error(value.move_as_error()); + } + } + + template + auto do_wrap(td::Status status, F &&func) { + set_error(std::move(status)); + } + + template + auto wrap(F &&func) { + return [promise = std::move(*this), func = std::move(func)](auto &&res) mutable { + promise.do_wrap(std::move(res), std::move(func)); + }; + } private: std::unique_ptr> promise_; diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.cpp b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.cpp index 7554a05d10..8894266204 100644 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.cpp +++ b/submodules/ton/tonlib-src/tdactor/td/actor/core/ActorExecutor.cpp @@ -76,7 +76,7 @@ void ActorExecutor::send(ActorSignals signals) { } void ActorExecutor::start() noexcept { - //LOG(ERROR) << "START " << actor_info_.get_name() << " " << tag("from_queue", options.from_queue); + //LOG(ERROR) << "START " << actor_info_.get_name() << " " << tag("from_queue", options_.from_queue); if (is_closed()) { return; } diff --git a/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.cpp b/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.cpp index 7e343c4dea..9569fac360 100644 --- a/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.cpp +++ b/submodules/ton/tonlib-src/tdactor/td/actor/core/Scheduler.cpp @@ -133,6 +133,7 @@ void Scheduler::ContextImpl::add_to_queue(ActorInfoPtr actor_info_ptr, Scheduler if (!scheduler_id.is_valid()) { scheduler_id = get_scheduler_id(); } + //LOG(ERROR) << "Add to queue: " << actor_info_ptr->get_name() << " " << scheduler_id.value(); auto &info = scheduler_group()->schedulers.at(scheduler_id.value()); if (need_poll || !info.cpu_queue) { info.io_queue->writer_put(std::move(actor_info_ptr)); diff --git a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.cpp b/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.cpp index dfc97e608d..5e187342be 100644 --- a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.cpp +++ b/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.cpp @@ -73,5 +73,57 @@ void TcpListener::loop() { return stop(); } } +TcpInfiniteListener::TcpInfiniteListener(int32 port, std::unique_ptr callback) + : port_(port), callback_(std::move(callback)) { +} + +void TcpInfiniteListener::start_up() { + loop(); +} + +void TcpInfiniteListener::hangup() { + close_flag_ = true; + tcp_listener_.reset(); + if (refcnt_ == 0) { + stop(); + } +} + +void TcpInfiniteListener::loop() { + if (!tcp_listener_.empty()) { + return; + } + class Callback : public TcpListener::Callback { + public: + Callback(actor::ActorShared parent) : parent_(std::move(parent)) { + } + void accept(SocketFd fd) override { + actor::send_closure(parent_, &TcpInfiniteListener::accept, std::move(fd)); + } + + private: + actor::ActorShared parent_; + }; + refcnt_++; + tcp_listener_ = actor::create_actor( + actor::ActorOptions().with_name(PSLICE() << "TcpListener" << tag("port", port_)).with_poll(), port_, + std::make_unique(actor_shared(this))); +} + +void TcpInfiniteListener::accept(SocketFd fd) { + callback_->accept(std::move(fd)); +} + +void TcpInfiniteListener::hangup_shared() { + refcnt_--; + tcp_listener_.reset(); + if (close_flag_) { + if (refcnt_ == 0) { + stop(); + } + } else { + alarm_timestamp() = Timestamp::in(5 /*5 seconds*/); + } +} } // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.h b/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.h index bccf9e52f7..d83030eb0f 100644 --- a/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.h +++ b/submodules/ton/tonlib-src/tdnet/td/net/TcpListener.h @@ -49,4 +49,23 @@ class TcpListener : public td::actor::Actor, private td::ObserverBase { void loop() override; }; + +class TcpInfiniteListener : public actor::Actor { + public: + TcpInfiniteListener(int32 port, std::unique_ptr callback); + + private: + int32 port_; + std::unique_ptr callback_; + actor::ActorOwn tcp_listener_; + int32 refcnt_{0}; + bool close_flag_{false}; + + void start_up() override; + + void hangup() override; + void loop() override; + void accept(SocketFd fd); + void hangup_shared() override; +}; } // namespace td diff --git a/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.cpp b/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.cpp index 1a88d17f14..7dff5e761a 100644 --- a/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.cpp +++ b/submodules/ton/tonlib-src/tdnet/td/net/UdpServer.cpp @@ -130,70 +130,6 @@ void UdpServerImpl::hangup_shared() { stop(); } -class TcpInfiniteListener : public actor::Actor { - public: - TcpInfiniteListener(int32 port, std::unique_ptr callback) - : port_(port), callback_(std::move(callback)) { - } - - private: - int32 port_; - std::unique_ptr callback_; - actor::ActorOwn tcp_listener_; - int32 refcnt_{0}; - bool close_flag_{false}; - - void start_up() override { - loop(); - } - - void hangup() override { - close_flag_ = true; - tcp_listener_.reset(); - if (refcnt_ == 0) { - stop(); - } - } - - void loop() override { - if (!tcp_listener_.empty()) { - return; - } - class Callback : public TcpListener::Callback { - public: - Callback(actor::ActorShared parent) : parent_(std::move(parent)) { - } - void accept(SocketFd fd) override { - actor::send_closure(parent_, &TcpInfiniteListener::accept, std::move(fd)); - } - - private: - actor::ActorShared parent_; - }; - VLOG(udp_server) << "Create listener"; - refcnt_++; - tcp_listener_ = actor::create_actor( - actor::ActorOptions().with_name(PSLICE() << "TcpListener" << tag("port", port_)).with_poll(), port_, - std::make_unique(actor_shared(this))); - } - - void accept(SocketFd fd) { - callback_->accept(std::move(fd)); - } - - void hangup_shared() override { - refcnt_--; - tcp_listener_.reset(); - if (close_flag_) { - if (refcnt_ == 0) { - stop(); - } - } else { - alarm_timestamp() = Timestamp::in(5 /*5 seconds*/); - } - } -}; - class TcpClient : public td::actor::Actor, td::ObserverBase { public: class Callback { diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/CancellationToken.h b/submodules/ton/tonlib-src/tdutils/td/utils/CancellationToken.h index f3bca2fcde..08f413c4b4 100644 --- a/submodules/ton/tonlib-src/tdutils/td/utils/CancellationToken.h +++ b/submodules/ton/tonlib-src/tdutils/td/utils/CancellationToken.h @@ -32,8 +32,13 @@ struct RawCancellationToken { class CancellationToken { public: explicit operator bool() const { + // Empty CancellationToken is never cancelled + if (!token_) { + return false; + } return token_->is_cancelled_.load(std::memory_order_acquire); } + CancellationToken() = default; explicit CancellationToken(std::shared_ptr token) : token_(std::move(token)) { } diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/Status.h b/submodules/ton/tonlib-src/tdutils/td/utils/Status.h index 1759c0abef..6ac9210059 100644 --- a/submodules/ton/tonlib-src/tdutils/td/utils/Status.h +++ b/submodules/ton/tonlib-src/tdutils/td/utils/Status.h @@ -48,6 +48,15 @@ } \ } +#define TRY_STATUS_PROMISE(promise_name, status) \ + { \ + auto try_status = (status); \ + if (try_status.is_error()) { \ + promise_name.set_error(std::move(try_status)); \ + return; \ + } \ + } + #define TRY_RESULT(name, result) TRY_RESULT_IMPL(TD_CONCAT(TD_CONCAT(r_, name), __LINE__), auto name, result) #define TRY_RESULT_PROMISE(promise_name, name, result) \ @@ -309,6 +318,11 @@ class Status { return std::move(*this); } + Auto move_as_ok() { + UNREACHABLE(); + return {}; + } + Status move_as_error_prefix(const Status &status) const TD_WARN_UNUSED_RESULT { return status.move_as_error_suffix(message()); } diff --git a/submodules/ton/tonlib-src/tdutils/td/utils/tests.h b/submodules/ton/tonlib-src/tdutils/td/utils/tests.h index eb1fc3a82c..464fa0ea87 100644 --- a/submodules/ton/tonlib-src/tdutils/td/utils/tests.h +++ b/submodules/ton/tonlib-src/tdutils/td/utils/tests.h @@ -38,6 +38,34 @@ namespace td { +class RandomSteps { + public: + struct Step { + std::function func; + td::uint32 weight; + }; + RandomSteps(std::vector steps) : steps_(std::move(steps)) { + for (auto &step : steps_) { + steps_sum_ += step.weight; + } + } + template + void step(Random &rnd) { + auto w = rnd() % steps_sum_; + for (auto &step : steps_) { + if (w < step.weight) { + step.func(); + break; + } + w -= step.weight; + } + } + + private: + std::vector steps_; + td::int32 steps_sum_ = 0; +}; + class RegressionTester { public: virtual ~RegressionTester() = default; diff --git a/submodules/ton/tonlib-src/test/regression-tests.ans b/submodules/ton/tonlib-src/test/regression-tests.ans index ba4b51d503..29e26328dc 100644 --- a/submodules/ton/tonlib-src/test/regression-tests.ans +++ b/submodules/ton/tonlib-src/test/regression-tests.ans @@ -4,11 +4,16 @@ Test_Bitstrings_main_default a8b08af3116923c4c2a14e138d168375abd0c059f2f780d3267 Test_Cells_simple_default 832502642fe4fe5db70de82681aedb7d54d7f3530e0069861fff405fe6f6cf23 Test_Fift_bug_div_default 1ac42861ce96b2896001c587f65e9afe1617db48859f19c2f4e3063a20ea60b0 Test_Fift_bug_newlize_default e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +Test_Fift_bug_ufits_default 51bf5a9f1ed7633a193f6fdd17a7a3af8e032dfe72a9669c85e8639aa8a7c195 Test_Fift_contfrac_default 09ebce5c91bcb70696c6fb6981d82dc3b9e3444dab608a7a1b044c0ddd778a96 Test_Fift_test_default 4e44b3382963ec89f7b5c8f2ebd85da3bc8aebad5b49f5b11b14075061477b4d -Test_Fift_testvm2_default 4dcb0f98fd689cbdd81a3a1f937a497dd64d27ecebdcd67cf28fd6888469d93d +Test_Fift_test_dict_default 480d22a6ec25a232febf4eec8ff64747573f79721327e7ff3b1aa7ea4921bbb4 +Test_Fift_test_fixed_default 278a19d56b773102caf5c1fe2997ea6c8d0d9e720eff8503feede6398a197eec +Test_Fift_test_sort2_default 9b57d47e6a10e7d1bbb565db35400debf2f963031f434742a702ec76555a5d3a +Test_Fift_test_sort_default 9b57d47e6a10e7d1bbb565db35400debf2f963031f434742a702ec76555a5d3a +Test_Fift_testvm2_default 8a6e35fc0224398be9d2de39d31c86ea96965ef1eca2aa9e0af2303150ed4a7b Test_Fift_testvm3_default 3c1b77471c5fd914ed8b5f528b9faed618e278693f5030b953ff150e543864ae -Test_Fift_testvm4_default 4dcb0f98fd689cbdd81a3a1f937a497dd64d27ecebdcd67cf28fd6888469d93d +Test_Fift_testvm4_default 8a6e35fc0224398be9d2de39d31c86ea96965ef1eca2aa9e0af2303150ed4a7b Test_Fift_testvm4a_default 523b561d6bf2f5ebb26a755e687bfbda8e33462c98e9978119755f79a086cf5e Test_Fift_testvm4b_default daf8567bd58f05c10bb6596cea33b63e1061fa02dd5560db18ff22f96736f0d5 Test_Fift_testvm4c_default 2bbd67831d90bceaae29546ee3a58c4d376c2e8fb6a5b8ea2eae3ab8787e063e diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp index 810c29527e..5c8b605177 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.cpp @@ -178,6 +178,8 @@ object_ptr Object::fetch(td::TlParser &p) { return db_candidate::fetch(p); case db_block_info::ID: return db_block_info::fetch(p); + case db_block_packedInfo::ID: + return db_block_packedInfo::fetch(p); case db_block_archivedInfo::ID: return db_block_archivedInfo::fetch(p); case db_blockdb_key_lru::ID: @@ -4330,6 +4332,8 @@ object_ptr db_block_Info::fetch(td::TlParser &p) { switch (constructor) { case db_block_info::ID: return db_block_info::fetch(p); + case db_block_packedInfo::ID: + return db_block_packedInfo::fetch(p); case db_block_archivedInfo::ID: return db_block_archivedInfo::fetch(p); default: @@ -4427,6 +4431,56 @@ void db_block_info::store(td::TlStorerToString &s, const char *field_name) const } } +db_block_packedInfo::db_block_packedInfo() + : id_() + , unixtime_() + , offset_() +{} + +db_block_packedInfo::db_block_packedInfo(object_ptr &&id_, std::int32_t unixtime_, std::int64_t offset_) + : id_(std::move(id_)) + , unixtime_(unixtime_) + , offset_(offset_) +{} + +const std::int32_t db_block_packedInfo::ID; + +object_ptr db_block_packedInfo::fetch(td::TlParser &p) { + return make_object(p); +} + +db_block_packedInfo::db_block_packedInfo(td::TlParser &p) +#define FAIL(error) p.set_error(error) + : id_(TlFetchObject::parse(p)) + , unixtime_(TlFetchInt::parse(p)) + , offset_(TlFetchLong::parse(p)) +#undef FAIL +{} + +void db_block_packedInfo::store(td::TlStorerCalcLength &s) const { + (void)sizeof(s); + TlStoreObject::store(id_, s); + TlStoreBinary::store(unixtime_, s); + TlStoreBinary::store(offset_, s); +} + +void db_block_packedInfo::store(td::TlStorerUnsafe &s) const { + (void)sizeof(s); + TlStoreObject::store(id_, s); + TlStoreBinary::store(unixtime_, s); + TlStoreBinary::store(offset_, s); +} + +void db_block_packedInfo::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "db_block_packedInfo"); + if (id_ == nullptr) { s.store_field("id", "null"); } else { id_->store(s, "id"); } + s.store_field("unixtime", unixtime_); + s.store_field("offset", offset_); + s.store_class_end(); + } +} + db_block_archivedInfo::db_block_archivedInfo() : id_() , flags_() diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h index 3f3f8e8ad8..8bf7d8ff9b 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.h @@ -2382,6 +2382,32 @@ class db_block_info final : public db_block_Info { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class db_block_packedInfo final : public db_block_Info { + public: + object_ptr id_; + std::int32_t unixtime_; + std::int64_t offset_; + + db_block_packedInfo(); + + db_block_packedInfo(object_ptr &&id_, std::int32_t unixtime_, std::int64_t offset_); + + static const std::int32_t ID = 1186697618; + std::int32_t get_id() const final { + return ID; + } + + static object_ptr fetch(td::TlParser &p); + + explicit db_block_packedInfo(td::TlParser &p); + + void store(td::TlStorerCalcLength &s) const final; + + void store(td::TlStorerUnsafe &s) const final; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class db_block_archivedInfo final : public db_block_Info { public: object_ptr id_; diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp index 29f45bb527..9216c063dc 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api.hpp @@ -245,6 +245,9 @@ bool downcast_call(Object &obj, const T &func) { case db_block_info::ID: func(static_cast(obj)); return true; + case db_block_packedInfo::ID: + func(static_cast(obj)); + return true; case db_block_archivedInfo::ID: func(static_cast(obj)); return true; @@ -1340,6 +1343,9 @@ bool downcast_call(db_block_Info &obj, const T &func) { case db_block_info::ID: func(static_cast(obj)); return true; + case db_block_packedInfo::ID: + func(static_cast(obj)); + return true; case db_block_archivedInfo::ID: func(static_cast(obj)); return true; diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp index df0f134a1d..dde2c4fd45 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.cpp @@ -159,6 +159,7 @@ Result tl_constructor_from_string(ton_api::catchain_block_inner_Data *obj Result tl_constructor_from_string(ton_api::db_block_Info *object, const std::string &str) { static const std::unordered_map m = { {"db.block.info", 1254549287}, + {"db.block.packedInfo", 1186697618}, {"db.block.archivedInfo", 543128145} }; auto it = m.find(str); @@ -575,6 +576,7 @@ Result tl_constructor_from_string(ton_api::Object *object, const std::str {"control.config.local", 1964895469}, {"db.candidate", 1708747482}, {"db.block.info", 1254549287}, + {"db.block.packedInfo", 1186697618}, {"db.block.archivedInfo", 543128145}, {"db.blockdb.key.lru", 1354536506}, {"db.blockdb.key.value", 2136461683}, @@ -2116,6 +2118,27 @@ Status from_json(ton_api::db_block_info &to, JsonObject &from) { } return Status::OK(); } +Status from_json(ton_api::db_block_packedInfo &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.id_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "unixtime", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.unixtime_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "offset", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.offset_, value)); + } + } + return Status::OK(); +} Status from_json(ton_api::db_block_archivedInfo &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); @@ -6446,6 +6469,15 @@ void to_json(JsonValueScope &jv, const ton_api::db_block_info &object) { jo << ctie("ts", ToJson(object.ts_)); jo << ctie("state", ToJson(object.state_)); } +void to_json(JsonValueScope &jv, const ton_api::db_block_packedInfo &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "db.block.packedInfo"); + if (object.id_) { + jo << ctie("id", ToJson(object.id_)); + } + jo << ctie("unixtime", ToJson(object.unixtime_)); + jo << ctie("offset", ToJson(JsonInt64{object.offset_})); +} void to_json(JsonValueScope &jv, const ton_api::db_block_archivedInfo &object) { auto jo = jv.enter_object(); jo << ctie("@type", "db.block.archivedInfo"); diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h index da8fa1524d..b7fbcebbc5 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/ton_api_json.h @@ -128,6 +128,7 @@ Status from_json(ton_api::config_local &to, JsonObject &from); Status from_json(ton_api::control_config_local &to, JsonObject &from); Status from_json(ton_api::db_candidate &to, JsonObject &from); Status from_json(ton_api::db_block_info &to, JsonObject &from); +Status from_json(ton_api::db_block_packedInfo &to, JsonObject &from); Status from_json(ton_api::db_block_archivedInfo &to, JsonObject &from); Status from_json(ton_api::db_blockdb_key_lru &to, JsonObject &from); Status from_json(ton_api::db_blockdb_key_value &to, JsonObject &from); @@ -472,6 +473,7 @@ void to_json(JsonValueScope &jv, const ton_api::control_config_local &object); void to_json(JsonValueScope &jv, const ton_api::db_candidate &object); void to_json(JsonValueScope &jv, const ton_api::db_block_Info &object); void to_json(JsonValueScope &jv, const ton_api::db_block_info &object); +void to_json(JsonValueScope &jv, const ton_api::db_block_packedInfo &object); void to_json(JsonValueScope &jv, const ton_api::db_block_archivedInfo &object); void to_json(JsonValueScope &jv, const ton_api::db_blockdb_Key &object); void to_json(JsonValueScope &jv, const ton_api::db_blockdb_key_lru &object); diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp index 99ac12bb06..8e3b60dd62 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.cpp @@ -175,6 +175,33 @@ void exportedPemKey::store(td::TlStorerToString &s, const char *field_name) cons } } +fees::fees() + : in_fwd_fee_() + , storage_fee_() + , gas_fee_() + , fwd_fee_() +{} + +fees::fees(std::int64_t in_fwd_fee_, std::int64_t storage_fee_, std::int64_t gas_fee_, std::int64_t fwd_fee_) + : in_fwd_fee_(in_fwd_fee_) + , storage_fee_(storage_fee_) + , gas_fee_(gas_fee_) + , fwd_fee_(fwd_fee_) +{} + +const std::int32_t fees::ID; + +void fees::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "fees"); + s.store_field("in_fwd_fee", in_fwd_fee_); + s.store_field("storage_fee", storage_fee_); + s.store_field("gas_fee", gas_fee_); + s.store_field("fwd_fee", fwd_fee_); + s.store_class_end(); + } +} + inputKey::inputKey() : key_() , local_password_() @@ -196,6 +223,18 @@ void inputKey::store(td::TlStorerToString &s, const char *field_name) const { } } +inputKeyFake::inputKeyFake() { +} + +const std::int32_t inputKeyFake::ID; + +void inputKeyFake::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "inputKeyFake"); + s.store_class_end(); + } +} + key::key() : public_key_() , secret_() @@ -382,6 +421,42 @@ void sendGramsResult::store(td::TlStorerToString &s, const char *field_name) con } } +syncStateDone::syncStateDone() { +} + +const std::int32_t syncStateDone::ID; + +void syncStateDone::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "syncStateDone"); + s.store_class_end(); + } +} + +syncStateInProgress::syncStateInProgress() + : from_seqno_() + , to_seqno_() + , current_seqno_() +{} + +syncStateInProgress::syncStateInProgress(std::int32_t from_seqno_, std::int32_t to_seqno_, std::int32_t current_seqno_) + : from_seqno_(from_seqno_) + , to_seqno_(to_seqno_) + , current_seqno_(current_seqno_) +{} + +const std::int32_t syncStateInProgress::ID; + +void syncStateInProgress::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "syncStateInProgress"); + s.store_field("from_seqno", from_seqno_); + s.store_field("to_seqno", to_seqno_); + s.store_field("current_seqno", current_seqno_); + s.store_class_end(); + } +} + unpackedAccountAddress::unpackedAccountAddress() : workchain_id_() , bounceable_() @@ -430,6 +505,24 @@ void updateSendLiteServerQuery::store(td::TlStorerToString &s, const char *field } } +updateSyncState::updateSyncState() + : sync_state_() +{} + +updateSyncState::updateSyncState(object_ptr &&sync_state_) + : sync_state_(std::move(sync_state_)) +{} + +const std::int32_t updateSyncState::ID; + +void updateSyncState::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "updateSyncState"); + if (sync_state_ == nullptr) { s.store_field("sync_state", "null"); } else { sync_state_->store(s, "sync_state"); } + s.store_class_end(); + } +} + generic_accountStateRaw::generic_accountStateRaw() : account_state_() {} @@ -541,6 +634,75 @@ void internal_transactionId::store(td::TlStorerToString &s, const char *field_na } } +liteServer_info::liteServer_info() + : now_() + , version_() + , capabilities_() +{} + +liteServer_info::liteServer_info(std::int64_t now_, std::int32_t version_, std::int64_t capabilities_) + : now_(now_) + , version_(version_) + , capabilities_(capabilities_) +{} + +const std::int32_t liteServer_info::ID; + +void liteServer_info::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "liteServer_info"); + s.store_field("now", now_); + s.store_field("version", version_); + s.store_field("capabilities", capabilities_); + s.store_class_end(); + } +} + +query_fees::query_fees() + : source_fees_() + , destination_fees_() +{} + +query_fees::query_fees(object_ptr &&source_fees_, object_ptr &&destination_fees_) + : source_fees_(std::move(source_fees_)) + , destination_fees_(std::move(destination_fees_)) +{} + +const std::int32_t query_fees::ID; + +void query_fees::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "query_fees"); + if (source_fees_ == nullptr) { s.store_field("source_fees", "null"); } else { source_fees_->store(s, "source_fees"); } + if (destination_fees_ == nullptr) { s.store_field("destination_fees", "null"); } else { destination_fees_->store(s, "destination_fees"); } + s.store_class_end(); + } +} + +query_info::query_info() + : id_() + , valid_until_() + , body_hash_() +{} + +query_info::query_info(std::int64_t id_, std::int64_t valid_until_, std::string const &body_hash_) + : id_(id_) + , valid_until_(valid_until_) + , body_hash_(std::move(body_hash_)) +{} + +const std::int32_t query_info::ID; + +void query_info::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "query_info"); + s.store_field("id", id_); + s.store_field("valid_until", valid_until_); + s.store_bytes_field("body_hash", body_hash_); + s.store_class_end(); + } +} + raw_accountState::raw_accountState() : balance_() , code_() @@ -864,7 +1026,7 @@ changeLocalPassword::changeLocalPassword() , new_local_password_() {} -changeLocalPassword::changeLocalPassword(object_ptr &&input_key_, td::SecureString &&new_local_password_) +changeLocalPassword::changeLocalPassword(object_ptr &&input_key_, td::SecureString &&new_local_password_) : input_key_(std::move(input_key_)) , new_local_password_(std::move(new_local_password_)) {} @@ -993,7 +1155,7 @@ exportEncryptedKey::exportEncryptedKey() , key_password_() {} -exportEncryptedKey::exportEncryptedKey(object_ptr &&input_key_, td::SecureString &&key_password_) +exportEncryptedKey::exportEncryptedKey(object_ptr &&input_key_, td::SecureString &&key_password_) : input_key_(std::move(input_key_)) , key_password_(std::move(key_password_)) {} @@ -1013,7 +1175,7 @@ exportKey::exportKey() : input_key_() {} -exportKey::exportKey(object_ptr &&input_key_) +exportKey::exportKey(object_ptr &&input_key_) : input_key_(std::move(input_key_)) {} @@ -1032,7 +1194,7 @@ exportPemKey::exportPemKey() , key_password_() {} -exportPemKey::exportPemKey(object_ptr &&input_key_, td::SecureString &&key_password_) +exportPemKey::exportPemKey(object_ptr &&input_key_, td::SecureString &&key_password_) : input_key_(std::move(input_key_)) , key_password_(std::move(key_password_)) {} @@ -1048,6 +1210,42 @@ void exportPemKey::store(td::TlStorerToString &s, const char *field_name) const } } +generic_createSendGramsQuery::generic_createSendGramsQuery() + : private_key_() + , source_() + , destination_() + , amount_() + , timeout_() + , allow_send_to_uninited_() + , message_() +{} + +generic_createSendGramsQuery::generic_createSendGramsQuery(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::int32_t timeout_, bool allow_send_to_uninited_, std::string const &message_) + : private_key_(std::move(private_key_)) + , source_(std::move(source_)) + , destination_(std::move(destination_)) + , amount_(amount_) + , timeout_(timeout_) + , allow_send_to_uninited_(allow_send_to_uninited_) + , message_(std::move(message_)) +{} + +const std::int32_t generic_createSendGramsQuery::ID; + +void generic_createSendGramsQuery::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "generic_createSendGramsQuery"); + if (private_key_ == nullptr) { s.store_field("private_key", "null"); } else { private_key_->store(s, "private_key"); } + if (source_ == nullptr) { s.store_field("source", "null"); } else { source_->store(s, "source"); } + if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); } + s.store_field("amount", amount_); + s.store_field("timeout", timeout_); + s.store_field("allow_send_to_uninited", allow_send_to_uninited_); + s.store_bytes_field("message", message_); + s.store_class_end(); + } +} + generic_getAccountState::generic_getAccountState() : account_address_() {} @@ -1076,7 +1274,7 @@ generic_sendGrams::generic_sendGrams() , message_() {} -generic_sendGrams::generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::int32_t timeout_, bool allow_send_to_uninited_, std::string const &message_) +generic_sendGrams::generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::int32_t timeout_, bool allow_send_to_uninited_, std::string const &message_) : private_key_(std::move(private_key_)) , source_(std::move(source_)) , destination_(std::move(destination_)) @@ -1288,6 +1486,18 @@ void kdf::store(td::TlStorerToString &s, const char *field_name) const { } } +liteServer_getInfo::liteServer_getInfo() { +} + +const std::int32_t liteServer_getInfo::ID; + +void liteServer_getInfo::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "liteServer_getInfo"); + s.store_class_end(); + } +} + onLiteServerQueryError::onLiteServerQueryError() : id_() , error_() @@ -1366,6 +1576,132 @@ void packAccountAddress::store(td::TlStorerToString &s, const char *field_name) } } +query_estimateFees::query_estimateFees() + : id_() + , ignore_chksig_() +{} + +query_estimateFees::query_estimateFees(std::int64_t id_, bool ignore_chksig_) + : id_(id_) + , ignore_chksig_(ignore_chksig_) +{} + +const std::int32_t query_estimateFees::ID; + +void query_estimateFees::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "query_estimateFees"); + s.store_field("id", id_); + s.store_field("ignore_chksig", ignore_chksig_); + s.store_class_end(); + } +} + +query_forget::query_forget() + : id_() +{} + +query_forget::query_forget(std::int64_t id_) + : id_(id_) +{} + +const std::int32_t query_forget::ID; + +void query_forget::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "query_forget"); + s.store_field("id", id_); + s.store_class_end(); + } +} + +query_getInfo::query_getInfo() + : id_() +{} + +query_getInfo::query_getInfo(std::int64_t id_) + : id_(id_) +{} + +const std::int32_t query_getInfo::ID; + +void query_getInfo::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "query_getInfo"); + s.store_field("id", id_); + s.store_class_end(); + } +} + +query_send::query_send() + : id_() +{} + +query_send::query_send(std::int64_t id_) + : id_(id_) +{} + +const std::int32_t query_send::ID; + +void query_send::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "query_send"); + s.store_field("id", id_); + s.store_class_end(); + } +} + +raw_createAndSendMessage::raw_createAndSendMessage() + : destination_() + , initial_account_state_() + , data_() +{} + +raw_createAndSendMessage::raw_createAndSendMessage(object_ptr &&destination_, std::string const &initial_account_state_, std::string const &data_) + : destination_(std::move(destination_)) + , initial_account_state_(std::move(initial_account_state_)) + , data_(std::move(data_)) +{} + +const std::int32_t raw_createAndSendMessage::ID; + +void raw_createAndSendMessage::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "raw_createAndSendMessage"); + if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); } + s.store_bytes_field("initial_account_state", initial_account_state_); + s.store_bytes_field("data", data_); + s.store_class_end(); + } +} + +raw_createQuery::raw_createQuery() + : destination_() + , init_code_() + , init_data_() + , body_() +{} + +raw_createQuery::raw_createQuery(object_ptr &&destination_, std::string const &init_code_, std::string const &init_data_, std::string const &body_) + : destination_(std::move(destination_)) + , init_code_(std::move(init_code_)) + , init_data_(std::move(init_data_)) + , body_(std::move(body_)) +{} + +const std::int32_t raw_createQuery::ID; + +void raw_createQuery::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "raw_createQuery"); + if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); } + s.store_bytes_field("init_code", init_code_); + s.store_bytes_field("init_data", init_data_); + s.store_bytes_field("body", body_); + s.store_class_end(); + } +} + raw_getAccountAddress::raw_getAccountAddress() : initital_account_state_() {} @@ -1424,15 +1760,11 @@ void raw_getTransactions::store(td::TlStorerToString &s, const char *field_name) } raw_sendMessage::raw_sendMessage() - : destination_() - , initial_account_state_() - , data_() + : body_() {} -raw_sendMessage::raw_sendMessage(object_ptr &&destination_, std::string const &initial_account_state_, std::string const &data_) - : destination_(std::move(destination_)) - , initial_account_state_(std::move(initial_account_state_)) - , data_(std::move(data_)) +raw_sendMessage::raw_sendMessage(std::string const &body_) + : body_(std::move(body_)) {} const std::int32_t raw_sendMessage::ID; @@ -1440,9 +1772,7 @@ const std::int32_t raw_sendMessage::ID; void raw_sendMessage::store(td::TlStorerToString &s, const char *field_name) const { if (!LOG_IS_STRIPPED(ERROR)) { s.store_class_begin(field_name, "raw_sendMessage"); - if (destination_ == nullptr) { s.store_field("destination", "null"); } else { destination_->store(s, "destination"); } - s.store_bytes_field("initial_account_state", initial_account_state_); - s.store_bytes_field("data", data_); + s.store_bytes_field("body", body_); s.store_class_end(); } } @@ -1522,6 +1852,18 @@ void setLogVerbosityLevel::store(td::TlStorerToString &s, const char *field_name } } +sync::sync() { +} + +const std::int32_t sync::ID; + +void sync::store(td::TlStorerToString &s, const char *field_name) const { + if (!LOG_IS_STRIPPED(ERROR)) { + s.store_class_begin(field_name, "sync"); + s.store_class_end(); + } +} + testGiver_getAccountAddress::testGiver_getAccountAddress() { } @@ -1613,7 +1955,7 @@ testWallet_init::testWallet_init() : private_key_() {} -testWallet_init::testWallet_init(object_ptr &&private_key_) +testWallet_init::testWallet_init(object_ptr &&private_key_) : private_key_(std::move(private_key_)) {} @@ -1635,7 +1977,7 @@ testWallet_sendGrams::testWallet_sendGrams() , message_() {} -testWallet_sendGrams::testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_) +testWallet_sendGrams::testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_) : private_key_(std::move(private_key_)) , destination_(std::move(destination_)) , seqno_(seqno_) @@ -1715,7 +2057,7 @@ wallet_init::wallet_init() : private_key_() {} -wallet_init::wallet_init(object_ptr &&private_key_) +wallet_init::wallet_init(object_ptr &&private_key_) : private_key_(std::move(private_key_)) {} @@ -1738,7 +2080,7 @@ wallet_sendGrams::wallet_sendGrams() , message_() {} -wallet_sendGrams::wallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t valid_until_, std::int64_t amount_, std::string const &message_) +wallet_sendGrams::wallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t valid_until_, std::int64_t amount_, std::string const &message_) : private_key_(std::move(private_key_)) , destination_(std::move(destination_)) , seqno_(seqno_) diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h index a9f5430c73..e7862ec366 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.h @@ -60,7 +60,9 @@ class exportedKey; class exportedPemKey; -class inputKey; +class fees; + +class InputKey; class key; @@ -78,14 +80,22 @@ class options; class sendGramsResult; +class SyncState; + class unpackedAccountAddress; -class updateSendLiteServerQuery; +class Update; class generic_AccountState; class internal_transactionId; +class liteServer_info; + +class query_fees; + +class query_info; + class raw_accountState; class raw_initialAccountState; @@ -250,7 +260,30 @@ class exportedPemKey final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; -class inputKey final : public Object { +class fees final : public Object { + public: + std::int64_t in_fwd_fee_; + std::int64_t storage_fee_; + std::int64_t gas_fee_; + std::int64_t fwd_fee_; + + fees(); + + fees(std::int64_t in_fwd_fee_, std::int64_t storage_fee_, std::int64_t gas_fee_, std::int64_t fwd_fee_); + + static const std::int32_t ID = 1676273340; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class InputKey: public Object { + public: +}; + +class inputKey final : public InputKey { public: object_ptr key_; td::SecureString local_password_; @@ -267,6 +300,19 @@ class inputKey final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class inputKeyFake final : public InputKey { + public: + + inputKeyFake(); + + static const std::int32_t ID = -1074054722; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class key final : public Object { public: std::string public_key_; @@ -443,6 +489,41 @@ class sendGramsResult final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class SyncState: public Object { + public: +}; + +class syncStateDone final : public SyncState { + public: + + syncStateDone(); + + static const std::int32_t ID = 1408448777; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class syncStateInProgress final : public SyncState { + public: + std::int32_t from_seqno_; + std::int32_t to_seqno_; + std::int32_t current_seqno_; + + syncStateInProgress(); + + syncStateInProgress(std::int32_t from_seqno_, std::int32_t to_seqno_, std::int32_t current_seqno_); + + static const std::int32_t ID = 107726023; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class unpackedAccountAddress final : public Object { public: std::int32_t workchain_id_; @@ -462,7 +543,11 @@ class unpackedAccountAddress final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; -class updateSendLiteServerQuery final : public Object { +class Update: public Object { + public: +}; + +class updateSendLiteServerQuery final : public Update { public: std::int64_t id_; std::string data_; @@ -479,6 +564,22 @@ class updateSendLiteServerQuery final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class updateSyncState final : public Update { + public: + object_ptr sync_state_; + + updateSyncState(); + + explicit updateSyncState(object_ptr &&sync_state_); + + static const std::int32_t ID = 1204298718; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class generic_AccountState: public Object { public: }; @@ -580,6 +681,59 @@ class internal_transactionId final : public Object { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class liteServer_info final : public Object { + public: + std::int64_t now_; + std::int32_t version_; + std::int64_t capabilities_; + + liteServer_info(); + + liteServer_info(std::int64_t now_, std::int32_t version_, std::int64_t capabilities_); + + static const std::int32_t ID = -1250165133; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class query_fees final : public Object { + public: + object_ptr source_fees_; + object_ptr destination_fees_; + + query_fees(); + + query_fees(object_ptr &&source_fees_, object_ptr &&destination_fees_); + + static const std::int32_t ID = 725267759; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class query_info final : public Object { + public: + std::int64_t id_; + std::int64_t valid_until_; + std::string body_hash_; + + query_info(); + + query_info(std::int64_t id_, std::int64_t valid_until_, std::string const &body_hash_); + + static const std::int32_t ID = 1588635915; + std::int32_t get_id() const final { + return ID; + } + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class raw_accountState final : public Object { public: std::int64_t balance_; @@ -810,14 +964,14 @@ class addLogMessage final : public Function { class changeLocalPassword final : public Function { public: - object_ptr input_key_; + object_ptr input_key_; td::SecureString new_local_password_; changeLocalPassword(); - changeLocalPassword(object_ptr &&input_key_, td::SecureString &&new_local_password_); + changeLocalPassword(object_ptr &&input_key_, td::SecureString &&new_local_password_); - static const std::int32_t ID = -1685491421; + static const std::int32_t ID = -401590337; std::int32_t get_id() const final { return ID; } @@ -935,14 +1089,14 @@ class encrypt final : public Function { class exportEncryptedKey final : public Function { public: - object_ptr input_key_; + object_ptr input_key_; td::SecureString key_password_; exportEncryptedKey(); - exportEncryptedKey(object_ptr &&input_key_, td::SecureString &&key_password_); + exportEncryptedKey(object_ptr &&input_key_, td::SecureString &&key_password_); - static const std::int32_t ID = 155352861; + static const std::int32_t ID = 218237311; std::int32_t get_id() const final { return ID; } @@ -954,13 +1108,13 @@ class exportEncryptedKey final : public Function { class exportKey final : public Function { public: - object_ptr input_key_; + object_ptr input_key_; exportKey(); - explicit exportKey(object_ptr &&input_key_); + explicit exportKey(object_ptr &&input_key_); - static const std::int32_t ID = 399723440; + static const std::int32_t ID = -1622353549; std::int32_t get_id() const final { return ID; } @@ -972,14 +1126,14 @@ class exportKey final : public Function { class exportPemKey final : public Function { public: - object_ptr input_key_; + object_ptr input_key_; td::SecureString key_password_; exportPemKey(); - exportPemKey(object_ptr &&input_key_, td::SecureString &&key_password_); + exportPemKey(object_ptr &&input_key_, td::SecureString &&key_password_); - static const std::int32_t ID = -2047752448; + static const std::int32_t ID = -643259462; std::int32_t get_id() const final { return ID; } @@ -989,6 +1143,30 @@ class exportPemKey final : public Function { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class generic_createSendGramsQuery final : public Function { + public: + object_ptr private_key_; + object_ptr source_; + object_ptr destination_; + std::int64_t amount_; + std::int32_t timeout_; + bool allow_send_to_uninited_; + std::string message_; + + generic_createSendGramsQuery(); + + generic_createSendGramsQuery(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::int32_t timeout_, bool allow_send_to_uninited_, std::string const &message_); + + static const std::int32_t ID = 208206338; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class generic_getAccountState final : public Function { public: object_ptr account_address_; @@ -1009,7 +1187,7 @@ class generic_getAccountState final : public Function { class generic_sendGrams final : public Function { public: - object_ptr private_key_; + object_ptr private_key_; object_ptr source_; object_ptr destination_; std::int64_t amount_; @@ -1019,9 +1197,9 @@ class generic_sendGrams final : public Function { generic_sendGrams(); - generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::int32_t timeout_, bool allow_send_to_uninited_, std::string const &message_); + generic_sendGrams(object_ptr &&private_key_, object_ptr &&source_, object_ptr &&destination_, std::int64_t amount_, std::int32_t timeout_, bool allow_send_to_uninited_, std::string const &message_); - static const std::int32_t ID = -758801136; + static const std::int32_t ID = -553513162; std::int32_t get_id() const final { return ID; } @@ -1210,6 +1388,21 @@ class kdf final : public Function { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class liteServer_getInfo final : public Function { + public: + + liteServer_getInfo(); + + static const std::int32_t ID = 1435327470; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class onLiteServerQueryError final : public Function { public: std::int64_t id_; @@ -1284,6 +1477,120 @@ class packAccountAddress final : public Function { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class query_estimateFees final : public Function { + public: + std::int64_t id_; + bool ignore_chksig_; + + query_estimateFees(); + + query_estimateFees(std::int64_t id_, bool ignore_chksig_); + + static const std::int32_t ID = -957002175; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class query_forget final : public Function { + public: + std::int64_t id_; + + query_forget(); + + explicit query_forget(std::int64_t id_); + + static const std::int32_t ID = -1211985313; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class query_getInfo final : public Function { + public: + std::int64_t id_; + + query_getInfo(); + + explicit query_getInfo(std::int64_t id_); + + static const std::int32_t ID = -799333669; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class query_send final : public Function { + public: + std::int64_t id_; + + query_send(); + + explicit query_send(std::int64_t id_); + + static const std::int32_t ID = 925242739; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class raw_createAndSendMessage final : public Function { + public: + object_ptr destination_; + std::string initial_account_state_; + std::string data_; + + raw_createAndSendMessage(); + + raw_createAndSendMessage(object_ptr &&destination_, std::string const &initial_account_state_, std::string const &data_); + + static const std::int32_t ID = -772224603; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + +class raw_createQuery final : public Function { + public: + object_ptr destination_; + std::string init_code_; + std::string init_data_; + std::string body_; + + raw_createQuery(); + + raw_createQuery(object_ptr &&destination_, std::string const &init_code_, std::string const &init_data_, std::string const &body_); + + static const std::int32_t ID = -1928557909; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class raw_getAccountAddress final : public Function { public: object_ptr initital_account_state_; @@ -1341,15 +1648,13 @@ class raw_getTransactions final : public Function { class raw_sendMessage final : public Function { public: - object_ptr destination_; - std::string initial_account_state_; - std::string data_; + std::string body_; raw_sendMessage(); - raw_sendMessage(object_ptr &&destination_, std::string const &initial_account_state_, std::string const &data_); + explicit raw_sendMessage(std::string const &body_); - static const std::int32_t ID = 473889461; + static const std::int32_t ID = -1789427488; std::int32_t get_id() const final { return ID; } @@ -1432,6 +1737,21 @@ class setLogVerbosityLevel final : public Function { void store(td::TlStorerToString &s, const char *field_name) const final; }; +class sync final : public Function { + public: + + sync(); + + static const std::int32_t ID = -1617065525; + std::int32_t get_id() const final { + return ID; + } + + using ReturnType = object_ptr; + + void store(td::TlStorerToString &s, const char *field_name) const final; +}; + class testGiver_getAccountAddress final : public Function { public: @@ -1521,13 +1841,13 @@ class testWallet_getAccountState final : public Function { class testWallet_init final : public Function { public: - object_ptr private_key_; + object_ptr private_key_; testWallet_init(); - explicit testWallet_init(object_ptr &&private_key_); + explicit testWallet_init(object_ptr &&private_key_); - static const std::int32_t ID = 419055225; + static const std::int32_t ID = -1417409140; std::int32_t get_id() const final { return ID; } @@ -1539,7 +1859,7 @@ class testWallet_init final : public Function { class testWallet_sendGrams final : public Function { public: - object_ptr private_key_; + object_ptr private_key_; object_ptr destination_; std::int32_t seqno_; std::int64_t amount_; @@ -1547,9 +1867,9 @@ class testWallet_sendGrams final : public Function { testWallet_sendGrams(); - testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_); + testWallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t amount_, std::string const &message_); - static const std::int32_t ID = 1290131585; + static const std::int32_t ID = 573748322; std::int32_t get_id() const final { return ID; } @@ -1615,13 +1935,13 @@ class wallet_getAccountState final : public Function { class wallet_init final : public Function { public: - object_ptr private_key_; + object_ptr private_key_; wallet_init(); - explicit wallet_init(object_ptr &&private_key_); + explicit wallet_init(object_ptr &&private_key_); - static const std::int32_t ID = 1528056782; + static const std::int32_t ID = -395706309; std::int32_t get_id() const final { return ID; } @@ -1633,7 +1953,7 @@ class wallet_init final : public Function { class wallet_sendGrams final : public Function { public: - object_ptr private_key_; + object_ptr private_key_; object_ptr destination_; std::int32_t seqno_; std::int64_t valid_until_; @@ -1642,9 +1962,9 @@ class wallet_sendGrams final : public Function { wallet_sendGrams(); - wallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t valid_until_, std::int64_t amount_, std::string const &message_); + wallet_sendGrams(object_ptr &&private_key_, object_ptr &&destination_, std::int32_t seqno_, std::int64_t valid_until_, std::int64_t amount_, std::string const &message_); - static const std::int32_t ID = -1837893526; + static const std::int32_t ID = 297317621; std::int32_t get_id() const final { return ID; } diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp index 6ab06e09bc..bd5e0fad7e 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api.hpp @@ -38,9 +38,15 @@ bool downcast_call(Object &obj, const T &func) { case exportedPemKey::ID: func(static_cast(obj)); return true; + case fees::ID: + func(static_cast(obj)); + return true; case inputKey::ID: func(static_cast(obj)); return true; + case inputKeyFake::ID: + func(static_cast(obj)); + return true; case key::ID: func(static_cast(obj)); return true; @@ -74,12 +80,21 @@ bool downcast_call(Object &obj, const T &func) { case sendGramsResult::ID: func(static_cast(obj)); return true; + case syncStateDone::ID: + func(static_cast(obj)); + return true; + case syncStateInProgress::ID: + func(static_cast(obj)); + return true; case unpackedAccountAddress::ID: func(static_cast(obj)); return true; case updateSendLiteServerQuery::ID: func(static_cast(obj)); return true; + case updateSyncState::ID: + func(static_cast(obj)); + return true; case generic_accountStateRaw::ID: func(static_cast(obj)); return true; @@ -98,6 +113,15 @@ bool downcast_call(Object &obj, const T &func) { case internal_transactionId::ID: func(static_cast(obj)); return true; + case liteServer_info::ID: + func(static_cast(obj)); + return true; + case query_fees::ID: + func(static_cast(obj)); + return true; + case query_info::ID: + func(static_cast(obj)); + return true; case raw_accountState::ID: func(static_cast(obj)); return true; @@ -178,6 +202,9 @@ bool downcast_call(Function &obj, const T &func) { case exportPemKey::ID: func(static_cast(obj)); return true; + case generic_createSendGramsQuery::ID: + func(static_cast(obj)); + return true; case generic_getAccountState::ID: func(static_cast(obj)); return true; @@ -214,6 +241,9 @@ bool downcast_call(Function &obj, const T &func) { case kdf::ID: func(static_cast(obj)); return true; + case liteServer_getInfo::ID: + func(static_cast(obj)); + return true; case onLiteServerQueryError::ID: func(static_cast(obj)); return true; @@ -226,6 +256,24 @@ bool downcast_call(Function &obj, const T &func) { case packAccountAddress::ID: func(static_cast(obj)); return true; + case query_estimateFees::ID: + func(static_cast(obj)); + return true; + case query_forget::ID: + func(static_cast(obj)); + return true; + case query_getInfo::ID: + func(static_cast(obj)); + return true; + case query_send::ID: + func(static_cast(obj)); + return true; + case raw_createAndSendMessage::ID: + func(static_cast(obj)); + return true; + case raw_createQuery::ID: + func(static_cast(obj)); + return true; case raw_getAccountAddress::ID: func(static_cast(obj)); return true; @@ -250,6 +298,9 @@ bool downcast_call(Function &obj, const T &func) { case setLogVerbosityLevel::ID: func(static_cast(obj)); return true; + case sync::ID: + func(static_cast(obj)); + return true; case testGiver_getAccountAddress::ID: func(static_cast(obj)); return true; @@ -291,6 +342,26 @@ bool downcast_call(Function &obj, const T &func) { } } +/** + * Calls specified function object with the specified object downcasted to the most-derived type. + * \param[in] obj Object to pass as an argument to the function object. + * \param[in] func Function object to which the object will be passed. + * \returns whether function object call has happened. Should always return true for correct parameters. + */ +template +bool downcast_call(InputKey &obj, const T &func) { + switch (obj.get_id()) { + case inputKey::ID: + func(static_cast(obj)); + return true; + case inputKeyFake::ID: + func(static_cast(obj)); + return true; + default: + return false; + } +} + /** * Calls specified function object with the specified object downcasted to the most-derived type. * \param[in] obj Object to pass as an argument to the function object. @@ -334,6 +405,46 @@ bool downcast_call(LogStream &obj, const T &func) { } } +/** + * Calls specified function object with the specified object downcasted to the most-derived type. + * \param[in] obj Object to pass as an argument to the function object. + * \param[in] func Function object to which the object will be passed. + * \returns whether function object call has happened. Should always return true for correct parameters. + */ +template +bool downcast_call(SyncState &obj, const T &func) { + switch (obj.get_id()) { + case syncStateDone::ID: + func(static_cast(obj)); + return true; + case syncStateInProgress::ID: + func(static_cast(obj)); + return true; + default: + return false; + } +} + +/** + * Calls specified function object with the specified object downcasted to the most-derived type. + * \param[in] obj Object to pass as an argument to the function object. + * \param[in] func Function object to which the object will be passed. + * \returns whether function object call has happened. Should always return true for correct parameters. + */ +template +bool downcast_call(Update &obj, const T &func) { + switch (obj.get_id()) { + case updateSendLiteServerQuery::ID: + func(static_cast(obj)); + return true; + case updateSyncState::ID: + func(static_cast(obj)); + return true; + default: + return false; + } +} + /** * Calls specified function object with the specified object downcasted to the most-derived type. * \param[in] obj Object to pass as an argument to the function object. diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp index 4a891190db..a0448c9d68 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.cpp @@ -14,6 +14,17 @@ namespace ton { namespace tonlib_api{ using namespace td; +Result tl_constructor_from_string(tonlib_api::InputKey *object, const std::string &str) { + static const std::unordered_map m = { + {"inputKey", 869287093}, + {"inputKeyFake", -1074054722} + }; + auto it = m.find(str); + if (it == m.end()) { + return Status::Error(str + "Unknown class"); + } + return it->second; +} Result tl_constructor_from_string(tonlib_api::KeyStoreType *object, const std::string &str) { static const std::unordered_map m = { {"keyStoreTypeDirectory", -378990038}, @@ -37,6 +48,28 @@ Result tl_constructor_from_string(tonlib_api::LogStream *object, const st } return it->second; } +Result tl_constructor_from_string(tonlib_api::SyncState *object, const std::string &str) { + static const std::unordered_map m = { + {"syncStateDone", 1408448777}, + {"syncStateInProgress", 107726023} + }; + auto it = m.find(str); + if (it == m.end()) { + return Status::Error(str + "Unknown class"); + } + return it->second; +} +Result tl_constructor_from_string(tonlib_api::Update *object, const std::string &str) { + static const std::unordered_map m = { + {"updateSendLiteServerQuery", -1555130916}, + {"updateSyncState", 1204298718} + }; + auto it = m.find(str); + if (it == m.end()) { + return Status::Error(str + "Unknown class"); + } + return it->second; +} Result tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str) { static const std::unordered_map m = { {"generic.accountStateRaw", -1387096685}, @@ -61,7 +94,9 @@ Result tl_constructor_from_string(tonlib_api::Object *object, const std:: {"exportedEncryptedKey", 2024406612}, {"exportedKey", -1449248297}, {"exportedPemKey", 1425473725}, + {"fees", 1676273340}, {"inputKey", 869287093}, + {"inputKeyFake", -1074054722}, {"key", -1978362923}, {"keyStoreTypeDirectory", -378990038}, {"keyStoreTypeInMemory", -2106848825}, @@ -73,14 +108,20 @@ Result tl_constructor_from_string(tonlib_api::Object *object, const std:: {"ok", -722616727}, {"options", -1924388359}, {"sendGramsResult", 426872238}, + {"syncStateDone", 1408448777}, + {"syncStateInProgress", 107726023}, {"unpackedAccountAddress", 1892946998}, {"updateSendLiteServerQuery", -1555130916}, + {"updateSyncState", 1204298718}, {"generic.accountStateRaw", -1387096685}, {"generic.accountStateTestWallet", -1041955397}, {"generic.accountStateWallet", 942582925}, {"generic.accountStateTestGiver", 1134654598}, {"generic.accountStateUninited", -908702008}, {"internal.transactionId", -989527262}, + {"liteServer.info", -1250165133}, + {"query.fees", 725267759}, + {"query.info", 1588635915}, {"raw.accountState", 1205935434}, {"raw.initialAccountState", 777456197}, {"raw.message", -906281442}, @@ -102,18 +143,19 @@ Result tl_constructor_from_string(tonlib_api::Object *object, const std:: Result tl_constructor_from_string(tonlib_api::Function *object, const std::string &str) { static const std::unordered_map m = { {"addLogMessage", 1597427692}, - {"changeLocalPassword", -1685491421}, + {"changeLocalPassword", -401590337}, {"close", -1187782273}, {"createNewKey", -1861385712}, {"decrypt", 357991854}, {"deleteAllKeys", 1608776483}, {"deleteKey", -1579595571}, {"encrypt", -1821422820}, - {"exportEncryptedKey", 155352861}, - {"exportKey", 399723440}, - {"exportPemKey", -2047752448}, + {"exportEncryptedKey", 218237311}, + {"exportKey", -1622353549}, + {"exportPemKey", -643259462}, + {"generic.createSendGramsQuery", 208206338}, {"generic.getAccountState", -657000446}, - {"generic.sendGrams", -758801136}, + {"generic.sendGrams", -553513162}, {"getBip39Hints", -1889640982}, {"getLogStream", 1167608667}, {"getLogTagVerbosityLevel", 951004547}, @@ -124,30 +166,38 @@ Result tl_constructor_from_string(tonlib_api::Function *object, const std {"importPemKey", 76385617}, {"init", -2014661877}, {"kdf", -1667861635}, + {"liteServer.getInfo", 1435327470}, {"onLiteServerQueryError", -677427533}, {"onLiteServerQueryResult", 2056444510}, {"options.setConfig", 646497241}, {"packAccountAddress", -1388561940}, + {"query.estimateFees", -957002175}, + {"query.forget", -1211985313}, + {"query.getInfo", -799333669}, + {"query.send", 925242739}, + {"raw.createAndSendMessage", -772224603}, + {"raw.createQuery", -1928557909}, {"raw.getAccountAddress", -521283849}, {"raw.getAccountState", 663706721}, {"raw.getTransactions", 935377269}, - {"raw.sendMessage", 473889461}, + {"raw.sendMessage", -1789427488}, {"runTests", -2039925427}, {"setLogStream", -1364199535}, {"setLogTagVerbosityLevel", -2095589738}, {"setLogVerbosityLevel", -303429678}, + {"sync", -1617065525}, {"testGiver.getAccountAddress", -540100768}, {"testGiver.getAccountState", 267738275}, {"testGiver.sendGrams", -1785750375}, {"testWallet.getAccountAddress", -1557748223}, {"testWallet.getAccountState", 654082364}, - {"testWallet.init", 419055225}, - {"testWallet.sendGrams", 1290131585}, + {"testWallet.init", -1417409140}, + {"testWallet.sendGrams", 573748322}, {"unpackAccountAddress", -682459063}, {"wallet.getAccountAddress", -1004103180}, {"wallet.getAccountState", 462294850}, - {"wallet.init", 1528056782}, - {"wallet.sendGrams", -1837893526} + {"wallet.init", -395706309}, + {"wallet.sendGrams", 297317621} }; auto it = m.find(str); if (it == m.end()) { @@ -251,6 +301,33 @@ Status from_json(tonlib_api::exportedPemKey &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::fees &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "in_fwd_fee", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.in_fwd_fee_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "storage_fee", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.storage_fee_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "gas_fee", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.gas_fee_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "fwd_fee", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.fwd_fee_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::inputKey &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "key", JsonValue::Type::Null, true)); @@ -266,6 +343,9 @@ Status from_json(tonlib_api::inputKey &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::inputKeyFake &to, JsonObject &from) { + return Status::OK(); +} Status from_json(tonlib_api::key &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "public_key", JsonValue::Type::Null, true)); @@ -365,6 +445,30 @@ Status from_json(tonlib_api::sendGramsResult &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::syncStateDone &to, JsonObject &from) { + return Status::OK(); +} +Status from_json(tonlib_api::syncStateInProgress &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "from_seqno", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.from_seqno_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "to_seqno", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.to_seqno_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "current_seqno", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.current_seqno_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::unpackedAccountAddress &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "workchain_id", JsonValue::Type::Null, true)); @@ -407,6 +511,15 @@ Status from_json(tonlib_api::updateSendLiteServerQuery &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::updateSyncState &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "sync_state", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.sync_state_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::generic_accountStateRaw &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "account_state", JsonValue::Type::Null, true)); @@ -467,6 +580,63 @@ Status from_json(tonlib_api::internal_transactionId &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::liteServer_info &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "now", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.now_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "version", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.version_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "capabilities", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.capabilities_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::query_fees &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "source_fees", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.source_fees_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "destination_fees", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.destination_fees_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::query_info &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.id_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "valid_until", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.valid_until_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "body_hash", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.body_hash_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::raw_accountState &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "balance", JsonValue::Type::Null, true)); @@ -899,6 +1069,51 @@ Status from_json(tonlib_api::exportPemKey &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::generic_createSendGramsQuery &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "private_key", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.private_key_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "source", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.source_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "destination", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.destination_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "amount", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.amount_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "timeout", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.timeout_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "allow_send_to_uninited", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.allow_send_to_uninited_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "message", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.message_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::generic_getAccountState &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "account_address", JsonValue::Type::Null, true)); @@ -1073,6 +1288,9 @@ Status from_json(tonlib_api::kdf &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::liteServer_getInfo &to, JsonObject &from) { + return Status::OK(); +} Status from_json(tonlib_api::onLiteServerQueryError &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); @@ -1121,6 +1339,96 @@ Status from_json(tonlib_api::packAccountAddress &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::query_estimateFees &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.id_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "ignore_chksig", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.ignore_chksig_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::query_forget &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.id_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::query_getInfo &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.id_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::query_send &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "id", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.id_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::raw_createAndSendMessage &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "destination", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.destination_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "initial_account_state", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.initial_account_state_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "data", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.data_, value)); + } + } + return Status::OK(); +} +Status from_json(tonlib_api::raw_createQuery &to, JsonObject &from) { + { + TRY_RESULT(value, get_json_object_field(from, "destination", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json(to.destination_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "init_code", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.init_code_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "init_data", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.init_data_, value)); + } + } + { + TRY_RESULT(value, get_json_object_field(from, "body", JsonValue::Type::Null, true)); + if (value.type() != JsonValue::Type::Null) { + TRY_STATUS(from_json_bytes(to.body_, value)); + } + } + return Status::OK(); +} Status from_json(tonlib_api::raw_getAccountAddress &to, JsonObject &from) { { TRY_RESULT(value, get_json_object_field(from, "initital_account_state", JsonValue::Type::Null, true)); @@ -1156,21 +1464,9 @@ Status from_json(tonlib_api::raw_getTransactions &to, JsonObject &from) { } Status from_json(tonlib_api::raw_sendMessage &to, JsonObject &from) { { - TRY_RESULT(value, get_json_object_field(from, "destination", JsonValue::Type::Null, true)); + TRY_RESULT(value, get_json_object_field(from, "body", JsonValue::Type::Null, true)); if (value.type() != JsonValue::Type::Null) { - TRY_STATUS(from_json(to.destination_, value)); - } - } - { - TRY_RESULT(value, get_json_object_field(from, "initial_account_state", JsonValue::Type::Null, true)); - if (value.type() != JsonValue::Type::Null) { - TRY_STATUS(from_json_bytes(to.initial_account_state_, value)); - } - } - { - TRY_RESULT(value, get_json_object_field(from, "data", JsonValue::Type::Null, true)); - if (value.type() != JsonValue::Type::Null) { - TRY_STATUS(from_json_bytes(to.data_, value)); + TRY_STATUS(from_json_bytes(to.body_, value)); } } return Status::OK(); @@ -1217,6 +1513,9 @@ Status from_json(tonlib_api::setLogVerbosityLevel &to, JsonObject &from) { } return Status::OK(); } +Status from_json(tonlib_api::sync &to, JsonObject &from) { + return Status::OK(); +} Status from_json(tonlib_api::testGiver_getAccountAddress &to, JsonObject &from) { return Status::OK(); } @@ -1429,6 +1728,17 @@ void to_json(JsonValueScope &jv, const tonlib_api::exportedPemKey &object) { jo << ctie("@type", "exportedPemKey"); jo << ctie("pem", ToJson(object.pem_)); } +void to_json(JsonValueScope &jv, const tonlib_api::fees &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "fees"); + jo << ctie("in_fwd_fee", ToJson(object.in_fwd_fee_)); + jo << ctie("storage_fee", ToJson(object.storage_fee_)); + jo << ctie("gas_fee", ToJson(object.gas_fee_)); + jo << ctie("fwd_fee", ToJson(object.fwd_fee_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::InputKey &object) { + tonlib_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); +} void to_json(JsonValueScope &jv, const tonlib_api::inputKey &object) { auto jo = jv.enter_object(); jo << ctie("@type", "inputKey"); @@ -1437,6 +1747,10 @@ void to_json(JsonValueScope &jv, const tonlib_api::inputKey &object) { } jo << ctie("local_password", ToJson(JsonBytes{object.local_password_})); } +void to_json(JsonValueScope &jv, const tonlib_api::inputKeyFake &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "inputKeyFake"); +} void to_json(JsonValueScope &jv, const tonlib_api::key &object) { auto jo = jv.enter_object(); jo << ctie("@type", "key"); @@ -1502,6 +1816,20 @@ void to_json(JsonValueScope &jv, const tonlib_api::sendGramsResult &object) { jo << ctie("sent_until", ToJson(object.sent_until_)); jo << ctie("body_hash", ToJson(JsonBytes{object.body_hash_})); } +void to_json(JsonValueScope &jv, const tonlib_api::SyncState &object) { + tonlib_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); +} +void to_json(JsonValueScope &jv, const tonlib_api::syncStateDone &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "syncStateDone"); +} +void to_json(JsonValueScope &jv, const tonlib_api::syncStateInProgress &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "syncStateInProgress"); + jo << ctie("from_seqno", ToJson(object.from_seqno_)); + jo << ctie("to_seqno", ToJson(object.to_seqno_)); + jo << ctie("current_seqno", ToJson(object.current_seqno_)); +} void to_json(JsonValueScope &jv, const tonlib_api::unpackedAccountAddress &object) { auto jo = jv.enter_object(); jo << ctie("@type", "unpackedAccountAddress"); @@ -1510,12 +1838,22 @@ void to_json(JsonValueScope &jv, const tonlib_api::unpackedAccountAddress &objec jo << ctie("testnet", ToJson(object.testnet_)); jo << ctie("addr", ToJson(JsonBytes{object.addr_})); } +void to_json(JsonValueScope &jv, const tonlib_api::Update &object) { + tonlib_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); +} void to_json(JsonValueScope &jv, const tonlib_api::updateSendLiteServerQuery &object) { auto jo = jv.enter_object(); jo << ctie("@type", "updateSendLiteServerQuery"); jo << ctie("id", ToJson(JsonInt64{object.id_})); jo << ctie("data", ToJson(JsonBytes{object.data_})); } +void to_json(JsonValueScope &jv, const tonlib_api::updateSyncState &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "updateSyncState"); + if (object.sync_state_) { + jo << ctie("sync_state", ToJson(object.sync_state_)); + } +} void to_json(JsonValueScope &jv, const tonlib_api::generic_AccountState &object) { tonlib_api::downcast_call(const_cast(object), [&jv](const auto &object) { to_json(jv, object); }); } @@ -1560,6 +1898,30 @@ void to_json(JsonValueScope &jv, const tonlib_api::internal_transactionId &objec jo << ctie("lt", ToJson(JsonInt64{object.lt_})); jo << ctie("hash", ToJson(JsonBytes{object.hash_})); } +void to_json(JsonValueScope &jv, const tonlib_api::liteServer_info &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "liteServer.info"); + jo << ctie("now", ToJson(object.now_)); + jo << ctie("version", ToJson(object.version_)); + jo << ctie("capabilities", ToJson(JsonInt64{object.capabilities_})); +} +void to_json(JsonValueScope &jv, const tonlib_api::query_fees &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "query.fees"); + if (object.source_fees_) { + jo << ctie("source_fees", ToJson(object.source_fees_)); + } + if (object.destination_fees_) { + jo << ctie("destination_fees", ToJson(object.destination_fees_)); + } +} +void to_json(JsonValueScope &jv, const tonlib_api::query_info &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "query.info"); + jo << ctie("id", ToJson(object.id_)); + jo << ctie("valid_until", ToJson(object.valid_until_)); + jo << ctie("body_hash", ToJson(JsonBytes{object.body_hash_})); +} void to_json(JsonValueScope &jv, const tonlib_api::raw_accountState &object) { auto jo = jv.enter_object(); jo << ctie("@type", "raw.accountState"); @@ -1735,6 +2097,23 @@ void to_json(JsonValueScope &jv, const tonlib_api::exportPemKey &object) { } jo << ctie("key_password", ToJson(JsonBytes{object.key_password_})); } +void to_json(JsonValueScope &jv, const tonlib_api::generic_createSendGramsQuery &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "generic.createSendGramsQuery"); + if (object.private_key_) { + jo << ctie("private_key", ToJson(object.private_key_)); + } + if (object.source_) { + jo << ctie("source", ToJson(object.source_)); + } + if (object.destination_) { + jo << ctie("destination", ToJson(object.destination_)); + } + jo << ctie("amount", ToJson(JsonInt64{object.amount_})); + jo << ctie("timeout", ToJson(object.timeout_)); + jo << ctie("allow_send_to_uninited", ToJson(object.allow_send_to_uninited_)); + jo << ctie("message", ToJson(JsonBytes{object.message_})); +} void to_json(JsonValueScope &jv, const tonlib_api::generic_getAccountState &object) { auto jo = jv.enter_object(); jo << ctie("@type", "generic.getAccountState"); @@ -1822,6 +2201,10 @@ void to_json(JsonValueScope &jv, const tonlib_api::kdf &object) { jo << ctie("salt", ToJson(JsonBytes{object.salt_})); jo << ctie("iterations", ToJson(object.iterations_)); } +void to_json(JsonValueScope &jv, const tonlib_api::liteServer_getInfo &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "liteServer.getInfo"); +} void to_json(JsonValueScope &jv, const tonlib_api::onLiteServerQueryError &object) { auto jo = jv.enter_object(); jo << ctie("@type", "onLiteServerQueryError"); @@ -1850,6 +2233,46 @@ void to_json(JsonValueScope &jv, const tonlib_api::packAccountAddress &object) { jo << ctie("account_address", ToJson(object.account_address_)); } } +void to_json(JsonValueScope &jv, const tonlib_api::query_estimateFees &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "query.estimateFees"); + jo << ctie("id", ToJson(object.id_)); + jo << ctie("ignore_chksig", ToJson(object.ignore_chksig_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::query_forget &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "query.forget"); + jo << ctie("id", ToJson(object.id_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::query_getInfo &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "query.getInfo"); + jo << ctie("id", ToJson(object.id_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::query_send &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "query.send"); + jo << ctie("id", ToJson(object.id_)); +} +void to_json(JsonValueScope &jv, const tonlib_api::raw_createAndSendMessage &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "raw.createAndSendMessage"); + if (object.destination_) { + jo << ctie("destination", ToJson(object.destination_)); + } + jo << ctie("initial_account_state", ToJson(JsonBytes{object.initial_account_state_})); + jo << ctie("data", ToJson(JsonBytes{object.data_})); +} +void to_json(JsonValueScope &jv, const tonlib_api::raw_createQuery &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "raw.createQuery"); + if (object.destination_) { + jo << ctie("destination", ToJson(object.destination_)); + } + jo << ctie("init_code", ToJson(JsonBytes{object.init_code_})); + jo << ctie("init_data", ToJson(JsonBytes{object.init_data_})); + jo << ctie("body", ToJson(JsonBytes{object.body_})); +} void to_json(JsonValueScope &jv, const tonlib_api::raw_getAccountAddress &object) { auto jo = jv.enter_object(); jo << ctie("@type", "raw.getAccountAddress"); @@ -1877,11 +2300,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::raw_getTransactions &object) void to_json(JsonValueScope &jv, const tonlib_api::raw_sendMessage &object) { auto jo = jv.enter_object(); jo << ctie("@type", "raw.sendMessage"); - if (object.destination_) { - jo << ctie("destination", ToJson(object.destination_)); - } - jo << ctie("initial_account_state", ToJson(JsonBytes{object.initial_account_state_})); - jo << ctie("data", ToJson(JsonBytes{object.data_})); + jo << ctie("body", ToJson(JsonBytes{object.body_})); } void to_json(JsonValueScope &jv, const tonlib_api::runTests &object) { auto jo = jv.enter_object(); @@ -1906,6 +2325,10 @@ void to_json(JsonValueScope &jv, const tonlib_api::setLogVerbosityLevel &object) jo << ctie("@type", "setLogVerbosityLevel"); jo << ctie("new_verbosity_level", ToJson(object.new_verbosity_level_)); } +void to_json(JsonValueScope &jv, const tonlib_api::sync &object) { + auto jo = jv.enter_object(); + jo << ctie("@type", "sync"); +} void to_json(JsonValueScope &jv, const tonlib_api::testGiver_getAccountAddress &object) { auto jo = jv.enter_object(); jo << ctie("@type", "testGiver.getAccountAddress"); diff --git a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h index 2341004613..5eea809726 100644 --- a/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h +++ b/submodules/ton/tonlib-src/tl/generate/auto/tl/tonlib_api_json.h @@ -11,8 +11,11 @@ namespace ton { namespace tonlib_api{ using namespace td; +Result tl_constructor_from_string(tonlib_api::InputKey *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::KeyStoreType *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::LogStream *object, const std::string &str); +Result tl_constructor_from_string(tonlib_api::SyncState *object, const std::string &str); +Result tl_constructor_from_string(tonlib_api::Update *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::Object *object, const std::string &str); Result tl_constructor_from_string(tonlib_api::Function *object, const std::string &str); @@ -24,7 +27,9 @@ Status from_json(tonlib_api::error &to, JsonObject &from); Status from_json(tonlib_api::exportedEncryptedKey &to, JsonObject &from); Status from_json(tonlib_api::exportedKey &to, JsonObject &from); Status from_json(tonlib_api::exportedPemKey &to, JsonObject &from); +Status from_json(tonlib_api::fees &to, JsonObject &from); Status from_json(tonlib_api::inputKey &to, JsonObject &from); +Status from_json(tonlib_api::inputKeyFake &to, JsonObject &from); Status from_json(tonlib_api::key &to, JsonObject &from); Status from_json(tonlib_api::keyStoreTypeDirectory &to, JsonObject &from); Status from_json(tonlib_api::keyStoreTypeInMemory &to, JsonObject &from); @@ -36,14 +41,20 @@ Status from_json(tonlib_api::logVerbosityLevel &to, JsonObject &from); Status from_json(tonlib_api::ok &to, JsonObject &from); Status from_json(tonlib_api::options &to, JsonObject &from); Status from_json(tonlib_api::sendGramsResult &to, JsonObject &from); +Status from_json(tonlib_api::syncStateDone &to, JsonObject &from); +Status from_json(tonlib_api::syncStateInProgress &to, JsonObject &from); Status from_json(tonlib_api::unpackedAccountAddress &to, JsonObject &from); Status from_json(tonlib_api::updateSendLiteServerQuery &to, JsonObject &from); +Status from_json(tonlib_api::updateSyncState &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateRaw &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateTestWallet &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateWallet &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateTestGiver &to, JsonObject &from); Status from_json(tonlib_api::generic_accountStateUninited &to, JsonObject &from); Status from_json(tonlib_api::internal_transactionId &to, JsonObject &from); +Status from_json(tonlib_api::liteServer_info &to, JsonObject &from); +Status from_json(tonlib_api::query_fees &to, JsonObject &from); +Status from_json(tonlib_api::query_info &to, JsonObject &from); Status from_json(tonlib_api::raw_accountState &to, JsonObject &from); Status from_json(tonlib_api::raw_initialAccountState &to, JsonObject &from); Status from_json(tonlib_api::raw_message &to, JsonObject &from); @@ -66,6 +77,7 @@ Status from_json(tonlib_api::encrypt &to, JsonObject &from); Status from_json(tonlib_api::exportEncryptedKey &to, JsonObject &from); Status from_json(tonlib_api::exportKey &to, JsonObject &from); Status from_json(tonlib_api::exportPemKey &to, JsonObject &from); +Status from_json(tonlib_api::generic_createSendGramsQuery &to, JsonObject &from); Status from_json(tonlib_api::generic_getAccountState &to, JsonObject &from); Status from_json(tonlib_api::generic_sendGrams &to, JsonObject &from); Status from_json(tonlib_api::getBip39Hints &to, JsonObject &from); @@ -78,10 +90,17 @@ Status from_json(tonlib_api::importKey &to, JsonObject &from); Status from_json(tonlib_api::importPemKey &to, JsonObject &from); Status from_json(tonlib_api::init &to, JsonObject &from); Status from_json(tonlib_api::kdf &to, JsonObject &from); +Status from_json(tonlib_api::liteServer_getInfo &to, JsonObject &from); Status from_json(tonlib_api::onLiteServerQueryError &to, JsonObject &from); Status from_json(tonlib_api::onLiteServerQueryResult &to, JsonObject &from); Status from_json(tonlib_api::options_setConfig &to, JsonObject &from); Status from_json(tonlib_api::packAccountAddress &to, JsonObject &from); +Status from_json(tonlib_api::query_estimateFees &to, JsonObject &from); +Status from_json(tonlib_api::query_forget &to, JsonObject &from); +Status from_json(tonlib_api::query_getInfo &to, JsonObject &from); +Status from_json(tonlib_api::query_send &to, JsonObject &from); +Status from_json(tonlib_api::raw_createAndSendMessage &to, JsonObject &from); +Status from_json(tonlib_api::raw_createQuery &to, JsonObject &from); Status from_json(tonlib_api::raw_getAccountAddress &to, JsonObject &from); Status from_json(tonlib_api::raw_getAccountState &to, JsonObject &from); Status from_json(tonlib_api::raw_getTransactions &to, JsonObject &from); @@ -90,6 +109,7 @@ Status from_json(tonlib_api::runTests &to, JsonObject &from); Status from_json(tonlib_api::setLogStream &to, JsonObject &from); Status from_json(tonlib_api::setLogTagVerbosityLevel &to, JsonObject &from); Status from_json(tonlib_api::setLogVerbosityLevel &to, JsonObject &from); +Status from_json(tonlib_api::sync &to, JsonObject &from); Status from_json(tonlib_api::testGiver_getAccountAddress &to, JsonObject &from); Status from_json(tonlib_api::testGiver_getAccountState &to, JsonObject &from); Status from_json(tonlib_api::testGiver_sendGrams &to, JsonObject &from); @@ -110,7 +130,10 @@ void to_json(JsonValueScope &jv, const tonlib_api::error &object); void to_json(JsonValueScope &jv, const tonlib_api::exportedEncryptedKey &object); void to_json(JsonValueScope &jv, const tonlib_api::exportedKey &object); void to_json(JsonValueScope &jv, const tonlib_api::exportedPemKey &object); +void to_json(JsonValueScope &jv, const tonlib_api::fees &object); +void to_json(JsonValueScope &jv, const tonlib_api::InputKey &object); void to_json(JsonValueScope &jv, const tonlib_api::inputKey &object); +void to_json(JsonValueScope &jv, const tonlib_api::inputKeyFake &object); void to_json(JsonValueScope &jv, const tonlib_api::key &object); void to_json(JsonValueScope &jv, const tonlib_api::KeyStoreType &object); void to_json(JsonValueScope &jv, const tonlib_api::keyStoreTypeDirectory &object); @@ -124,8 +147,13 @@ void to_json(JsonValueScope &jv, const tonlib_api::logVerbosityLevel &object); void to_json(JsonValueScope &jv, const tonlib_api::ok &object); void to_json(JsonValueScope &jv, const tonlib_api::options &object); void to_json(JsonValueScope &jv, const tonlib_api::sendGramsResult &object); +void to_json(JsonValueScope &jv, const tonlib_api::SyncState &object); +void to_json(JsonValueScope &jv, const tonlib_api::syncStateDone &object); +void to_json(JsonValueScope &jv, const tonlib_api::syncStateInProgress &object); void to_json(JsonValueScope &jv, const tonlib_api::unpackedAccountAddress &object); +void to_json(JsonValueScope &jv, const tonlib_api::Update &object); void to_json(JsonValueScope &jv, const tonlib_api::updateSendLiteServerQuery &object); +void to_json(JsonValueScope &jv, const tonlib_api::updateSyncState &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_AccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateRaw &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateTestWallet &object); @@ -133,6 +161,9 @@ void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateWallet &o void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateTestGiver &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateUninited &object); void to_json(JsonValueScope &jv, const tonlib_api::internal_transactionId &object); +void to_json(JsonValueScope &jv, const tonlib_api::liteServer_info &object); +void to_json(JsonValueScope &jv, const tonlib_api::query_fees &object); +void to_json(JsonValueScope &jv, const tonlib_api::query_info &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_accountState &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_initialAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_message &object); @@ -155,6 +186,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::encrypt &object); void to_json(JsonValueScope &jv, const tonlib_api::exportEncryptedKey &object); void to_json(JsonValueScope &jv, const tonlib_api::exportKey &object); void to_json(JsonValueScope &jv, const tonlib_api::exportPemKey &object); +void to_json(JsonValueScope &jv, const tonlib_api::generic_createSendGramsQuery &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_getAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::generic_sendGrams &object); void to_json(JsonValueScope &jv, const tonlib_api::getBip39Hints &object); @@ -167,10 +199,17 @@ void to_json(JsonValueScope &jv, const tonlib_api::importKey &object); void to_json(JsonValueScope &jv, const tonlib_api::importPemKey &object); void to_json(JsonValueScope &jv, const tonlib_api::init &object); void to_json(JsonValueScope &jv, const tonlib_api::kdf &object); +void to_json(JsonValueScope &jv, const tonlib_api::liteServer_getInfo &object); void to_json(JsonValueScope &jv, const tonlib_api::onLiteServerQueryError &object); void to_json(JsonValueScope &jv, const tonlib_api::onLiteServerQueryResult &object); void to_json(JsonValueScope &jv, const tonlib_api::options_setConfig &object); void to_json(JsonValueScope &jv, const tonlib_api::packAccountAddress &object); +void to_json(JsonValueScope &jv, const tonlib_api::query_estimateFees &object); +void to_json(JsonValueScope &jv, const tonlib_api::query_forget &object); +void to_json(JsonValueScope &jv, const tonlib_api::query_getInfo &object); +void to_json(JsonValueScope &jv, const tonlib_api::query_send &object); +void to_json(JsonValueScope &jv, const tonlib_api::raw_createAndSendMessage &object); +void to_json(JsonValueScope &jv, const tonlib_api::raw_createQuery &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_getAccountAddress &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_getAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::raw_getTransactions &object); @@ -179,6 +218,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::runTests &object); void to_json(JsonValueScope &jv, const tonlib_api::setLogStream &object); void to_json(JsonValueScope &jv, const tonlib_api::setLogTagVerbosityLevel &object); void to_json(JsonValueScope &jv, const tonlib_api::setLogVerbosityLevel &object); +void to_json(JsonValueScope &jv, const tonlib_api::sync &object); void to_json(JsonValueScope &jv, const tonlib_api::testGiver_getAccountAddress &object); void to_json(JsonValueScope &jv, const tonlib_api::testGiver_getAccountState &object); void to_json(JsonValueScope &jv, const tonlib_api::testGiver_sendGrams &object); diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl index 942ec47ef9..7617f1fe09 100644 --- a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl +++ b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tl @@ -411,13 +411,14 @@ db.root.key.config = db.root.Key; db.celldb.value block_id:tonNode.blockIdExt prev:int256 next:int256 root_hash:int256 = db.celldb.Value; db.celldb.key.value hash:int256 = db.celldb.key.Value; -db.block.info id:tonNode.blockIdExt flags:# prev_left:flags.1?tonNode.blockIdExt +db.block.info#4ac6e727 id:tonNode.blockIdExt flags:# prev_left:flags.1?tonNode.blockIdExt prev_right:flags.2?tonNode.blockIdExt next_left:flags.3?tonNode.blockIdExt next_right:flags.4?tonNode.blockIdExt lt:flags.13?long ts:flags.14?int state:flags.17?int256 = db.block.Info; +db.block.packedInfo id:tonNode.blockIdExt unixtime:int offset:long = db.block.Info; db.block.archivedInfo id:tonNode.blockIdExt flags:# next:flags.0?tonNode.blockIdExt = db.block.Info; db.blockdb.value next:tonNode.blockIdExt data:bytes = db.blockdb.Value; diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo index 6727841e90..28e5cfa571 100644 Binary files a/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo and b/submodules/ton/tonlib-src/tl/generate/scheme/ton_api.tlo differ diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl index cf0ed2b837..0963f27230 100644 --- a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl +++ b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tl @@ -25,6 +25,7 @@ options config:config keystore_type:KeyStoreType = Options; key public_key:string secret:secureBytes = Key; inputKey key:key local_password:secureBytes = InputKey; +inputKeyFake = InputKey; exportedKey word_list:vector = ExportedKey; exportedPemKey pem:secureString = ExportedPemKey; exportedEncryptedKey data:secureBytes = ExportedEncryptedKey; @@ -65,7 +66,15 @@ generic.accountStateUninited account_state:uninited.accountState = generic.Accou sendGramsResult sent_until:int53 body_hash:bytes = SendGramsResult; +syncStateDone = SyncState; +syncStateInProgress from_seqno:int32 to_seqno:int32 current_seqno:int32 = SyncState; + +fees in_fwd_fee:int53 storage_fee:int53 gas_fee:int53 fwd_fee:int53= Fees; +query.fees source_fees:fees destination_fees:fees = query.Fees; +query.info id:int53 valid_until:int53 body_hash:bytes = query.Info; + updateSendLiteServerQuery id:int64 data:bytes = Update; +updateSyncState sync_state:SyncState = Update; //@class LogStream @description Describes a stream to which TDLib internal log is written @@ -87,6 +96,8 @@ logTags tags:vector = LogTags; data bytes:secureBytes = Data; +liteServer.info now:int53 version:int32 capabilities:int64 = liteServer.Info; + ---functions--- init options:options = Ok; @@ -97,13 +108,13 @@ options.setConfig config:config = Ok; createNewKey local_password:secureBytes mnemonic_password:secureBytes random_extra_seed:secureBytes = Key; deleteKey key:key = Ok; deleteAllKeys = Ok; -exportKey input_key:inputKey = ExportedKey; -exportPemKey input_key:inputKey key_password:secureBytes = ExportedPemKey; -exportEncryptedKey input_key:inputKey key_password:secureBytes = ExportedEncryptedKey; +exportKey input_key:InputKey = ExportedKey; +exportPemKey input_key:InputKey key_password:secureBytes = ExportedPemKey; +exportEncryptedKey input_key:InputKey key_password:secureBytes = ExportedEncryptedKey; importKey local_password:secureBytes mnemonic_password:secureBytes exported_key:exportedKey = Key; importPemKey local_password:secureBytes key_password:secureBytes exported_key:exportedPemKey = Key; importEncryptedKey local_password:secureBytes key_password:secureBytes exported_encrypted_key:exportedEncryptedKey = Key; -changeLocalPassword input_key:inputKey new_local_password:secureBytes = Key; +changeLocalPassword input_key:InputKey new_local_password:secureBytes = Key; encrypt decrypted_data:secureBytes secret:secureBytes = Data; decrypt encrypted_data:secureBytes secret:secureBytes = Data; @@ -117,32 +128,45 @@ getBip39Hints prefix:string = Bip39Hints; //raw.init initial_account_state:raw.initialAccountState = Ok; raw.getAccountAddress initital_account_state:raw.initialAccountState = AccountAddress; raw.getAccountState account_address:accountAddress = raw.AccountState; -raw.sendMessage destination:accountAddress initial_account_state:bytes data:bytes = Ok; raw.getTransactions account_address:accountAddress from_transaction_id:internal.transactionId = raw.Transactions; +raw.sendMessage body:bytes = Ok; +raw.createAndSendMessage destination:accountAddress initial_account_state:bytes data:bytes = Ok; +raw.createQuery destination:accountAddress init_code:bytes init_data:bytes body:bytes = query.Info; -testWallet.init private_key:inputKey = Ok; +testWallet.init private_key:InputKey = Ok; testWallet.getAccountAddress initital_account_state:testWallet.initialAccountState = AccountAddress; testWallet.getAccountState account_address:accountAddress = testWallet.AccountState; -testWallet.sendGrams private_key:inputKey destination:accountAddress seqno:int32 amount:int64 message:bytes = SendGramsResult; +testWallet.sendGrams private_key:InputKey destination:accountAddress seqno:int32 amount:int64 message:bytes = SendGramsResult; -wallet.init private_key:inputKey = Ok; +wallet.init private_key:InputKey = Ok; wallet.getAccountAddress initital_account_state:wallet.initialAccountState = AccountAddress; wallet.getAccountState account_address:accountAddress = wallet.AccountState; -wallet.sendGrams private_key:inputKey destination:accountAddress seqno:int32 valid_until:int53 amount:int64 message:bytes = SendGramsResult; +wallet.sendGrams private_key:InputKey destination:accountAddress seqno:int32 valid_until:int53 amount:int64 message:bytes = SendGramsResult; testGiver.getAccountState = testGiver.AccountState; testGiver.getAccountAddress = AccountAddress; testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 message:bytes = SendGramsResult; +sync = Ok; + //generic.getAccountAddress initital_account_state:generic.InitialAccountState = AccountAddress; generic.getAccountState account_address:accountAddress = generic.AccountState; -generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 timeout:int32 allow_send_to_uninited:Bool message:bytes = SendGramsResult; +generic.sendGrams private_key:InputKey source:accountAddress destination:accountAddress amount:int64 timeout:int32 allow_send_to_uninited:Bool message:bytes = SendGramsResult; + +generic.createSendGramsQuery private_key:InputKey source:accountAddress destination:accountAddress amount:int64 timeout:int32 allow_send_to_uninited:Bool message:bytes = query.Info; + +query.send id:int53 = Ok; +query.forget id:int53 = Ok; +query.estimateFees id:int53 ignore_chksig:Bool = query.Fees; +query.getInfo id:int53 = query.Info; onLiteServerQueryResult id:int64 bytes:bytes = Ok; onLiteServerQueryError id:int64 error:error = Ok; runTests dir:string = Ok; +liteServer.getInfo = liteServer.Info; + //@description Sets new log stream for internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously @log_stream New log stream setLogStream log_stream:LogStream = Ok; diff --git a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo index 1af5d79a94..edbbe50fc9 100644 Binary files a/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo and b/submodules/ton/tonlib-src/tl/generate/scheme/tonlib_api.tlo differ diff --git a/submodules/ton/tonlib-src/tonlib/CMakeLists.txt b/submodules/ton/tonlib-src/tonlib/CMakeLists.txt index 42b909ca27..26b14c3d50 100644 --- a/submodules/ton/tonlib-src/tonlib/CMakeLists.txt +++ b/submodules/ton/tonlib-src/tonlib/CMakeLists.txt @@ -5,42 +5,34 @@ if (NOT OPENSSL_FOUND) endif() set(TONLIB_SOURCE - tonlib/CellString.cpp tonlib/Client.cpp tonlib/Config.cpp tonlib/ExtClient.cpp tonlib/ExtClientLazy.cpp tonlib/ExtClientOutbound.cpp - tonlib/GenericAccount.cpp tonlib/KeyStorage.cpp tonlib/KeyValue.cpp tonlib/LastBlock.cpp tonlib/LastBlockStorage.cpp + tonlib/LastConfig.cpp tonlib/Logging.cpp - tonlib/TestGiver.cpp - tonlib/TestWallet.cpp tonlib/TonlibClient.cpp tonlib/utils.cpp - tonlib/Wallet.cpp - tonlib/CellString.h tonlib/Client.h tonlib/Config.h tonlib/ExtClient.h tonlib/ExtClientLazy.h tonlib/ExtClientOutbound.h - tonlib/GenericAccount.h tonlib/KeyStorage.h tonlib/KeyValue.h tonlib/LastBlock.h tonlib/LastBlockStorage.h + tonlib/LastConfig.h tonlib/Logging.h - tonlib/TestGiver.h - tonlib/TestWallet.h tonlib/TonlibCallback.h tonlib/TonlibClient.h tonlib/utils.h - tonlib/Wallet.h tonlib/keys/bip39.cpp tonlib/keys/DecryptedKey.cpp @@ -64,7 +56,7 @@ target_include_directories(tonlib PUBLIC $/.. $ ) -target_link_libraries(tonlib PRIVATE tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block lite-client-common) +target_link_libraries(tonlib PRIVATE tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block lite-client-common smc-envelope) target_link_libraries(tonlib PUBLIC tdutils tl_tonlib_api) if (TONLIB_ENABLE_JNI AND NOT ANDROID) # jni is available by default on Android @@ -134,7 +126,7 @@ if (NOT TON_USE_ABSEIL) if (WIN32) set(WINGETOPT_TARGET wingetopt) endif() -install(TARGETS tdnet keys crc32c tdactor adnllite tl_api tl-utils tl_lite_api tl-lite-utils ton_crypto ton_block ${WINGETOPT_TARGET} +install(TARGETS tdnet keys crc32c tdactor adnllite tl_api tl-utils tl_lite_api tl-lite-utils ton_crypto ton_block smc-envelope ${WINGETOPT_TARGET} tdutils tl_tonlib_api tonlib lite-client-common Tonlib EXPORT Tonlib LIBRARY DESTINATION lib ARCHIVE DESTINATION lib diff --git a/submodules/ton/tonlib-src/tonlib/test/offline.cpp b/submodules/ton/tonlib-src/tonlib/test/offline.cpp index 04b55c7804..9e89ba6476 100644 --- a/submodules/ton/tonlib-src/tonlib/test/offline.cpp +++ b/submodules/ton/tonlib-src/tonlib/test/offline.cpp @@ -17,23 +17,14 @@ Copyright 2017-2019 Telegram Systems LLP */ -#include "fift/Fift.h" -#include "fift/words.h" -#include "fift/utils.h" - #include "block/block.h" #include "block/block-auto.h" #include "vm/cells.h" #include "vm/boc.h" -#include "vm/cells/MerkleProof.h" +#include "vm/cells/CellString.h" -#include "tonlib/CellString.h" #include "tonlib/utils.h" -#include "tonlib/TestGiver.h" -#include "tonlib/TestWallet.h" -#include "tonlib/Wallet.h" -#include "tonlib/GenericAccount.h" #include "tonlib/TonlibClient.h" #include "tonlib/Client.h" @@ -70,181 +61,6 @@ TEST(Tonlib, CellString) { using namespace tonlib; -std::string current_dir() { - return td::PathView(td::realpath(__FILE__).move_as_ok()).parent_dir().str(); -} - -std::string load_source(std::string name) { - return td::read_file_str(current_dir() + "../../crypto/" + name).move_as_ok(); -} - -td::Ref get_test_wallet_source() { - std::string code = R"ABCD( -SETCP0 DUP IFNOTRET // return if recv_internal -DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method - DROP c4 PUSHCTR CTOS 32 PLDU // cnt -}> -INC 32 THROWIF // fail unless recv_external -512 INT LDSLICEX DUP 32 PLDU // sign cs cnt -c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk -s1 s2 XCPU // sign cs cnt pubk cnt' cnt -EQUAL 33 THROWIFNOT // ( seqno mismatch? ) -s2 PUSH HASHSU // sign cs cnt pubk hash -s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk -CHKSIGNU // pubk cs cnt ? -34 THROWIFNOT // signature mismatch -ACCEPT -SWAP 32 LDU NIP -DUP SREFS IF:<{ - // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance - 8 LDU LDREF // pubk cnt mode msg cs - s0 s2 XCHG SENDRAWMSG // pubk cnt cs ; ( message sent ) -}> -ENDS -INC NEWC 32 STU 256 STU ENDC c4 POPCTR -)ABCD"; - return fift::compile_asm(code).move_as_ok(); -} - -td::Ref get_wallet_source() { - std::string code = R"ABCD( -SETCP0 DUP IFNOTRET // return if recv_internal - DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method - DROP c4 PUSHCTR CTOS 32 PLDU // cnt - }> - INC 32 THROWIF // fail unless recv_external - 9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU // signature in_msg msg_seqno valid_until cs - SWAP NOW LEQ 35 THROWIF // signature in_msg msg_seqno cs - c4 PUSH CTOS 32 LDU 256 LDU ENDS // signature in_msg msg_seqno cs stored_seqno public_key - s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno - EQUAL 33 THROWIFNOT // signature in_msg public_key cs stored_seqno - s0 s3 XCHG HASHSU // signature stored_seqno public_key cs hash - s0 s4 s2 XC2PU CHKSIGNU 34 THROWIFNOT // cs stored_seqno public_key - ACCEPT - s0 s2 XCHG // public_key stored_seqno cs - WHILE:<{ - DUP SREFS // public_key stored_seqno cs _40 - }>DO<{ // public_key stored_seqno cs - // 3 INT 35 LSHIFT# 3 INT RAWRESERVE // reserve all but 103 Grams from the balance - 8 LDU LDREF s0 s2 XCHG // public_key stored_seqno cs _45 mode - SENDRAWMSG // public_key stored_seqno cs - }> - ENDS INC // public_key seqno' - NEWC 32 STU 256 STU ENDC c4 POP -)ABCD"; - return fift::compile_asm(code).move_as_ok(); -} - -TEST(Tonlib, TestWallet) { - LOG(ERROR) << td::base64_encode(std_boc_serialize(get_test_wallet_source()).move_as_ok()); - CHECK(get_test_wallet_source()->get_hash() == TestWallet::get_init_code()->get_hash()); - auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet.fif"), {"aba", "0"}).move_as_ok(); - - auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; - auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data; - auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data; - - td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; - auto pub_key = priv_key.get_public_key().move_as_ok(); - auto init_state = TestWallet::get_init_state(pub_key); - auto init_message = TestWallet::get_init_message(priv_key); - auto address = GenericAccount::get_address(0, init_state); - - CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - - td::Ref res = GenericAccount::create_ext_message(address, init_state, init_message); - - LOG(ERROR) << "-------"; - vm::load_cell_slice(res).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet.fif")).ensure(); - auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); - fift_output = - fift::mem_run_fift(std::move(fift_output.source_lookup), - {"aba", "new-wallet", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "123", "321"}) - .move_as_ok(); - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - auto gift_message = GenericAccount::create_ext_message( - address, {}, TestWallet::make_a_gift_message(priv_key, 123, 321000000000ll, "TEST", dest)); - LOG(ERROR) << "-------"; - vm::load_cell_slice(gift_message).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} - -td::Ref get_wallet_source_fc() { - return fift::compile_asm(load_source("smartcont/wallet-code.fif"), "", false).move_as_ok(); -} - -TEST(Tonlib, Wallet) { - LOG(ERROR) << td::base64_encode(std_boc_serialize(get_wallet_source()).move_as_ok()); - CHECK(get_wallet_source()->get_hash() == Wallet::get_init_code()->get_hash()); - - auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet-v2.fif"), {"aba", "0"}).move_as_ok(); - - auto new_wallet_pk = fift_output.source_lookup.read_file("new-wallet.pk").move_as_ok().data; - auto new_wallet_query = fift_output.source_lookup.read_file("new-wallet-query.boc").move_as_ok().data; - auto new_wallet_addr = fift_output.source_lookup.read_file("new-wallet.addr").move_as_ok().data; - - td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}}; - auto pub_key = priv_key.get_public_key().move_as_ok(); - auto init_state = Wallet::get_init_state(pub_key); - auto init_message = Wallet::get_init_message(priv_key); - auto address = GenericAccount::get_address(0, init_state); - - CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32)); - - td::Ref res = GenericAccount::create_ext_message(address, init_state, init_message); - - LOG(ERROR) << "-------"; - vm::load_cell_slice(res).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(new_wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(new_wallet_query).move_as_ok()->get_hash() == res->get_hash()); - - fift_output.source_lookup.write_file("/main.fif", load_source("smartcont/wallet-v2.fif")).ensure(); - class ZeroOsTime : public fift::OsTime { - public: - td::uint32 now() override { - return 0; - } - }; - fift_output.source_lookup.set_os_time(std::make_unique()); - auto dest = block::StdAddress::parse("Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX").move_as_ok(); - fift_output = - fift::mem_run_fift(std::move(fift_output.source_lookup), - {"aba", "new-wallet", "Ef9Tj6fMJP+OqhAdhKXxq36DL+HYSzCc3+9O6UNzqsgPfYFX", "123", "321"}) - .move_as_ok(); - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - auto gift_message = GenericAccount::create_ext_message( - address, {}, Wallet::make_a_gift_message(priv_key, 123, 60, 321000000000ll, "TESTv2", dest)); - LOG(ERROR) << "-------"; - vm::load_cell_slice(gift_message).print_rec(std::cerr); - LOG(ERROR) << "-------"; - vm::load_cell_slice(vm::std_boc_deserialize(wallet_query).move_as_ok()).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash()); -} - -TEST(Tonlib, TestGiver) { - auto address = - block::StdAddress::parse("-1:60c04141c6a7b96d68615e7a91d265ad0f3a9a922e9ae9c901d4fa83f5d3c0d0").move_as_ok(); - LOG(ERROR) << address.bounceable; - auto fift_output = fift::mem_run_fift(load_source("smartcont/testgiver.fif"), - {"aba", address.rserialize(), "0", "6.666", "wallet-query"}) - .move_as_ok(); - LOG(ERROR) << fift_output.output; - - auto wallet_query = fift_output.source_lookup.read_file("wallet-query.boc").move_as_ok().data; - - auto res = GenericAccount::create_ext_message( - TestGiver::address(), {}, TestGiver::make_a_gift_message(0, 1000000000ll * 6666 / 1000, "GIFT", address)); - vm::CellSlice(vm::NoVm(), res).print_rec(std::cerr); - CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == res->get_hash()); -} TEST(Tonlib, PublicKey) { block::PublicKey::parse("pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").ensure_error(); auto key = block::PublicKey::parse("Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").move_as_ok(); diff --git a/submodules/ton/tonlib-src/tonlib/test/online.cpp b/submodules/ton/tonlib-src/tonlib/test/online.cpp index 6ac47921df..11040e53a1 100644 --- a/submodules/ton/tonlib-src/tonlib/test/online.cpp +++ b/submodules/ton/tonlib-src/tonlib/test/online.cpp @@ -34,10 +34,12 @@ #include "ton/ton-tl.hpp" #include "block/block.h" #include "block/block-auto.h" +#include "Ed25519.h" -#include "tonlib/GenericAccount.h" -#include "tonlib/TestGiver.h" -#include "tonlib/TestWallet.h" +#include "smc-envelope/GenericAccount.h" +#include "smc-envelope/MultisigWallet.h" +#include "smc-envelope/TestGiver.h" +#include "smc-envelope/TestWallet.h" #include "tonlib/LastBlock.h" #include "tonlib/ExtClient.h" #include "tonlib/utils.h" @@ -57,18 +59,21 @@ #include "td/utils/optional.h" #include "td/utils/overloaded.h" #include "td/utils/MpscPollableQueue.h" +#include "td/utils/port/path.h" #include "td/utils/port/signals.h" using namespace tonlib; +constexpr td::int64 Gramm = 1000000000; + auto sync_send = [](auto& client, auto query) { using ReturnTypePtr = typename std::decay_t::ReturnType; using ReturnType = typename ReturnTypePtr::element_type; client.send({1, std::move(query)}); while (true) { auto response = client.receive(100); - if (response.object) { + if (response.object && response.id != 0) { CHECK(response.id == 1); if (response.object->get_id() == tonlib_api::error::ID) { auto error = tonlib_api::move_object_as(response.object); @@ -78,87 +83,295 @@ auto sync_send = [](auto& client, auto query) { } } }; +auto static_send = [](auto query) { + using ReturnTypePtr = typename std::decay_t::ReturnType; + using ReturnType = typename ReturnTypePtr::element_type; + auto response = Client::execute({1, std::move(query)}); + if (response.object->get_id() == tonlib_api::error::ID) { + auto error = tonlib_api::move_object_as(response.object); + return td::Result(td::Status::Error(error->code_, error->message_)); + } + return td::Result(tonlib_api::move_object_as(response.object)); +}; struct Key { std::string public_key; td::SecureString secret; - tonlib_api::object_ptr get_input_key() const { + tonlib_api::object_ptr get_input_key() const { return tonlib_api::make_object( tonlib_api::make_object(public_key, secret.copy()), td::SecureString("local")); } + tonlib_api::object_ptr get_fake_input_key() const { + return tonlib_api::make_object(); + } }; struct Wallet { std::string address; Key key; }; +struct TransactionId { + td::int64 lt{0}; + std::string hash; +}; + +struct AccountState { + enum Type { Empty, Wallet, Unknown } type{Empty}; + td::int64 sync_utime{-1}; + td::int64 balance{-1}; + TransactionId last_transaction_id; + std::string address; + + bool is_inited() const { + return type != Empty; + } +}; + +using tonlib_api::make_object; + +void sync(Client& client) { + sync_send(client, make_object()).ensure(); +} + +std::string wallet_address(Client& client, const Key& key) { + return sync_send(client, make_object( + make_object(key.public_key))) + .move_as_ok() + ->account_address_; +} + +Wallet import_wallet_from_pkey(Client& client, std::string pkey, std::string password) { + auto key = sync_send(client, make_object( + td::SecureString("local"), td::SecureString(password), + make_object(td::SecureString(pkey)))) + .move_as_ok(); + Wallet wallet{"", {key->public_key_, std::move(key->secret_)}}; + wallet.address = wallet_address(client, wallet.key); + return wallet; +} + std::string test_giver_address(Client& client) { using tonlib_api::make_object; return sync_send(client, make_object()).move_as_ok()->account_address_; } -td::int64 get_balance(Client& client, std::string address) { +AccountState get_account_state(Client& client, std::string address) { auto generic_state = sync_send(client, tonlib_api::make_object( tonlib_api::make_object(address))) .move_as_ok(); - td::int64 res = 0; - tonlib_api::downcast_call(*generic_state, [&](auto& state) { res = state.account_state_->balance_; }); + AccountState res; + tonlib_api::downcast_call(*generic_state, [&](auto& state) { + res.balance = state.account_state_->balance_; + res.sync_utime = state.account_state_->sync_utime_; + res.last_transaction_id.lt = state.account_state_->last_transaction_id_->lt_; + res.last_transaction_id.hash = state.account_state_->last_transaction_id_->hash_; + }); + res.address = address; + switch (generic_state->get_id()) { + case tonlib_api::generic_accountStateUninited::ID: + res.type = AccountState::Empty; + break; + case tonlib_api::generic_accountStateWallet::ID: + res.type = AccountState::Wallet; + break; + default: + res.type = AccountState::Unknown; + break; + } return res; } -bool is_inited(Client& client, std::string address) { - auto generic_state = sync_send(client, tonlib_api::make_object( - tonlib_api::make_object(address))) - .move_as_ok(); - return generic_state->get_id() != tonlib_api::generic_accountStateUninited::ID; +struct QueryId { + td::int64 id; +}; + +struct Fee { + td::int64 in_fwd_fee{0}; + td::int64 storage_fee{0}; + td::int64 gas_fee{0}; + td::int64 fwd_fee{0}; + td::int64 sum() const { + return in_fwd_fee + storage_fee + gas_fee + fwd_fee; + } +}; + +template +auto to_fee(const T& fee) { + Fee res; + res.in_fwd_fee = fee->in_fwd_fee_; + res.storage_fee = fee->storage_fee_; + res.gas_fee = fee->gas_fee_; + res.fwd_fee = fee->fwd_fee_; + return res; } -void transfer_grams(Client& client, std::string from, std::string to, td::int64 amount, - tonlib_api::object_ptr input_key) { - auto balance = get_balance(client, to); - sync_send(client, tonlib_api::make_object( - std::move(input_key), tonlib_api::make_object(from), - tonlib_api::make_object(to), amount, 0, true, "GIFT")) - .ensure(); - while (balance == get_balance(client, to)) { +td::StringBuilder& operator<<(td::StringBuilder& sb, const Fee& fees) { + return sb << td::tag("in_fwd_fee", fees.in_fwd_fee) << td::tag("storage_fee", fees.storage_fee) + << td::tag("gas_fee", fees.gas_fee) << td::tag("fwd_fee", fees.fwd_fee); +} + +struct QueryInfo { + td::int64 valid_until; + std::string body_hash; +}; + +td::Result create_send_grams_query(Client& client, const Wallet& source, std::string destination, + td::int64 amount, std::string message, bool force = false, int timeout = 0, + bool fake = false) { + auto r_id = sync_send(client, tonlib_api::make_object( + fake ? source.key.get_fake_input_key() : source.key.get_input_key(), + tonlib_api::make_object(source.address), + tonlib_api::make_object(destination), amount, timeout, + force, std::move(message))); + TRY_RESULT(id, std::move(r_id)); + return QueryId{id->id_}; +} + +td::Result create_raw_query(Client& client, std::string source, std::string init_code, std::string init_data, + std::string body) { + auto r_id = + sync_send(client, tonlib_api::make_object( + tonlib_api::make_object(source), init_code, init_data, body)); + TRY_RESULT(id, std::move(r_id)); + return QueryId{id->id_}; +} + +std::pair query_estimate_fees(Client& client, QueryId query_id, bool ignore_chksig = false) { + auto fees = sync_send(client, tonlib_api::make_object(query_id.id, ignore_chksig)) + .move_as_ok(); + return std::make_pair(to_fee(fees->source_fees_), to_fee(fees->destination_fees_)); +} + +void query_send(Client& client, QueryId query_id) { + sync_send(client, tonlib_api::make_object(query_id.id)).ensure(); +} +QueryInfo query_get_info(Client& client, QueryId query_id) { + auto info = sync_send(client, tonlib_api::make_object(query_id.id)).move_as_ok(); + return QueryInfo{info->valid_until_, info->body_hash_}; +} + +td::Result wait_state_change(Client& client, const AccountState& old_state, td::int64 valid_until) { + while (true) { + auto new_state = get_account_state(client, old_state.address); + if (new_state.last_transaction_id.lt != old_state.last_transaction_id.lt) { + return new_state; + } + if (valid_until != 0 && new_state.sync_utime >= valid_until) { + return td::Status::Error("valid_until expired"); + } client.receive(1); } +}; + +td::Result> get_transactions(Client& client, std::string address, + const TransactionId& from) { + auto got_transactions = sync_send(client, make_object( + make_object(address), + make_object(from.lt, from.hash))) + .move_as_ok(); + return std::move(got_transactions); } + +td::Status transfer_grams(Client& client, const Wallet& wallet, std::string address, td::int64 amount) { + auto src_state = get_account_state(client, wallet.address); + auto dst_state = get_account_state(client, address); + auto message = td::rand_string('a', 'z', 500); + + LOG(INFO) << "Transfer: create query " << (double)amount / Gramm << " from " << wallet.address << " to " << address; + auto r_query_id = create_send_grams_query(client, wallet, address, amount, message); + if (r_query_id.is_error() && td::begins_with(r_query_id.error().message(), "DANGEROUS_TRANSACTION")) { + ASSERT_TRUE(dst_state.type == AccountState::Empty); + LOG(INFO) << "Transfer: recreate query due to DANGEROUS_TRANSACTION error"; + r_query_id = create_send_grams_query(client, wallet, address, amount, message, true); + } + + r_query_id.ensure(); + QueryId query_id = r_query_id.move_as_ok(); + auto query_info = query_get_info(client, query_id); + auto fees = query_estimate_fees(client, query_id); + + LOG(INFO) << "Expected src fees: " << fees.first; + LOG(INFO) << "Expected dst fees: " << fees.second; + + bool transfer_all = amount == src_state.balance; + if (!transfer_all && amount + fees.first.sum() + 10 > src_state.balance) { + return td::Status::Error("Not enough balance for query"); + } + + LOG(INFO) << "Transfer: send query"; + + query_send(client, query_id); + td::Timer timer; + TRY_RESULT(new_src_state, wait_state_change(client, src_state, query_info.valid_until)); + LOG(INFO) << "Transfer: reached source in " << timer; + + td::int64 lt; + td::int64 first_fee; + { + auto tr = get_transactions(client, src_state.address, new_src_state.last_transaction_id).move_as_ok(); + CHECK(tr->transactions_.size() > 0); + const auto& txn = tr->transactions_[0]; + CHECK(txn->in_msg_->body_hash_ == query_info.body_hash); + ASSERT_EQ(1u, txn->out_msgs_.size()); + ASSERT_EQ(message, txn->out_msgs_[0]->message_); + lt = txn->out_msgs_[0]->created_lt_; + auto fee_difference = fees.first.sum() - txn->fee_; + first_fee = txn->fee_; + auto desc = PSTRING() << fee_difference << " storage:[" << fees.first.storage_fee << " vs " << txn->storage_fee_ + << "] other:[" << fees.first.sum() - fees.first.storage_fee << " vs " << txn->other_fee_ + << "]"; + LOG(INFO) << "Source fee difference " << desc; + LOG_IF(ERROR, std::abs(fee_difference) > 1) << "Too big source fee difference " << desc; + } + + TRY_RESULT(new_dst_state, wait_state_change(client, dst_state, new_src_state.sync_utime + 30)); + LOG(INFO) << "Transfer: reached destination in " << timer; + + { + auto tr = get_transactions(client, dst_state.address, new_dst_state.last_transaction_id).move_as_ok(); + CHECK(tr->transactions_.size() > 0); + const auto& txn = tr->transactions_[0]; + ASSERT_EQ(lt, txn->in_msg_->created_lt_); + if (transfer_all) { + ASSERT_EQ(amount - first_fee, txn->in_msg_->value_); + } else { + ASSERT_EQ(new_src_state.address, txn->in_msg_->source_); + } + ASSERT_EQ(new_src_state.address, txn->in_msg_->source_); + ASSERT_EQ(message, txn->in_msg_->message_); + auto fee_difference = fees.second.sum() - txn->fee_; + auto desc = PSTRING() << fee_difference << " storage:[" << fees.second.storage_fee << " vs " << txn->storage_fee_ + << "] other:[" << fees.second.sum() - fees.second.storage_fee << " vs " << txn->other_fee_ + << "]"; + LOG(INFO) << "Destination fee difference " << desc; + LOG_IF(ERROR, std::abs(fee_difference) > 1) << "Too big destination fee difference " << desc; + } + + return td::Status::OK(); +} + Wallet create_empty_wallet(Client& client) { using tonlib_api::make_object; - auto key = sync_send(client, make_object(td::SecureString("local"), - td::SecureString("mnemonic"), td::SecureString())) + auto key = sync_send(client, make_object(td::SecureString("local"), td::SecureString(), + td::SecureString())) .move_as_ok(); Wallet wallet{"", {key->public_key_, std::move(key->secret_)}}; auto account_address = - sync_send(client, make_object( - make_object(wallet.key.public_key))) + sync_send(client, make_object( + make_object(wallet.key.public_key))) .move_as_ok(); wallet.address = account_address->account_address_; + + // get state of empty account + auto state = get_account_state(client, wallet.address); + ASSERT_EQ(-1, state.balance); + ASSERT_EQ(AccountState::Empty, state.type); + return wallet; } -Wallet create_wallet(Client& client) { - using tonlib_api::make_object; - auto wallet = create_empty_wallet(client); - - transfer_grams(client, test_giver_address(client), wallet.address, 6000000000, {}); - sync_send(client, make_object(wallet.key.get_input_key())).ensure(); - while (!is_inited(client, wallet.address)) { - client.receive(1); - } - LOG(ERROR) << get_balance(client, wallet.address); - return wallet; -} - -std::string get_test_giver_address(Client& client) { - return sync_send(client, tonlib_api::make_object()) - .move_as_ok() - ->account_address_; -} - void dump_transaction_history(Client& client, std::string address) { using tonlib_api::make_object; auto state = sync_send(client, make_object()).move_as_ok(); @@ -180,166 +393,156 @@ void dump_transaction_history(Client& client, std::string address) { LOG(ERROR) << cnt; } +void test_estimate_fees_without_key(Client& client, const Wallet& wallet_a, const Wallet& wallet_b) { + LOG(ERROR) << " SUBTEST: estimate fees without key"; + { + auto query_id = create_send_grams_query(client, wallet_a, wallet_b.address, 0, "???", true, 0, true).move_as_ok(); + auto fees1 = query_estimate_fees(client, query_id, false); + auto fees2 = query_estimate_fees(client, query_id, true); + LOG(INFO) << "Fee without ignore_chksig\t" << fees1; + LOG(INFO) << "Fee with ignore_chksig\t" << fees2; + CHECK(fees1.first.gas_fee == 0); + CHECK(fees2.first.gas_fee != 0); + } +} + +void test_back_and_forth_transfer(Client& client, const Wallet& giver_wallet, bool flag) { + LOG(ERROR) << "TEST: back and forth transfer"; + // just generate private key and address + auto wallet_a = create_empty_wallet(client); + LOG(INFO) << wallet_a.address; + + // get state of empty account + auto state = get_account_state(client, wallet_a.address); + ASSERT_EQ(-1, state.balance); + ASSERT_EQ(AccountState::Empty, state.type); + + test_estimate_fees_without_key(client, giver_wallet, wallet_a); + + // transfer from giver to a + transfer_grams(client, giver_wallet, wallet_a.address, 1 * Gramm).ensure(); + state = get_account_state(client, wallet_a.address); + ASSERT_EQ(1 * Gramm, state.balance); + ASSERT_EQ(AccountState::Empty, state.type); + + test_estimate_fees_without_key(client, wallet_a, giver_wallet); + + if (flag) { + // transfer from a to giver + transfer_grams(client, wallet_a, giver_wallet.address, 5 * Gramm / 10).ensure(); + state = get_account_state(client, wallet_a.address); + ASSERT_TRUE(state.balance < 5 * Gramm / 10); + ASSERT_EQ(AccountState::Wallet, state.type); + } + + // transfer all remaining balance (test flag 128) + transfer_grams(client, wallet_a, giver_wallet.address, state.balance).ensure(); + state = get_account_state(client, wallet_a.address); + ASSERT_TRUE(state.balance == 0); + ASSERT_EQ(AccountState::Wallet, state.type); +} + +void test_multisig(Client& client, const Wallet& giver_wallet) { + LOG(ERROR) << "TEST: multisig"; + + int n = 16; + int k = 10; + std::vector private_keys; + for (int i = 0; i < n; i++) { + private_keys.push_back(td::Ed25519::generate_private_key().move_as_ok()); + } + + auto ms = ton::MultisigWallet::create(); + auto init_data = ms->create_init_data( + td::transform(private_keys, [](const auto& pk) { return pk.get_public_key().move_as_ok().as_octet_string(); }), + k); + ms = ton::MultisigWallet::create(init_data); + auto raw_address = ms->get_address(ton::basechainId); + auto address = raw_address.rserialize(); + transfer_grams(client, giver_wallet, address, 1 * Gramm).ensure(); + auto init_state = ms->get_init_state(); + + // Just transfer all (some) money back in one query + vm::CellBuilder icb; + ton::GenericAccount::store_int_message(icb, block::StdAddress::parse(giver_wallet.address).move_as_ok(), + 5 * Gramm / 10); + icb.store_bytes("\0\0\0\0", 4); + vm::CellString::store(icb, "Greatings from multisig", 35 * 8).ensure(); + ton::MultisigWallet::QueryBuilder qb(-1, icb.finalize()); + for (int i = 0; i < k - 1; i++) { + qb.sign(i, private_keys[i]); + } + + auto query_id = + create_raw_query(client, address, vm::std_boc_serialize(ms->get_state().code).move_as_ok().as_slice().str(), + vm::std_boc_serialize(ms->get_state().data).move_as_ok().as_slice().str(), + vm::std_boc_serialize(qb.create(k - 1, private_keys[k - 1])).move_as_ok().as_slice().str()) + .move_as_ok(); + auto fees = query_estimate_fees(client, query_id); + + LOG(INFO) << "Expected src fees: " << fees.first; + LOG(INFO) << "Expected dst fees: " << fees.second; + auto a_state = get_account_state(client, address); + query_send(client, query_id); + auto new_a_state = wait_state_change(client, a_state, a_state.sync_utime + 30).move_as_ok(); +} + int main(int argc, char* argv[]) { td::set_default_failure_signal_handler(); using tonlib_api::make_object; td::OptionsParser p; std::string global_config_str; + std::string giver_key_str; + std::string giver_key_pwd = "cucumber"; + std::string keystore_dir = "test-keystore"; + bool reset_keystore_dir = false; p.add_option('C', "global-config", "file to read global config", [&](td::Slice fname) { TRY_RESULT(str, td::read_file_str(fname.str())); global_config_str = std::move(str); - LOG(ERROR) << global_config_str; + return td::Status::OK(); + }); + p.add_option('G', "giver-key", "file with a wallet key that should be used as a giver", [&](td::Slice fname) { + TRY_RESULT(str, td::read_file_str(fname.str())); + giver_key_str = std::move(str); + return td::Status::OK(); + }); + p.add_option('f', "force", "reser keystore dir", [&]() { + reset_keystore_dir = true; return td::Status::OK(); }); p.run(argc, argv).ensure(); + if (reset_keystore_dir) { + td::rmrf(keystore_dir).ignore(); + td::mkdir(keystore_dir).ensure(); + } + + SET_VERBOSITY_LEVEL(VERBOSITY_NAME(INFO)); + static_send(make_object("tonlib_query", 4)).ensure(); + auto tags = static_send(make_object()).move_as_ok()->tags_; + for (auto& tag : tags) { + static_send(make_object(tag, 4)).ensure(); + } + Client client; { sync_send(client, make_object(make_object( make_object(global_config_str, "", false, false), - make_object(".")))) + make_object(keystore_dir)))) .ensure(); } - //dump_transaction_history(client, get_test_giver_address(client)); - auto wallet_a = create_wallet(client); - auto wallet_b = create_empty_wallet(client); - transfer_grams(client, wallet_a.address, wallet_b.address, 3000000000, wallet_a.key.get_input_key()); - auto a = get_balance(client, wallet_a.address); - auto b = get_balance(client, wallet_b.address); - LOG(ERROR) << a << " " << b; - return 0; - { - // init - sync_send(client, make_object(make_object( - make_object(global_config_str, "", false, false), - make_object(".")))) - .ensure(); - auto key = sync_send(client, make_object( - td::SecureString("local"), td::SecureString("mnemonic"), td::SecureString())) - .move_as_ok(); + // wait till client is synchronized with blockchain. + // not necessary, but synchronized will be trigged anyway later + sync(client); - auto create_input_key = [&] { - return make_object(make_object(key->public_key_, key->secret_.copy()), - td::SecureString("local")); - }; + // give wallet with some test grams to run test + auto giver_wallet = import_wallet_from_pkey(client, giver_key_str, giver_key_pwd); - auto public_key_raw = key->public_key_; - td::Ed25519::PublicKey public_key_std(td::SecureString{public_key_raw}); - - sync_send(client, make_object( - make_object(global_config_str, "", false, false))) - .ensure(); - - auto wallet_addr = GenericAccount::get_address(0, TestWallet::get_init_state(public_key_std)); - { - auto account_address = - sync_send(client, make_object( - make_object(public_key_raw))) - .move_as_ok(); - ASSERT_EQ(wallet_addr.rserialize(), account_address->account_address_); - } - - std::string test_giver_address; - { - auto account_address = sync_send(client, make_object()).move_as_ok(); - test_giver_address = account_address->account_address_; - ASSERT_EQ(TestGiver::address().rserialize(), test_giver_address); - } - - { - auto account_address = - sync_send( - client, - make_object(make_object( - vm::std_boc_serialize(TestWallet::get_init_code()).move_as_ok().as_slice().str(), - vm::std_boc_serialize(TestWallet::get_init_data(public_key_std)).move_as_ok().as_slice().str()))) - .move_as_ok(); - ASSERT_EQ(wallet_addr.rserialize(), account_address->account_address_); - } - - { - auto state = sync_send(client, make_object( - make_object(wallet_addr.rserialize()))) - .move_as_ok(); - LOG(ERROR) << to_string(state); - } - - td::int32 seqno = 0; - { - auto state = sync_send(client, make_object()).move_as_ok(); - LOG(ERROR) << to_string(state); - seqno = state->seqno_; - } - - { - sync_send(client, make_object( - make_object(wallet_addr.rserialize()), seqno, - 1000000000ll * 6666 / 1000, "GIFT")) - .ensure(); - } - - while (true) { - auto state = sync_send(client, make_object()).move_as_ok(); - if (state->seqno_ > seqno) { - break; - } - client.receive(1); - } - - while (true) { - auto state = sync_send(client, make_object( - make_object(wallet_addr.rserialize()))) - .move_as_ok(); - td::int64 grams_count = state->balance_; - if (grams_count > 0) { - LOG(ERROR) << "GOT " << grams_count; - break; - } - client.receive(1); - } - - { sync_send(client, make_object(create_input_key())).ensure(); } - - while (true) { - auto r_state = sync_send(client, make_object( - make_object(wallet_addr.rserialize()))); - if (r_state.is_ok()) { - LOG(ERROR) << to_string(r_state.ok()); - break; - } - client.receive(1); - } - - { - sync_send(client, make_object( - create_input_key(), make_object(wallet_addr.rserialize()), - make_object(test_giver_address), 1000000000ll * 3333 / 1000, 0, - true, "GIFT")) - .ensure(); - } - while (true) { - auto generic_state = sync_send(client, make_object( - make_object(wallet_addr.rserialize()))) - .move_as_ok(); - if (generic_state->get_id() == tonlib_api::generic_accountStateTestWallet::ID) { - auto state = tonlib_api::move_object_as(generic_state); - if (state->account_state_->balance_ < 5617007000) { - LOG(ERROR) << to_string(state); - break; - } - } - client.receive(1); - } - { - auto generic_state = sync_send(client, make_object( - make_object(test_giver_address))) - .move_as_ok(); - CHECK(generic_state->get_id() == tonlib_api::generic_accountStateTestGiver::ID); - LOG(ERROR) << to_string(generic_state); - } - } + test_back_and_forth_transfer(client, giver_wallet, false); + test_back_and_forth_transfer(client, giver_wallet, true); + test_multisig(client, giver_wallet); return 0; } diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/Client.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/Client.cpp index c42b19655a..d22e7ac792 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/Client.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/Client.cpp @@ -56,8 +56,10 @@ class Client::Impl final { std::shared_ptr output_queue_; }; - scheduler_.run_in_context( - [&] { tonlib_ = td::actor::create_actor("Tonlib", td::make_unique(output_queue_)); }); + scheduler_.run_in_context([&] { + tonlib_ = td::actor::create_actor(td::actor::ActorOptions().with_name("Tonlib").with_poll(), + td::make_unique(output_queue_)); + }); scheduler_thread_ = td::thread([&] { scheduler_.run(); }); } @@ -107,7 +109,7 @@ class Client::Impl final { std::atomic receive_lock_{false}; bool is_closed_{false}; - td::actor::Scheduler scheduler_{{0}}; + td::actor::Scheduler scheduler_{{1}}; td::thread scheduler_thread_; td::actor::ActorOwn tonlib_; diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp index 442d65033a..6981078efb 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.cpp @@ -19,8 +19,27 @@ #include "tonlib/ExtClient.h" #include "tonlib/LastBlock.h" +#include "tonlib/LastConfig.h" namespace tonlib { +ExtClient::~ExtClient() { + last_config_queries_.for_each([](auto id, auto &promise) { promise.set_error(TonlibError::Cancelled()); }); + last_block_queries_.for_each([](auto id, auto &promise) { promise.set_error(TonlibError::Cancelled()); }); + queries_.for_each([](auto id, auto &promise) { promise.set_error(TonlibError::Cancelled()); }); +} +void ExtClient::with_last_config(td::Promise promise) { + auto query_id = last_config_queries_.create(std::move(promise)); + td::Promise P = [query_id, self = this, + actor_id = td::actor::actor_id()](td::Result result) { + send_lambda(actor_id, [self, query_id, result = std::move(result)]() mutable { + self->last_config_queries_.extract(query_id).set_result(std::move(result)); + }); + }; + if (client_.last_block_actor_.empty()) { + return P.set_error(TonlibError::NoLiteServers()); + } + td::actor::send_closure(client_.last_config_actor_, &LastConfig::get_last_config, std::move(P)); +} void ExtClient::with_last_block(td::Promise promise) { auto query_id = last_block_queries_.create(std::move(promise)); td::Promise P = [query_id, self = this, diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h index 1547337948..b3cbbaf09d 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClient.h @@ -33,10 +33,13 @@ namespace tonlib { class LastBlock; +class LastConfig; struct LastBlockState; +struct LastConfigState; struct ExtClientRef { td::actor::ActorId andl_ext_client_; td::actor::ActorId last_block_actor_; + td::actor::ActorId last_config_actor_; }; class ExtClient { @@ -53,8 +56,10 @@ class ExtClient { ExtClientRef get_client() { return client_; } + ~ExtClient(); void with_last_block(td::Promise promise); + void with_last_config(td::Promise promise); template void send_query(QueryT query, td::Promise promise, td::int32 seq_no = -1) { @@ -93,6 +98,7 @@ class ExtClient { ExtClientRef client_; td::Container> queries_; td::Container> last_block_queries_; + td::Container> last_config_queries_; void send_raw_query(td::BufferSlice query, td::Promise promise); }; diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClientLazy.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClientLazy.cpp index d5adb770e1..cd83e3abde 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/ExtClientLazy.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/ExtClientLazy.cpp @@ -17,6 +17,7 @@ Copyright 2017-2019 Telegram Systems LLP */ #include "ExtClientLazy.h" +#include "TonlibError.h" namespace tonlib { class ExtClientLazyImp : public ton::adnl::AdnlExtClient { @@ -28,12 +29,18 @@ class ExtClientLazyImp : public ton::adnl::AdnlExtClient { void check_ready(td::Promise promise) override { before_query(); + if (client_.empty()) { + return promise.set_error(TonlibError::Cancelled()); + } send_closure(client_, &ton::adnl::AdnlExtClient::check_ready, std::move(promise)); } void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout, td::Promise promise) override { before_query(); + if (client_.empty()) { + return promise.set_error(TonlibError::Cancelled()); + } send_closure(client_, &ton::adnl::AdnlExtClient::send_query, std::move(name), std::move(data), timeout, std::move(promise)); } diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp index 6e01f2f846..c34468a2de 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.cpp @@ -106,6 +106,9 @@ td::Result KeyStorage::export_key(InputKey input_key) { } td::Result KeyStorage::load_private_key(InputKey input_key) { + if (is_fake_input_key(input_key)) { + return fake_private_key(); + } TRY_RESULT(decrypted_key, export_decrypted_key(std::move(input_key))); PrivateKey private_key; private_key.private_key = decrypted_key.private_key.as_octet_string(); @@ -182,4 +185,28 @@ td::Result KeyStorage::import_encrypted_key(td::Slice local_pas return save_key(std::move(decrypted_key), local_password); } +KeyStorage::PrivateKey KeyStorage::fake_private_key() { + return PrivateKey{td::SecureString(32, 0)}; +} + +KeyStorage::InputKey KeyStorage::fake_input_key() { + return InputKey{{td::SecureString(32, 0), td::SecureString(32, 0)}, {}}; +} + +bool KeyStorage::is_fake_input_key(InputKey &input_key) { + auto is_zero = [](td::Slice slice, size_t size) { + if (slice.size() != size) { + return false; + } + for (auto c : slice) { + if (c != 0) { + return false; + } + } + return true; + }; + return is_zero(input_key.local_password, 0) && is_zero(input_key.key.secret, 32) && + is_zero(input_key.key.public_key, 32); +} + } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h index 1e37082885..38478bf1f3 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/KeyStorage.h @@ -69,6 +69,10 @@ class KeyStorage { td::Result load_private_key(InputKey input_key); + static PrivateKey fake_private_key(); + static InputKey fake_input_key(); + static bool is_fake_input_key(InputKey& input_key); + private: std::shared_ptr kv_; diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/KeyValue.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/KeyValue.cpp index 796969241f..ccf9a38372 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/KeyValue.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/KeyValue.cpp @@ -2,6 +2,7 @@ #include "td/utils/filesystem.h" #include "td/utils/port/path.h" +#include "td/utils/PathView.h" #include #include @@ -51,7 +52,7 @@ class KeyValueDir : public KeyValue { return td::WalkPath::Action::SkipDir; } } else if (type == td::WalkPath::Type::NotDir) { - f(path); + f(td::PathView::relative(path, directory_)); } return td::WalkPath::Action::Continue; diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp index d498aa7a25..234af99719 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.cpp @@ -17,6 +17,7 @@ Copyright 2017-2019 Telegram Systems LLP */ #include "tonlib/LastBlock.h" +#include "tonlib/LastConfig.h" #include "tonlib/utils.h" @@ -36,11 +37,22 @@ td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state << td::tag("init_block", state.init_block_id.to_str()); } -LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr callback) - : state_(std::move(state)), config_(std::move(config)), callback_(std::move(callback)) { +LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::CancellationToken cancellation_token, + td::unique_ptr callback) + : callback_(std::move(callback)) + , state_(std::move(state)) + , config_(std::move(config)) + , cancellation_token_(std::move(cancellation_token)) { client_.set_client(client); state_.last_block_id = state_.last_key_block_id; + if (state_.last_key_block_id.is_valid()) { + min_seqno_ = state_.last_key_block_id.id.seqno; + } + if (config_.init_block_id.is_valid() && config_.init_block_id != state_.init_block_id) { + min_seqno_ = td::min(min_seqno_, config_.init_block_id.id.seqno); + } + current_seqno_ = min_seqno_; VLOG(last_block) << "State: " << state_; } @@ -61,6 +73,9 @@ void LastBlock::get_last_block(td::Promise promise) { } void LastBlock::sync_loop() { + SCOPE_EXIT { + update_sync_state(); + }; if (promises_.empty()) { return; } @@ -147,7 +162,7 @@ td::Result> LastBlock::process_block_pro return td::Status::Error(PSLICE() << "block proof chain starts from block " << chain->from.to_str() << ", not from requested block " << from.to_str()); } - TRY_STATUS(chain->validate()); + TRY_STATUS(chain->validate(cancellation_token_)); return std::move(chain); } @@ -155,6 +170,8 @@ void LastBlock::update_state(block::BlockProofChain& chain) { // Update state_ bool is_changed = false; is_changed |= update_mc_last_block(chain.to); + current_seqno_ = td::max(current_seqno_, chain.to.id.seqno); + max_seqno_ = td::max(max_seqno_, current_seqno_); if (chain.has_key_block) { is_changed |= update_mc_last_key_block(chain.key_blkid); } @@ -193,10 +210,10 @@ void LastBlock::on_block_proof( if (chain->complete) { VLOG(last_block) << "get_last_block: done\n" << get_last_block_stats_; get_last_block_state_ = QueryState::Done; - sync_loop(); } else { do_get_last_block(); } + sync_loop(); } void LastBlock::on_init_block_proof( @@ -209,6 +226,7 @@ void LastBlock::on_init_block_proof( check_init_block_state_ = QueryState::Empty; VLOG(last_block) << "check_init_block: error " << r_chain.error(); on_sync_error(r_chain.move_as_error_suffix("(during check init block)")); + sync_loop(); return; } auto chain = r_chain.move_as_ok(); @@ -220,10 +238,10 @@ void LastBlock::on_init_block_proof( if (update_init_block(config_.init_block_id)) { save_state(); } - sync_loop(); } else { do_check_init_block(chain->to, to); } + sync_loop(); } void LastBlock::on_masterchain_info( @@ -233,6 +251,7 @@ void LastBlock::on_masterchain_info( update_zero_state(create_zero_state_id(info->init_), "masterchain info"); // last block is not validated! Do not update it get_mc_info_state_ = QueryState::Done; + max_seqno_ = td::max(max_seqno_, (unsigned)info->last_->seqno_); VLOG(last_block) << "get_masterchain_info: done"; } else { get_mc_info_state_ = QueryState::Empty; @@ -253,7 +272,7 @@ void LastBlock::update_zero_state(ton::ZeroStateIdExt zero_state_id, td::Slice s } if (!state_.zero_state_id.is_valid()) { - LOG(INFO) << "Init zerostate from " << source << ": " << zero_state_id.to_str(); + VLOG(last_block) << "Init zerostate from " << source << ": " << zero_state_id.to_str(); state_.zero_state_id = std::move(zero_state_id); return; } @@ -277,7 +296,7 @@ bool LastBlock::update_mc_last_block(ton::BlockIdExt mc_block_id) { } if (!state_.last_block_id.is_valid() || state_.last_block_id.id.seqno < mc_block_id.id.seqno) { state_.last_block_id = mc_block_id; - LOG(INFO) << "Update masterchain block id: " << state_.last_block_id.to_str(); + VLOG(last_block) << "Update masterchain block id: " << state_.last_block_id.to_str(); return true; } return false; @@ -293,7 +312,7 @@ bool LastBlock::update_mc_last_key_block(ton::BlockIdExt mc_key_block_id) { } if (!state_.last_key_block_id.is_valid() || state_.last_key_block_id.id.seqno < mc_key_block_id.id.seqno) { state_.last_key_block_id = mc_key_block_id; - LOG(INFO) << "Update masterchain key block id: " << state_.last_key_block_id.to_str(); + VLOG(last_block) << "Update masterchain key block id: " << state_.last_key_block_id.to_str(); //LOG(ERROR) << td::int64(state_.last_key_block_id.id.shard) << " " //<< td::base64_encode(state_.last_key_block_id.file_hash.as_slice()) << " " //<< td::base64_encode(state_.last_key_block_id.root_hash.as_slice()); @@ -312,7 +331,7 @@ bool LastBlock::update_init_block(ton::BlockIdExt init_block_id) { } if (state_.init_block_id != init_block_id) { state_.init_block_id = init_block_id; - LOG(INFO) << "Update init block id: " << state_.init_block_id.to_str(); + VLOG(last_block) << "Update init block id: " << state_.init_block_id.to_str(); return true; } return false; @@ -334,6 +353,9 @@ void LastBlock::on_sync_ok() { } void LastBlock::on_sync_error(td::Status status) { VLOG(last_block) << "sync: error " << status; + if (cancellation_token_) { + status = TonlibError::Cancelled(); + } for (auto& promise : promises_) { promise.set_error(status.clone()); } @@ -348,4 +370,32 @@ void LastBlock::on_fatal_error(td::Status status) { bool LastBlock::has_fatal_error() const { return fatal_error_.is_error(); } + +LastBlockSyncState LastBlock::get_sync_state() { + LastBlockSyncState state; + if (promises_.empty()) { + state.type = LastBlockSyncState::Done; + return state; + } + state.type = LastBlockSyncState::InProgress; + state.from_seqno = min_seqno_; + state.to_seqno = max_seqno_; + state.current_seqno = current_seqno_; + return state; +} + +void LastBlock::update_sync_state() { + auto new_state = get_sync_state(); + if (new_state == sync_state_) { + return; + } + sync_state_ = new_state; + VLOG(last_block) << "Sync state: " << current_seqno_ - min_seqno_ << " / " << max_seqno_ - min_seqno_; + callback_->on_sync_state_changed(sync_state_); +} + +void LastBlock::tear_down() { + on_sync_error(TonlibError::Cancelled()); +} + } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h index edd8c6f387..e01a7fde71 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastBlock.h @@ -22,6 +22,7 @@ #include "tonlib/Config.h" #include "tonlib/ExtClient.h" +#include "td/utils/CancellationToken.h" #include "td/utils/tl_helpers.h" namespace block { @@ -132,6 +133,20 @@ struct LastBlockState { } }; +struct LastBlockSyncState { + enum Type { Invalid, InProgress, Done } type = Invalid; + td::int32 from_seqno{0}; + td::int32 to_seqno{0}; + td::int32 current_seqno{0}; + + auto as_key() const { + return std::tie(type, from_seqno, to_seqno, current_seqno); + } + bool operator==(const LastBlockSyncState &other) const { + return as_key() == other.as_key(); + } +}; + class LastBlock : public td::actor::Actor { public: class Callback { @@ -139,16 +154,19 @@ class LastBlock : public td::actor::Actor { virtual ~Callback() { } virtual void on_state_changed(LastBlockState state) = 0; + virtual void on_sync_state_changed(LastBlockSyncState state) = 0; }; - explicit LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr callback); + explicit LastBlock(ExtClientRef client, LastBlockState state, Config config, td::CancellationToken cancellation_token, + td::unique_ptr callback); void get_last_block(td::Promise promise); private: + td::unique_ptr callback_; ExtClient client_; LastBlockState state_; Config config_; - td::unique_ptr callback_; + td::CancellationToken cancellation_token_; td::Status fatal_error_; @@ -157,6 +175,11 @@ class LastBlock : public td::actor::Actor { QueryState check_init_block_state_{QueryState::Empty}; // init_block <---> last_key_block (from older to newer) QueryState get_last_block_state_{QueryState::Empty}; // last_key_block_id --> ? + unsigned min_seqno_ = 0; + unsigned current_seqno_ = 0; + unsigned max_seqno_ = 0; + LastBlockSyncState sync_state_; + // stats struct Stats { td::Timer total_sync_; @@ -209,6 +232,10 @@ class LastBlock : public td::actor::Actor { void on_fatal_error(td::Status status); bool has_fatal_error() const; + LastBlockSyncState get_sync_state(); + void update_sync_state(); void sync_loop(); + + void tear_down() override; }; } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastConfig.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/LastConfig.cpp new file mode 100644 index 0000000000..7207b6f0eb --- /dev/null +++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastConfig.cpp @@ -0,0 +1,152 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#include "tonlib/LastConfig.h" + +#include "tonlib/utils.h" + +#include "ton/lite-tl.hpp" +#include "block/check-proof.h" +#include "block/mc-config.h" +#include "block/block-auto.h" + +#include "lite-client/lite-client-common.h" + +#include "LastBlock.h" + +namespace tonlib { + +// init_state <-> last_key_block +// state.valitated_init_state +// last_key_block -> +// +td::StringBuilder& operator<<(td::StringBuilder& sb, const LastConfigState& state) { + return sb; +} + +LastConfig::LastConfig(ExtClientRef client, td::unique_ptr callback) : callback_(std::move(callback)) { + client_.set_client(client); + VLOG(last_block) << "State: " << state_; +} + +void LastConfig::get_last_config(td::Promise promise) { + if (promises_.empty() && get_config_state_ == QueryState::Done) { + VLOG(last_config) << "start"; + VLOG(last_config) << "get_config: reset"; + get_config_state_ = QueryState::Empty; + } + + promises_.push_back(std::move(promise)); + loop(); +} + +void LastConfig::with_last_block(td::Result r_last_block) { + if (r_last_block.is_error()) { + on_error(r_last_block.move_as_error()); + return; + } + + auto last_block = r_last_block.move_as_ok(); + auto params = params_; + client_.send_query(ton::lite_api::liteServer_getConfigParams(0, create_tl_lite_block_id(last_block.last_block_id), + std::move(params)), + [this](auto r_config) { this->on_config(std::move(r_config)); }); +} + +void LastConfig::on_config(td::Result> r_config) { + auto status = process_config(std::move(r_config)); + if (status.is_ok()) { + on_ok(); + get_config_state_ = QueryState::Done; + } else { + on_error(std::move(status)); + get_config_state_ = QueryState::Empty; + } +} + +td::Status LastConfig::process_config( + td::Result> r_config) { + TRY_RESULT(raw_config, std::move(r_config)); + TRY_STATUS_PREFIX(TRY_VM(process_config_proof(std::move(raw_config))), TonlibError::ValidateConfig()); + return td::Status::OK(); +} + +td::Status LastConfig::process_config_proof(ton::ton_api::object_ptr raw_config) { + auto blkid = create_block_id(raw_config->id_); + if (!blkid.is_masterchain_ext()) { + return td::Status::Error(PSLICE() << "reference block " << blkid.to_str() + << " for the configuration is not a valid masterchain block"); + } + TRY_RESULT(state, block::check_extract_state_proof(blkid, raw_config->state_proof_.as_slice(), + raw_config->config_proof_.as_slice())); + TRY_RESULT(config, block::Config::extract_from_state(std::move(state), 0)); + + for (auto i : params_) { + VLOG(last_config) << "ConfigParam(" << i << ") = "; + auto value = config->get_config_param(i); + if (value.is_null()) { + VLOG(last_config) << "(null)\n"; + } else { + std::ostringstream os; + if (i >= 0) { + block::gen::ConfigParam{i}.print_ref(os, value); + os << std::endl; + } + vm::load_cell_slice(value).print_rec(os); + VLOG(last_config) << os.str(); + } + } + state_.config.reset(config.release()); + return td::Status::OK(); +} + +void LastConfig::loop() { + if (promises_.empty()) { + return; + } + + if (get_config_state_ == QueryState::Empty) { + VLOG(last_block) << "get_config: start"; + get_config_state_ = QueryState::Active; + client_.with_last_block( + [self = this](td::Result r_last_block) { self->with_last_block(std::move(r_last_block)); }); + } +} + +void LastConfig::on_ok() { + VLOG(last_block) << "ok " << state_; + for (auto& promise : promises_) { + auto state = state_; + promise.set_value(std::move(state)); + } + promises_.clear(); +} + +void LastConfig::on_error(td::Status status) { + VLOG(last_config) << "error " << status; + for (auto& promise : promises_) { + promise.set_error(status.clone()); + } + promises_.clear(); +} + +void LastConfig::tear_down() { + on_error(TonlibError::Cancelled()); +} + +} // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/LastConfig.h b/submodules/ton/tonlib-src/tonlib/tonlib/LastConfig.h new file mode 100644 index 0000000000..2e0cf2a399 --- /dev/null +++ b/submodules/ton/tonlib-src/tonlib/tonlib/LastConfig.h @@ -0,0 +1,70 @@ +/* + This file is part of TON Blockchain Library. + + TON Blockchain Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + TON Blockchain Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with TON Blockchain Library. If not, see . + + Copyright 2017-2019 Telegram Systems LLP +*/ +#pragma once +#include "td/actor/actor.h" + +#include "tonlib/Config.h" +#include "tonlib/ExtClient.h" + +#include "td/utils/CancellationToken.h" +#include "td/utils/tl_helpers.h" + +#include "block/mc-config.h" + +namespace tonlib { +struct LastConfigState { + std::shared_ptr config; +}; + +td::StringBuilder& operator<<(td::StringBuilder& sb, const LastConfigState& state); + +class LastConfig : public td::actor::Actor { + public: + class Callback { + public: + virtual ~Callback() { + } + }; + + explicit LastConfig(ExtClientRef client, td::unique_ptr callback); + void get_last_config(td::Promise promise); + + private: + td::unique_ptr callback_; + ExtClient client_; + LastConfigState state_; + + enum class QueryState { Empty, Active, Done }; + QueryState get_config_state_{QueryState::Empty}; + + std::vector> promises_; + std::vector params_{18, 20, 21, 24, 25}; + + void with_last_block(td::Result r_last_block); + void on_config(td::Result> r_config); + td::Status process_config(td::Result> r_config); + td::Status process_config_proof(ton::ton_api::object_ptr config); + + void on_ok(); + void on_error(td::Status status); + + void loop() override; + void tear_down() override; +}; +} // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/Logging.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/Logging.cpp index 31dc275c00..244ce4b4f9 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/Logging.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/Logging.cpp @@ -39,7 +39,8 @@ static td::NullLog null_log; #define ADD_TAG(tag) \ { #tag, &VERBOSITY_NAME(tag) } -static const std::map log_tags{ADD_TAG(tonlib_query), ADD_TAG(last_block)}; +static const std::map log_tags{ADD_TAG(tonlib_query), ADD_TAG(last_block), ADD_TAG(last_config), + ADD_TAG(lite_server)}; #undef ADD_TAG td::Status Logging::set_current_stream(tonlib_api::object_ptr stream) { diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp index ccf44df640..12bb8fe8c1 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.cpp @@ -20,18 +20,19 @@ #include "tonlib/ExtClientLazy.h" #include "tonlib/ExtClientOutbound.h" -#include "tonlib/GenericAccount.h" #include "tonlib/LastBlock.h" +#include "tonlib/LastConfig.h" #include "tonlib/Logging.h" -#include "tonlib/TestWallet.h" -#include "tonlib/Wallet.h" -#include "tonlib/TestGiver.h" #include "tonlib/utils.h" #include "tonlib/keys/Mnemonic.h" #include "tonlib/keys/SimpleEncryption.h" - #include "tonlib/TonlibError.h" +#include "smc-envelope/GenericAccount.h" +#include "smc-envelope/TestWallet.h" +#include "smc-envelope/Wallet.h" +#include "smc-envelope/TestGiver.h" + #include "auto/tl/tonlib_api.hpp" #include "block/block-auto.h" #include "block/check-proof.h" @@ -41,12 +42,43 @@ #include "vm/boc.h" #include "td/utils/Random.h" +#include "td/utils/optional.h" #include "td/utils/overloaded.h" #include "td/utils/tests.h" #include "td/utils/port/path.h" namespace tonlib { +namespace int_api { +struct GetAccountState { + block::StdAddress address; + using ReturnType = td::unique_ptr; +}; +struct GetPrivateKey { + KeyStorage::InputKey input_key; + using ReturnType = KeyStorage::PrivateKey; +}; +struct SendMessage { + td::Ref message; + using ReturnType = td::Unit; +}; +} // namespace int_api + +class TonlibQueryActor : public td::actor::Actor { + public: + TonlibQueryActor(td::actor::ActorShared client) : client_(std::move(client)) { + } + template + void send_query(QueryT query, td::Promise promise) { + td::actor::send_lambda(client_, + [self = client_.get(), query = std::move(query), promise = std::move(promise)]() mutable { + self.get_actor_unsafe().make_request(std::move(query), std::move(promise)); + }); + } + + private: + td::actor::ActorShared client_; +}; tonlib_api::object_ptr status_to_tonlib_api(const td::Status& status) { return tonlib_api::make_object(status.code(), status.message().str()); @@ -63,12 +95,417 @@ static block::AccountState create_account_state(ton::tl_object_ptr code; - td::Ref data; + + ton::UnixTime storage_last_paid{0}; + vm::CellStorageStat storage_stat; + + td::Ref code; + td::Ref data; std::string frozen_hash; block::AccountState::Info info; }; +tonlib_api::object_ptr empty_transaction_id() { + return tonlib_api::make_object(0, std::string(32, 0)); +} + +tonlib_api::object_ptr to_transaction_id(const block::AccountState::Info& info) { + return tonlib_api::make_object(info.last_trans_lt, + info.last_trans_hash.as_slice().str()); +} + +class AccountState { + public: + AccountState(block::StdAddress address, RawAccountState&& raw) : address_(std::move(address)), raw_(std::move(raw)) { + wallet_type_ = guess_type(); + } + + auto to_uninited_accountState() const { + return tonlib_api::make_object(get_balance(), to_transaction_id(raw().info), + raw().frozen_hash, get_sync_time()); + } + + td::Result> to_raw_accountState() const { + auto state = get_smc_state(); + std::string code; + if (state.code.not_null()) { + code = vm::std_boc_serialize(state.code).move_as_ok().as_slice().str(); + } + std::string data; + if (state.data.not_null()) { + data = vm::std_boc_serialize(state.data).move_as_ok().as_slice().str(); + } + return tonlib_api::make_object(get_balance(), std::move(code), std::move(data), + to_transaction_id(raw().info), raw().frozen_hash, + get_sync_time()); + } + + td::Result> to_testWallet_accountState() const { + if (wallet_type_ != SimpleWallet) { + return TonlibError::AccountTypeUnexpected("TestWallet"); + } + TRY_RESULT(seqno, ton::TestWallet(get_smc_state()).get_seqno()); + return tonlib_api::make_object(get_balance(), static_cast(seqno), + to_transaction_id(raw().info), get_sync_time()); + } + + td::Result> to_wallet_accountState() const { + if (wallet_type_ != Wallet) { + return TonlibError::AccountTypeUnexpected("Wallet"); + } + TRY_RESULT(seqno, ton::Wallet(get_smc_state()).get_seqno()); + return tonlib_api::make_object(get_balance(), static_cast(seqno), + to_transaction_id(raw().info), get_sync_time()); + } + + td::Result> to_testGiver_accountState() const { + if (wallet_type_ != Giver) { + return TonlibError::AccountTypeUnexpected("TestGiver"); + } + TRY_RESULT(seqno, ton::TestGiver(get_smc_state()).get_seqno()); + return tonlib_api::make_object(get_balance(), static_cast(seqno), + to_transaction_id(raw().info), get_sync_time()); + } + td::Result> to_generic_accountState() const { + switch (wallet_type_) { + case Empty: + return tonlib_api::make_object(to_uninited_accountState()); + case Unknown: { + TRY_RESULT(res, to_raw_accountState()); + return tonlib_api::make_object(std::move(res)); + } + case Giver: { + TRY_RESULT(res, to_testGiver_accountState()); + return tonlib_api::make_object(std::move(res)); + } + case SimpleWallet: { + TRY_RESULT(res, to_testWallet_accountState()); + return tonlib_api::make_object(std::move(res)); + } + case Wallet: { + TRY_RESULT(res, to_wallet_accountState()); + return tonlib_api::make_object(std::move(res)); + } + } + UNREACHABLE(); + } + + enum WalletType { Empty, Unknown, Giver, SimpleWallet, Wallet }; + WalletType get_wallet_type() const { + return wallet_type_; + } + bool is_frozen() const { + return !raw_.frozen_hash.empty(); + } + + const block::StdAddress& get_address() const { + return address_; + } + + void make_non_bounceable() { + address_.bounceable = false; + } + + td::uint32 get_sync_time() const { + return raw_.info.gen_utime; + } + + td::int64 get_balance() const { + return raw_.balance; + } + + const RawAccountState& raw() const { + return raw_; + } + + WalletType guess_type_by_public_key(td::Ed25519::PublicKey& key) { + if (wallet_type_ != WalletType::Empty) { + return wallet_type_; + } + if (ton::GenericAccount::get_address(address_.workchain, ton::TestWallet::get_init_state(key)).addr == + address_.addr) { + set_new_state({ton::TestWallet::get_init_code(), ton::TestWallet::get_init_data(key)}); + wallet_type_ = WalletType::SimpleWallet; + } else if (ton::GenericAccount::get_address(address_.workchain, ton::Wallet::get_init_state(key)).addr == + address_.addr) { + set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)}); + wallet_type_ = WalletType::Wallet; + } + return wallet_type_; + } + + WalletType guess_type_default(td::Ed25519::PublicKey& key) { + if (wallet_type_ != WalletType::Empty) { + return wallet_type_; + } + set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)}); + wallet_type_ = WalletType::Wallet; + return wallet_type_; + } + + ton::SmartContract::State get_smc_state() const { + return {raw_.code, raw_.data}; + } + + void set_new_state(ton::SmartContract::State state) { + raw_.code = std::move(state.code); + raw_.data = std::move(state.data); + has_new_state_ = true; + } + + td::Ref get_new_state() const { + if (!has_new_state_) { + return {}; + } + return ton::GenericAccount::get_init_state(raw_.code, raw_.data); + } + + private: + block::StdAddress address_; + RawAccountState raw_; + WalletType wallet_type_{Unknown}; + bool has_new_state_{false}; + + WalletType guess_type() const { + if (raw_.code.is_null()) { + return WalletType::Empty; + } + auto code_hash = raw_.code->get_hash(); + if (code_hash == ton::TestGiver::get_init_code_hash()) { + return WalletType::Giver; + } + if (code_hash == ton::TestWallet::get_init_code_hash()) { + return WalletType::SimpleWallet; + } + if (code_hash == ton::Wallet::get_init_code_hash()) { + return WalletType::Wallet; + } + LOG(WARNING) << "Unknown code hash: " << td::base64_encode(code_hash.as_slice()); + return WalletType::Unknown; + } +}; + +class Query { + public: + struct Raw { + td::unique_ptr source; + td::unique_ptr destination; + + td::uint32 valid_until{std::numeric_limits::max()}; + + td::Ref message; + td::Ref new_state; + td::Ref message_body; + }; + + Query(Raw&& raw) : raw_(std::move(raw)) { + } + + td::Ref get_message() const { + return raw_.message; + } + + vm::CellHash get_body_hash() const { + return raw_.message_body->get_hash(); + } + + td::uint32 get_valid_until() const { + return raw_.valid_until; + } + + // ported from block/transaction.cpp + // TODO: reuse code + static td::RefInt256 compute_threshold(const block::GasLimitsPrices& cfg) { + auto gas_price256 = td::RefInt256{true, cfg.gas_price}; + if (cfg.gas_limit > cfg.flat_gas_limit) { + return td::rshift(gas_price256 * (cfg.gas_limit - cfg.flat_gas_limit), 16, 1) + + td::make_refint(cfg.flat_gas_price); + } else { + return td::make_refint(cfg.flat_gas_price); + } + } + + static td::uint64 gas_bought_for(td::RefInt256 nanograms, td::RefInt256 max_gas_threshold, + const block::GasLimitsPrices& cfg) { + if (nanograms.is_null() || sgn(nanograms) < 0) { + return 0; + } + if (nanograms >= max_gas_threshold) { + return cfg.gas_limit; + } + if (nanograms < cfg.flat_gas_price) { + return 0; + } + auto gas_price256 = td::RefInt256{true, cfg.gas_price}; + auto res = td::div((std::move(nanograms) - cfg.flat_gas_price) << 16, gas_price256); + return res->to_long() + cfg.flat_gas_limit; + } + + static td::RefInt256 compute_gas_price(td::uint64 gas_used, const block::GasLimitsPrices& cfg) { + auto gas_price256 = td::RefInt256{true, cfg.gas_price}; + return gas_used <= cfg.flat_gas_limit + ? td::make_refint(cfg.flat_gas_price) + : td::rshift(gas_price256 * (gas_used - cfg.flat_gas_limit), 16, 1) + cfg.flat_gas_price; + } + + static vm::GasLimits compute_gas_limits(td::RefInt256 balance, const block::GasLimitsPrices& cfg) { + vm::GasLimits res; + // Compute gas limits + if (false /*account.is_special*/) { + res.gas_max = cfg.special_gas_limit; + } else { + res.gas_max = gas_bought_for(balance, compute_threshold(cfg), cfg); + } + res.gas_credit = 0; + if (false /*trans_type != tr_ord*/) { + // may use all gas that can be bought using remaining balance + res.gas_limit = res.gas_max; + } else { + // originally use only gas bought using remaining message balance + // if the message is "accepted" by the smart contract, the gas limit will be set to gas_max + res.gas_limit = gas_bought_for(td::make_refint(0) /*msg balance remaining*/, compute_threshold(cfg), cfg); + if (true /*!block::tlb::t_Message.is_internal(in_msg)*/) { + // external messages carry no balance, give them some credit to check whether they are accepted + res.gas_credit = std::min(static_cast(cfg.gas_credit), static_cast(res.gas_max)); + } + } + LOG(DEBUG) << "gas limits: max=" << res.gas_max << ", limit=" << res.gas_limit << ", credit=" << res.gas_credit; + return res; + } + + struct Fee { + td::int64 in_fwd_fee{0}; + td::int64 storage_fee{0}; + td::int64 gas_fee{0}; + td::int64 fwd_fee{0}; + auto to_tonlib_api() const { + return tonlib_api::make_object(in_fwd_fee, storage_fee, gas_fee, fwd_fee); + } + }; + + td::Result calc_fwd_fees(td::Ref list, const block::MsgPrices& msg_prices) { + td::int64 res = 0; + std::vector> actions; + int n{0}; + int max_actions = 20; + while (true) { + actions.push_back(list); + auto cs = load_cell_slice(std::move(list)); + if (!cs.size_ext()) { + break; + } + if (!cs.have_refs()) { + return td::Status::Error("action list invalid: entry found with data but no next reference"); + } + list = cs.prefetch_ref(); + n++; + if (n > max_actions) { + return td::Status::Error(PSLICE() << "action list too long: more than " << max_actions << " actions"); + } + } + for (int i = n - 1; i >= 0; --i) { + vm::CellSlice cs = load_cell_slice(actions[i]); + CHECK(cs.fetch_ref().not_null()); + int tag = block::gen::t_OutAction.get_tag(cs); + CHECK(tag >= 0); + switch (tag) { + case block::gen::OutAction::action_set_code: + return td::Status::Error("estimate_fee: action_set_code unsupported"); + case block::gen::OutAction::action_send_msg: { + block::gen::OutAction::Record_action_send_msg act_rec; + // mode: +128 = attach all remaining balance, +64 = attach all remaining balance of the inbound message, +1 = pay message fees, +2 = skip if message cannot be sent + if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xe3) || (act_rec.mode & 0xc0) == 0xc0) { + return td::Status::Error("estimate_fee: can't parse send_msg"); + } + block::gen::MessageRelaxed::Record msg; + if (!tlb::type_unpack_cell(act_rec.out_msg, block::gen::t_MessageRelaxed_Any, msg)) { + return td::Status::Error("estimate_fee: can't parse send_msg"); + } + vm::CellStorageStat sstat; // for message size + sstat.add_used_storage(msg.init, true, 3); // message init + sstat.add_used_storage(msg.body, true, 3); // message body (the root cell itself is not counted) + res += msg_prices.compute_fwd_fees(sstat.cells, sstat.bits); + break; + } + case block::gen::OutAction::action_reserve_currency: + return td::Status::Error("estimate_fee: action_reserve_currency unsupported"); + } + } + return res; + } + td::Result> estimate_fees(bool ignore_chksig, const block::Config& cfg) { + // gas fees + bool is_masterchain = raw_.source->get_address().workchain == ton::masterchainId; + bool dest_is_masterchain = raw_.destination && raw_.destination->get_address().workchain == ton::masterchainId; + TRY_RESULT(gas_limits_prices, cfg.get_gas_limits_prices(is_masterchain)); + TRY_RESULT(dest_gas_limits_prices, cfg.get_gas_limits_prices(dest_is_masterchain)); + TRY_RESULT(msg_prices, cfg.get_msg_prices(is_masterchain || dest_is_masterchain)); + TRY_RESULT(storage_prices, cfg.get_storage_prices()); + + auto storage_fee_256 = block::StoragePrices::compute_storage_fees( + raw_.source->get_sync_time(), storage_prices, raw_.source->raw().storage_stat, + raw_.source->raw().storage_last_paid, false, is_masterchain); + auto storage_fee = storage_fee_256.is_null() ? 0 : storage_fee_256->to_long(); + + auto dest_storage_fee_256 = + raw_.destination ? block::StoragePrices::compute_storage_fees( + raw_.destination->get_sync_time(), storage_prices, raw_.destination->raw().storage_stat, + raw_.destination->raw().storage_last_paid, false, is_masterchain) + : td::make_refint(0); + auto dest_storage_fee = dest_storage_fee_256.is_null() ? 0 : dest_storage_fee_256->to_long(); + + auto smc = ton::SmartContract::create(raw_.source->get_smc_state()); + + td::int64 in_fwd_fee = 0; + { + vm::CellStorageStat sstat; // for message size + sstat.add_used_storage(raw_.message, true, 3); // message init + in_fwd_fee += msg_prices.compute_fwd_fees(sstat.cells, sstat.bits); + } + + vm::GasLimits gas_limits = compute_gas_limits(td::make_refint(raw_.source->get_balance()), gas_limits_prices); + auto res = smc.write().send_external_message( + raw_.message_body, ton::SmartContract::Args().set_limits(gas_limits).set_ignore_chksig(ignore_chksig)); + td::int64 fwd_fee = 0; + if (res.success) { + //std::cerr << "new smart contract data: "; + //load_cell_slice(res.new_state.data).print_rec(std::cerr); + //std::cerr << "output actions: "; + //int out_act_num = output_actions_count(res.actions); + //block::gen::OutList{out_act_num}.print_ref(std::cerr, res.actions); + + TRY_RESULT_ASSIGN(fwd_fee, calc_fwd_fees(res.actions, msg_prices)); + } + + auto gas_fee = res.accepted ? compute_gas_price(res.gas_used, gas_limits_prices)->to_long() : 0; + LOG(ERROR) << storage_fee << " " << in_fwd_fee << " " << gas_fee << " " << fwd_fee; + + Fee fee; + fee.in_fwd_fee = in_fwd_fee; + fee.storage_fee = storage_fee; + fee.gas_fee = gas_fee; + fee.fwd_fee = fwd_fee; + + Fee dst_fee; + if (raw_.destination && raw_.destination->get_wallet_type() != AccountState::WalletType::Empty) { + dst_fee.gas_fee = dest_gas_limits_prices.flat_gas_price; + dst_fee.storage_fee = dest_storage_fee; + } + return std::make_pair(fee, dst_fee); + } + + private: + Raw raw_; + static int output_actions_count(td::Ref list) { + int i = -1; + do { + ++i; + list = load_cell_slice(std::move(list)).prefetch_ref(); + } while (list.not_null()); + return i; + } +}; // namespace tonlib + td::Result to_balance_or_throw(td::Ref balance_ref) { vm::CellSlice balance_slice = *balance_ref; auto balance = block::tlb::t_Grams.as_integer_skip(balance_slice); @@ -139,8 +576,8 @@ class GetTransactionHistory : public td::actor::Actor { td::Result do_with_transactions(std::vector blkids, td::BufferSlice transactions) { - LOG(INFO) << "got up to " << count_ << " transactions for " << address_ << " from last transaction " << lt_ << ":" - << hash_.to_hex(); + //LOG(INFO) << "got up to " << count_ << " transactions for " << address_ << " from last transaction " << lt_ << ":" + //<< hash_.to_hex(); block::TransactionList list; list.blkids = std::move(blkids); list.hash = hash_; @@ -166,6 +603,9 @@ class GetTransactionHistory : public td::actor::Actor { hash_), [self = this](auto r_transactions) { self->with_transactions(std::move(r_transactions)); }); } + void hangup() override { + check(TonlibError::Cancelled()); + } }; class GetRawAccountState : public td::actor::Actor { @@ -208,7 +648,7 @@ class GetRawAccountState : public td::actor::Actor { auto cell = res.info.root; std::ostringstream outp; block::gen::t_Account.print_ref(outp, cell); - LOG(INFO) << outp.str(); + //LOG(INFO) << outp.str(); if (cell.is_null()) { return res; } @@ -216,6 +656,41 @@ class GetRawAccountState : public td::actor::Actor { if (!tlb::unpack_cell(cell, account)) { return td::Status::Error("Failed to unpack Account"); } + { + block::gen::StorageInfo::Record storage_info; + if (!tlb::csr_unpack(account.storage_stat, storage_info)) { + return td::Status::Error("Failed to unpack StorageInfo"); + } + res.storage_last_paid = storage_info.last_paid; + td::RefInt256 due_payment; + if (storage_info.due_payment->prefetch_ulong(1) == 1) { + vm::CellSlice& cs2 = storage_info.due_payment.write(); + cs2.advance(1); + due_payment = block::tlb::t_Grams.as_integer_skip(cs2); + if (due_payment.is_null() || !cs2.empty_ext()) { + return td::Status::Error("Failed to upack due_payment"); + } + } else { + due_payment = td::RefInt256{true, 0}; + } + block::gen::StorageUsed::Record storage_used; + if (!tlb::csr_unpack(storage_info.used, storage_used)) { + return td::Status::Error("Failed to unpack StorageInfo"); + } + unsigned long long u = 0; + vm::CellStorageStat storage_stat; + u |= storage_stat.cells = block::tlb::t_VarUInteger_7.as_uint(*storage_used.cells); + u |= storage_stat.bits = block::tlb::t_VarUInteger_7.as_uint(*storage_used.bits); + u |= storage_stat.public_cells = block::tlb::t_VarUInteger_7.as_uint(*storage_used.public_cells); + //LOG(DEBUG) << "last_paid=" << res.storage_last_paid << "; cells=" << storage_stat.cells + //<< " bits=" << storage_stat.bits << " public_cells=" << storage_stat.public_cells; + if (u == std::numeric_limits::max()) { + return td::Status::Error("Failed to unpack StorageStat"); + } + + res.storage_stat = storage_stat; + } + block::gen::AccountStorage::Record storage; if (!tlb::csr_unpack(account.storage, storage)) { return td::Status::Error("Failed to unpack AccountStorage"); @@ -245,8 +720,8 @@ class GetRawAccountState : public td::actor::Actor { if (!tlb::csr_unpack(state.x, state_init)) { return td::Status::Error("Failed to parse StateInit"); } - res.code = std::move(state_init.code); - res.data = std::move(state_init.data); + state_init.code->prefetch_maybe_ref(res.code); + state_init.data->prefetch_maybe_ref(res.data); return res; } @@ -277,6 +752,9 @@ class GetRawAccountState : public td::actor::Actor { stop(); } } + void hangup() override { + check(TonlibError::Cancelled()); + } }; TonlibClient::TonlibClient(td::unique_ptr callback) : callback_(std::move(callback)) { @@ -284,10 +762,12 @@ TonlibClient::TonlibClient(td::unique_ptr callback) : callback_( TonlibClient::~TonlibClient() = default; void TonlibClient::hangup() { + source_.cancel(); is_closing_ = true; ref_cnt_--; raw_client_ = {}; raw_last_block_ = {}; + raw_last_config_ = {}; try_stop(); } @@ -295,12 +775,13 @@ ExtClientRef TonlibClient::get_client_ref() { ExtClientRef ref; ref.andl_ext_client_ = raw_client_.get(); ref.last_block_actor_ = raw_last_block_.get(); + ref.last_config_actor_ = raw_last_config_.get(); return ref; } void TonlibClient::proxy_request(td::int64 query_id, std::string data) { - callback_->on_result(0, tonlib_api::make_object(query_id, data)); + on_update(tonlib_api::make_object(query_id, data)); } void TonlibClient::init_ext_client() { @@ -342,8 +823,28 @@ void TonlibClient::init_ext_client() { } void TonlibClient::update_last_block_state(LastBlockState state, td::uint32 config_generation) { - if (config_generation == config_generation_) { - last_block_storage_.save_state(blockchain_name_, state); + if (config_generation != config_generation_) { + return; + } + last_block_storage_.save_state(blockchain_name_, state); +} + +void TonlibClient::update_sync_state(LastBlockSyncState state, td::uint32 config_generation) { + if (config_generation != config_generation_) { + return; + } + switch (state.type) { + case LastBlockSyncState::Done: + on_update( + tonlib_api::make_object(tonlib_api::make_object())); + break; + case LastBlockSyncState::InProgress: + on_update( + tonlib_api::make_object(tonlib_api::make_object( + state.from_seqno, state.to_seqno, state.current_seqno))); + break; + default: + LOG(ERROR) << "Unknown LastBlockSyncState type " << state.type; } } @@ -357,6 +858,9 @@ void TonlibClient::init_last_block() { void on_state_changed(LastBlockState state) override { send_closure(client_, &TonlibClient::update_last_block_state, std::move(state), config_generation_); } + void on_sync_state_changed(LastBlockSyncState sync_state) override { + send_closure(client_, &TonlibClient::update_sync_state, std::move(sync_state), config_generation_); + } private: td::actor::ActorShared client_; @@ -379,19 +883,37 @@ void TonlibClient::init_last_block() { state = r_state.move_as_ok(); } - raw_last_block_ = - td::actor::create_actor("LastBlock", get_client_ref(), std::move(state), config_, - td::make_unique(td::actor::actor_shared(this), config_generation_)); + raw_last_block_ = td::actor::create_actor( + td::actor::ActorOptions().with_name("LastBlock").with_poll(false), get_client_ref(), std::move(state), config_, + source_.get_cancellation_token(), td::make_unique(td::actor::actor_shared(this), config_generation_)); +} +void TonlibClient::init_last_config() { + ref_cnt_++; + class Callback : public LastConfig::Callback { + public: + Callback(td::actor::ActorShared client) : client_(std::move(client)) { + } + + private: + td::actor::ActorShared client_; + }; + raw_last_config_ = + td::actor::create_actor(td::actor::ActorOptions().with_name("LastConfig").with_poll(false), + get_client_ref(), td::make_unique(td::actor::actor_shared(this))); } void TonlibClient::on_result(td::uint64 id, tonlib_api::object_ptr response) { - VLOG(tonlib_query) << "Tonlib answer query " << td::tag("id", id) << " " << to_string(response); + VLOG_IF(tonlib_query, id != 0) << "Tonlib answer query " << td::tag("id", id) << " " << to_string(response); + VLOG_IF(tonlib_query, id == 0) << "Tonlib update " << to_string(response); if (response->get_id() == tonlib_api::error::ID) { callback_->on_error(id, tonlib_api::move_object_as(response)); return; } callback_->on_result(id, std::move(response)); } +void TonlibClient::on_update(object_ptr response) { + on_result(0, std::move(response)); +} void TonlibClient::request(td::uint64 id, tonlib_api::object_ptr function) { VLOG(tonlib_query) << "Tonlib got query " << td::tag("id", id) << " " << to_string(function); @@ -415,7 +937,9 @@ void TonlibClient::request(td::uint64 id, tonlib_api::object_ptr::ReturnType; - td::Promise promise = [actor_id = actor_id(self), id](td::Result r_result) { + ref_cnt_++; + td::Promise promise = [actor_id = actor_id(self), id, + tmp = actor_shared(self)](td::Result r_result) { tonlib_api::object_ptr result; if (r_result.is_error()) { result = status_to_tonlib_api(r_result.error()); @@ -425,11 +949,7 @@ void TonlibClient::request(td::uint64 id, tonlib_api::object_ptrdo_request(request, std::move(promise)); - if (status.is_error()) { - CHECK(promise); - promise.set_error(std::move(status)); - } + this->make_request(request, std::move(promise)); }); } void TonlibClient::close() { @@ -502,19 +1022,20 @@ td::Result get_public_key(td::Slice public_key) { td::Result get_account_address(const tonlib_api::raw_initialAccountState& raw_state) { TRY_RESULT_PREFIX(code, vm::std_boc_deserialize(raw_state.code_), TonlibError::InvalidBagOfCells("raw_state.code")); TRY_RESULT_PREFIX(data, vm::std_boc_deserialize(raw_state.data_), TonlibError::InvalidBagOfCells("raw_state.data")); - return GenericAccount::get_address(0 /*zerochain*/, GenericAccount::get_init_state(std::move(code), std::move(data))); + return ton::GenericAccount::get_address(0 /*zerochain*/, + ton::GenericAccount::get_init_state(std::move(code), std::move(data))); } td::Result get_account_address(const tonlib_api::testWallet_initialAccountState& test_wallet_state) { TRY_RESULT(key_bytes, get_public_key(test_wallet_state.public_key_)); auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key)); - return GenericAccount::get_address(0 /*zerochain*/, TestWallet::get_init_state(key)); + return ton::GenericAccount::get_address(0 /*zerochain*/, ton::TestWallet::get_init_state(key)); } td::Result get_account_address(const tonlib_api::wallet_initialAccountState& test_wallet_state) { TRY_RESULT(key_bytes, get_public_key(test_wallet_state.public_key_)); auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key)); - return GenericAccount::get_address(0 /*zerochain*/, Wallet::get_init_state(key)); + return ton::GenericAccount::get_address(0 /*zerochain*/, ton::Wallet::get_init_state(key)); } td::Result get_account_address(td::Slice account_address) { @@ -551,7 +1072,7 @@ tonlib_api::object_ptr TonlibClient::do_static_request( tonlib_api::object_ptr TonlibClient::do_static_request( const tonlib_api::testGiver_getAccountAddress& request) { - return tonlib_api::make_object(TestGiver::address().rserialize(true)); + return tonlib_api::make_object(ton::TestGiver::address().rserialize(true)); } tonlib_api::object_ptr TonlibClient::do_static_request( @@ -639,6 +1160,7 @@ td::Status TonlibClient::set_config(object_ptr config) { ignore_cache_ = config->ignore_cache_; init_ext_client(); init_last_block(); + init_last_config(); client_.set_client(get_client_ref()); return td::Status::OK(); } @@ -647,6 +1169,7 @@ td::Status TonlibClient::do_request(const tonlib_api::close& request, td::Promise>&& promise) { CHECK(state_ != State::Closed); state_ = State::Closed; + source_.cancel(); promise.set_value(tonlib_api::make_object()); return td::Status::OK(); } @@ -661,35 +1184,6 @@ td::Status TonlibClient::do_request(tonlib_api::options_setConfig& request, return td::Status::OK(); } -tonlib_api::object_ptr empty_transaction_id() { - return tonlib_api::make_object(0, std::string(32, 0)); -} - -tonlib_api::object_ptr to_transaction_id(const block::AccountState::Info& info) { - return tonlib_api::make_object(info.last_trans_lt, - info.last_trans_hash.as_slice().str()); -} - -td::Result> to_raw_accountState(RawAccountState&& raw_state) { - std::string code; - if (raw_state.code.not_null()) { - code = vm::std_boc_serialize(vm::CellBuilder().append_cellslice(std::move(raw_state.code)).finalize()) - .move_as_ok() - .as_slice() - .str(); - } - std::string data; - if (raw_state.data.not_null()) { - data = vm::std_boc_serialize(vm::CellBuilder().append_cellslice(std::move(raw_state.data)).finalize()) - .move_as_ok() - .as_slice() - .str(); - } - return tonlib_api::make_object(raw_state.balance, std::move(code), std::move(data), - to_transaction_id(raw_state.info), raw_state.frozen_hash, - raw_state.info.gen_utime); -} - td::Result to_std_address_or_throw(td::Ref cs) { auto tag = block::gen::MsgAddressInt().get_tag(*cs); if (tag < 0) { @@ -805,9 +1299,9 @@ td::Result> to_raw_transacti TRY_RESULT_ASSIGN(fees, to_balance(trans.total_fees)); - std::ostringstream outp; - block::gen::t_Transaction.print_ref(outp, info.transaction); - LOG(INFO) << outp.str(); + //std::ostringstream outp; + //block::gen::t_Transaction.print_ref(outp, info.transaction); + //LOG(INFO) << outp.str(); auto is_just = trans.r1.in_msg->prefetch_long(1); if (is_just == trans.r1.in_msg->fetch_long_eof) { @@ -862,89 +1356,27 @@ td::Result> to_raw_transact return tonlib_api::make_object(std::move(transactions), std::move(transaction_id)); } -td::Result> to_testWallet_accountState( - RawAccountState&& raw_state) { - if (raw_state.code.is_null()) { - return TonlibError::AccountNotInited(); - } - if (raw_state.code->prefetch_ref()->get_hash() != TestWallet::get_init_code_hash()) { - return TonlibError::AccountTypeUnexpected("TestWallet"); - } - auto ref = raw_state.data->prefetch_ref(); - auto cs = vm::load_cell_slice(std::move(ref)); - auto seqno = cs.fetch_ulong(32); - if (seqno == cs.fetch_ulong_eof) { - return td::Status::Error("Failed to parse seq_no"); - } - return tonlib_api::make_object( - raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime); -} - -td::Result> to_wallet_accountState( - RawAccountState&& raw_state) { - if (raw_state.code.is_null()) { - return TonlibError::AccountNotInited(); - } - if (raw_state.code->prefetch_ref()->get_hash() != Wallet::get_init_code_hash()) { - return TonlibError::AccountTypeUnexpected("Wallet"); - } - auto ref = raw_state.data->prefetch_ref(); - auto cs = vm::load_cell_slice(std::move(ref)); - auto seqno = cs.fetch_ulong(32); - if (seqno == cs.fetch_ulong_eof) { - return td::Status::Error("Failed to parse seq_no"); - } - return tonlib_api::make_object( - raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime); -} - -td::Result> to_testGiver_accountState( - RawAccountState&& raw_state) { - if (raw_state.code.is_null()) { - return TonlibError::AccountNotInited(); - } - if (raw_state.code->prefetch_ref()->get_hash() != TestGiver::get_init_code_hash()) { - return TonlibError::AccountTypeUnexpected("TestGiver"); - } - auto ref = raw_state.data->prefetch_ref(); - auto cs = vm::load_cell_slice(std::move(ref)); - auto seqno = cs.fetch_ulong(32); - if (seqno == cs.fetch_ulong_eof) { - return td::Status::Error("Failed to parse seq_no"); - } - return tonlib_api::make_object( - raw_state.balance, static_cast(seqno), to_transaction_id(raw_state.info), raw_state.info.gen_utime); -} - -td::Result> to_generic_accountState( - RawAccountState&& raw_state) { - if (raw_state.code.is_null()) { - return tonlib_api::make_object( - tonlib_api::make_object(raw_state.balance, to_transaction_id(raw_state.info), - raw_state.frozen_hash, raw_state.info.gen_utime)); - } - - auto code_hash = raw_state.code->prefetch_ref()->get_hash(); - if (code_hash == TestWallet::get_init_code_hash()) { - TRY_RESULT(test_wallet, to_testWallet_accountState(std::move(raw_state))); - return tonlib_api::make_object(std::move(test_wallet)); - } - if (code_hash == Wallet::get_init_code_hash()) { - TRY_RESULT(wallet, to_wallet_accountState(std::move(raw_state))); - return tonlib_api::make_object(std::move(wallet)); - } - if (code_hash == TestGiver::get_init_code_hash()) { - TRY_RESULT(test_wallet, to_testGiver_accountState(std::move(raw_state))); - return tonlib_api::make_object(std::move(test_wallet)); - } - TRY_RESULT(raw, to_raw_accountState(std::move(raw_state))); - return tonlib_api::make_object(std::move(raw)); -} - // Raw +auto to_any_promise(td::Promise>&& promise) { + return promise.wrap([](auto x) { return tonlib_api::make_object(); }); +} +auto to_any_promise(td::Promise&& promise) { + return promise.wrap([](auto x) { return td::Unit(); }); +} + td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessage& request, td::Promise>&& promise) { + TRY_RESULT_PREFIX(body, vm::std_boc_deserialize(request.body_), TonlibError::InvalidBagOfCells("body")); + std::ostringstream os; + block::gen::t_Message_Any.print_ref(os, body); + LOG(ERROR) << os.str(); + make_request(int_api::SendMessage{std::move(body)}, to_any_promise(std::move(promise))); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(const tonlib_api::raw_createAndSendMessage& request, + td::Promise>&& promise) { td::Ref init_state; if (!request.initial_account_state_.empty()) { TRY_RESULT_PREFIX(new_init_state, vm::std_boc_deserialize(request.initial_account_state_), @@ -953,12 +1385,9 @@ td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessage& request, } TRY_RESULT_PREFIX(data, vm::std_boc_deserialize(request.data_), TonlibError::InvalidBagOfCells("data")); TRY_RESULT(account_address, get_account_address(request.destination_->account_address_)); - auto message = GenericAccount::create_ext_message(account_address, std::move(init_state), std::move(data)); - client_.send_query(ton::lite_api::liteServer_sendMessage(vm::std_boc_serialize(message).move_as_ok()), - [promise = std::move(promise)](auto r_info) mutable { - TRY_RESULT_PROMISE(promise, info, std::move(r_info)); - promise.set_value(tonlib_api::make_object()); - }); + auto message = ton::GenericAccount::create_ext_message(account_address, std::move(init_state), std::move(data)); + + make_request(int_api::SendMessage{std::move(message)}, to_any_promise(std::move(promise))); return td::Status::OK(); } @@ -968,13 +1397,8 @@ td::Status TonlibClient::do_request(tonlib_api::raw_getAccountState& request, return TonlibError::EmptyField("account_address"); } TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_)); - auto actor_id = actor_id_++; - actors_[actor_id] = td::actor::create_actor( - "GetAccountState", client_.get_client(), std::move(account_address), actor_shared(this, actor_id), - [promise = std::move(promise)](td::Result r_state) mutable { - TRY_RESULT_PROMISE(promise, state, std::move(r_state)); - promise.set_result(to_raw_accountState(std::move(state))); - }); + make_request(int_api::GetAccountState{std::move(account_address)}, + promise.wrap([](auto&& res) { return res->to_raw_accountState(); })); return td::Status::OK(); } @@ -998,13 +1422,9 @@ td::Status TonlibClient::do_request(tonlib_api::raw_getTransactions& request, auto actor_id = actor_id_++; actors_[actor_id] = td::actor::create_actor( "GetTransactionHistory", client_.get_client(), account_address, lt, hash, actor_shared(this, actor_id), - [promise = std::move(promise)](td::Result r_info) mutable { - TRY_RESULT_PROMISE(promise, info, std::move(r_info)); - promise.set_result(to_raw_transactions(std::move(info))); - }); + promise.wrap(to_raw_transactions)); return td::Status::OK(); } - td::Result from_tonlib(tonlib_api::inputKey& input_key) { if (!input_key.key_) { return TonlibError::EmptyField("key"); @@ -1015,22 +1435,28 @@ td::Result from_tonlib(tonlib_api::inputKey& input_key) { std::move(input_key.local_password_)}; } -// TestWallet +td::Result from_tonlib(tonlib_api::InputKey& input_key) { + td::Result r_key; + tonlib_api::downcast_call(input_key, + td::overloaded([&](tonlib_api::inputKey& input_key) { r_key = from_tonlib(input_key); }, + [&](tonlib_api::inputKeyFake&) { r_key = KeyStorage::fake_input_key(); })); + return r_key; +} + +// ton::TestWallet td::Status TonlibClient::do_request(const tonlib_api::testWallet_init& request, td::Promise>&& promise) { if (!request.private_key_) { return td::Status::Error(400, "Field private_key must not be empty"); } TRY_RESULT(input_key, from_tonlib(*request.private_key_)); - auto init_state = TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())); - auto address = GenericAccount::get_address(0 /*zerochain*/, init_state); + auto init_state = ton::TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())); + auto address = ton::GenericAccount::get_address(0 /*zerochain*/, init_state); TRY_RESULT(private_key, key_storage_.load_private_key(std::move(input_key))); - auto init_message = TestWallet::get_init_message(td::Ed25519::PrivateKey(std::move(private_key.private_key))); - return do_request( - tonlib_api::raw_sendMessage(tonlib_api::make_object(address.rserialize(true)), - vm::std_boc_serialize(init_state).move_as_ok().as_slice().str(), - vm::std_boc_serialize(init_message).move_as_ok().as_slice().str()), - std::move(promise)); + auto init_message = ton::TestWallet::get_init_message(td::Ed25519::PrivateKey(std::move(private_key.private_key))); + auto message = ton::GenericAccount::create_ext_message(address, std::move(init_state), std::move(init_message)); + make_request(int_api::SendMessage{std::move(message)}, to_any_promise(std::move(promise))); + return td::Status::OK(); } td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& request, @@ -1041,33 +1467,30 @@ td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& requ if (!request.private_key_) { return TonlibError::EmptyField("private_key"); } - if (request.message_.size() > TestWallet::max_message_size) { + if (request.message_.size() > ton::TestWallet::max_message_size) { return TonlibError::MessageTooLong(); } TRY_RESULT(account_address, get_account_address(request.destination_->account_address_)); TRY_RESULT(input_key, from_tonlib(*request.private_key_)); - auto address = GenericAccount::get_address( - 0 /*zerochain*/, TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy()))); + auto address = ton::GenericAccount::get_address( + 0 /*zerochain*/, ton::TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy()))); TRY_RESULT(private_key_str, key_storage_.load_private_key(std::move(input_key))); auto private_key = td::Ed25519::PrivateKey(std::move(private_key_str.private_key)); - std::string init_state; + td::Ref init_state; if (request.seqno_ == 0) { TRY_RESULT_PREFIX(public_key, private_key.get_public_key(), TonlibError::Internal()); - init_state = vm::std_boc_serialize(TestWallet::get_init_state(public_key)).move_as_ok().as_slice().str(); + init_state = ton::TestWallet::get_init_state(public_key); } - auto message = - TestWallet::make_a_gift_message(private_key, request.seqno_, request.amount_, request.message_, account_address); + auto message = ton::TestWallet::make_a_gift_message(private_key, request.seqno_, request.amount_, request.message_, + account_address); auto message_hash = message->get_hash().as_slice().str(); - td::Promise> new_promise = - [promise = std::move(promise), - message_hash = std::move(message_hash)](td::Result> res) mutable { - TRY_RESULT_PROMISE(promise, ok, std::move(res)); - promise.set_value(tonlib_api::make_object(0, std::move(message_hash))); - }; - return do_request(tonlib_api::raw_sendMessage( - tonlib_api::make_object(address.rserialize(true)), - std::move(init_state), vm::std_boc_serialize(std::move(message)).move_as_ok().as_slice().str()), - std::move(new_promise)); + auto new_promise = promise.wrap([message_hash = std::move(message_hash)](auto&&) { + return tonlib_api::make_object(0, std::move(message_hash)); + }); + + auto ext_message = ton::GenericAccount::create_ext_message(address, std::move(init_state), std::move(message)); + make_request(int_api::SendMessage{std::move(message)}, std::move(new_promise)); + return td::Status::OK(); } td::Status TonlibClient::do_request(tonlib_api::testWallet_getAccountState& request, @@ -1076,32 +1499,27 @@ td::Status TonlibClient::do_request(tonlib_api::testWallet_getAccountState& requ return TonlibError::EmptyField("account_address"); } TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_)); - auto actor_id = actor_id_++; - actors_[actor_id] = td::actor::create_actor( - "GetAccountState", client_.get_client(), std::move(account_address), actor_shared(this, actor_id), - [promise = std::move(promise)](td::Result r_state) mutable { - TRY_RESULT_PROMISE(promise, state, std::move(r_state)); - promise.set_result(to_testWallet_accountState(std::move(state))); - }); + make_request(int_api::GetAccountState{std::move(account_address)}, + promise.wrap([](auto&& res) { return res->to_testWallet_accountState(); })); return td::Status::OK(); } -// Wallet +// ton::Wallet td::Status TonlibClient::do_request(const tonlib_api::wallet_init& request, td::Promise>&& promise) { if (!request.private_key_) { return TonlibError::EmptyField("private_key"); } TRY_RESULT(input_key, from_tonlib(*request.private_key_)); - auto init_state = Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())); - auto address = GenericAccount::get_address(0 /*zerochain*/, init_state); + auto init_state = ton::Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())); + auto address = ton::GenericAccount::get_address(0 /*zerochain*/, init_state); TRY_RESULT(private_key, key_storage_.load_private_key(std::move(input_key))); - auto init_message = Wallet::get_init_message(td::Ed25519::PrivateKey(std::move(private_key.private_key))); - return do_request( - tonlib_api::raw_sendMessage(tonlib_api::make_object(address.rserialize(true)), - vm::std_boc_serialize(init_state).move_as_ok().as_slice().str(), - vm::std_boc_serialize(init_message).move_as_ok().as_slice().str()), - std::move(promise)); + auto init_message = ton::Wallet::get_init_message(td::Ed25519::PrivateKey(std::move(private_key.private_key))); + auto message = + ton::GenericAccount::create_ext_message(std::move(address), std::move(init_state), std::move(init_message)); + + make_request(int_api::SendMessage{std::move(message)}, to_any_promise(std::move(promise))); + return td::Status::OK(); } td::Status TonlibClient::do_request(const tonlib_api::wallet_sendGrams& request, @@ -1112,35 +1530,31 @@ td::Status TonlibClient::do_request(const tonlib_api::wallet_sendGrams& request, if (!request.private_key_) { return TonlibError::EmptyField("private_key"); } - if (request.message_.size() > Wallet::max_message_size) { + if (request.message_.size() > ton::Wallet::max_message_size) { return TonlibError::MessageTooLong(); } TRY_RESULT_PREFIX(valid_until, td::narrow_cast_safe(request.valid_until_), TonlibError::InvalidField("valid_until", "overflow")); TRY_RESULT(account_address, get_account_address(request.destination_->account_address_)); TRY_RESULT(input_key, from_tonlib(*request.private_key_)); - auto address = GenericAccount::get_address( - 0 /*zerochain*/, Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy()))); + auto address = ton::GenericAccount::get_address( + 0 /*zerochain*/, ton::Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy()))); TRY_RESULT(private_key_str, key_storage_.load_private_key(std::move(input_key))); auto private_key = td::Ed25519::PrivateKey(std::move(private_key_str.private_key)); - std::string init_state; + td::Ref init_state; if (request.seqno_ == 0) { TRY_RESULT_PREFIX(public_key, private_key.get_public_key(), TonlibError::Internal()); - init_state = vm::std_boc_serialize(Wallet::get_init_state(public_key)).move_as_ok().as_slice().str(); + init_state = ton::Wallet::get_init_state(public_key); } - auto message = Wallet::make_a_gift_message(private_key, request.seqno_, valid_until, request.amount_, - request.message_, account_address); + auto message = ton::Wallet::make_a_gift_message(private_key, request.seqno_, valid_until, request.amount_, + request.message_, account_address); auto message_hash = message->get_hash().as_slice().str(); - td::Promise> new_promise = - [promise = std::move(promise), valid_until, - message_hash = std::move(message_hash)](td::Result> res) mutable { - TRY_RESULT_PROMISE(promise, ok, std::move(res)); - promise.set_value(tonlib_api::make_object(valid_until, std::move(message_hash))); - }; - return do_request(tonlib_api::raw_sendMessage( - tonlib_api::make_object(address.rserialize(true)), - std::move(init_state), vm::std_boc_serialize(std::move(message)).move_as_ok().as_slice().str()), - std::move(new_promise)); + auto new_promise = promise.wrap([valid_until, message_hash = std::move(message_hash)](auto&&) { + return tonlib_api::make_object(valid_until, std::move(message_hash)); + }); + auto ext_message = ton::GenericAccount::create_ext_message(address, std::move(init_state), std::move(message)); + make_request(int_api::SendMessage{std::move(message)}, std::move(new_promise)); + return td::Status::OK(); } td::Status TonlibClient::do_request(tonlib_api::wallet_getAccountState& request, @@ -1149,49 +1563,37 @@ td::Status TonlibClient::do_request(tonlib_api::wallet_getAccountState& request, return TonlibError::EmptyField("account_address"); } TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_)); - auto actor_id = actor_id_++; - actors_[actor_id] = td::actor::create_actor( - "GetAccountState", client_.get_client(), std::move(account_address), actor_shared(this, actor_id), - [promise = std::move(promise)](td::Result r_state) mutable { - TRY_RESULT_PROMISE(promise, state, std::move(r_state)); - promise.set_result(to_wallet_accountState(std::move(state))); - }); + make_request(int_api::GetAccountState{std::move(account_address)}, + promise.wrap([](auto&& res) { return res->to_wallet_accountState(); })); return td::Status::OK(); } -// TestGiver +// ton::TestGiver td::Status TonlibClient::do_request(const tonlib_api::testGiver_sendGrams& request, td::Promise>&& promise) { if (!request.destination_) { return TonlibError::EmptyField("destination"); } - if (request.message_.size() > TestGiver::max_message_size) { + if (request.message_.size() > ton::TestGiver::max_message_size) { return TonlibError::MessageTooLong(); } TRY_RESULT(account_address, get_account_address(request.destination_->account_address_)); - auto message = TestGiver::make_a_gift_message(request.seqno_, request.amount_, request.message_, account_address); + auto message = + ton::TestGiver::make_a_gift_message(request.seqno_, request.amount_, request.message_, account_address); auto message_hash = message->get_hash().as_slice().str(); - td::Promise> new_promise = - [promise = std::move(promise), - message_hash = std::move(message_hash)](td::Result> res) mutable { - TRY_RESULT_PROMISE(promise, ok, std::move(res)); - promise.set_value(tonlib_api::make_object(0, std::move(message_hash))); - }; - return do_request(tonlib_api::raw_sendMessage( - tonlib_api::make_object(TestGiver::address().rserialize(true)), "", - vm::std_boc_serialize(std::move(message)).move_as_ok().as_slice().str()), - std::move(new_promise)); + auto new_promise = promise.wrap([message_hash = std::move(message_hash)](auto&&) { + return tonlib_api::make_object(0, std::move(message_hash)); + }); + + auto ext_message = ton::GenericAccount::create_ext_message(ton::TestGiver::address(), {}, std::move(message)); + make_request(int_api::SendMessage{std::move(message)}, std::move(new_promise)); + return td::Status::OK(); } td::Status TonlibClient::do_request(const tonlib_api::testGiver_getAccountState& request, td::Promise>&& promise) { - auto actor_id = actor_id_++; - actors_[actor_id] = td::actor::create_actor( - "GetAccountState", client_.get_client(), TestGiver::address(), actor_shared(this, actor_id), - [promise = std::move(promise)](td::Result r_state) mutable { - TRY_RESULT_PROMISE(promise, state, std::move(r_state)); - promise.set_result(to_testGiver_accountState(std::move(state))); - }); + make_request(int_api::GetAccountState{ton::TestGiver::address()}, + promise.wrap([](auto&& res) { return res->to_testGiver_accountState(); })); return td::Status::OK(); } @@ -1201,51 +1603,29 @@ td::Status TonlibClient::do_request(const tonlib_api::generic_getAccountState& r return TonlibError::EmptyField("account_address"); } TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_)); - auto actor_id = actor_id_++; - actors_[actor_id] = td::actor::create_actor( - "GetAccountState", client_.get_client(), std::move(account_address), actor_shared(this, actor_id), - [promise = std::move(promise)](td::Result r_state) mutable { - TRY_RESULT_PROMISE(promise, state, std::move(r_state)); - promise.set_result(to_generic_accountState(std::move(state))); - }); + make_request(int_api::GetAccountState{std::move(account_address)}, + promise.wrap([](auto&& res) { return res->to_generic_accountState(); })); return td::Status::OK(); } -class TonlibQueryActor : public td::actor::Actor { +class GenericCreateSendGrams : public TonlibQueryActor { public: - TonlibQueryActor(td::actor::ActorShared client) : client_(std::move(client)) { - } - template - void send_query(QueryT query, td::Promise promise) { - td::actor::send_lambda(client_, - [self = client_.get(), query = std::move(query), promise = std::move(promise)]() mutable { - auto status = self.get_actor_unsafe().do_request(query, std::move(promise)); - if (status.is_error()) { - promise.set_error(std::move(status)); - } - }); - } - - private: - td::actor::ActorShared client_; -}; - -class GenericSendGrams : public TonlibQueryActor { - public: - GenericSendGrams(td::actor::ActorShared client, tonlib_api::generic_sendGrams send_grams, - td::Promise>&& promise) + GenericCreateSendGrams(td::actor::ActorShared client, + tonlib_api::generic_createSendGramsQuery send_grams, + td::Promise>&& promise) : TonlibQueryActor(std::move(client)), send_grams_(std::move(send_grams)), promise_(std::move(promise)) { } private: - tonlib_api::generic_sendGrams send_grams_; - td::Promise> promise_; + tonlib_api::generic_createSendGramsQuery send_grams_; + td::Promise> promise_; - tonlib_api::object_ptr source_state_; - block::StdAddress source_address_; - - tonlib_api::object_ptr destination_state_; - bool is_destination_bounceable_{false}; + td::unique_ptr source_; + td::unique_ptr destination_; + bool has_private_key_{false}; + bool is_fake_key_{false}; + td::optional private_key_; + td::optional public_key_; void check(td::Status status) { if (status.is_error()) { @@ -1257,172 +1637,324 @@ class GenericSendGrams : public TonlibQueryActor { void start_up() override { check(do_start_up()); } + void hangup() override { + check(TonlibError::Cancelled()); + } td::Status do_start_up() { + if (send_grams_.timeout_ < 0 || send_grams_.timeout_ > 300) { + return TonlibError::InvalidField("timeout", "must be between 0 and 300"); + } if (!send_grams_.destination_) { return TonlibError::EmptyField("destination"); } - TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_)); - is_destination_bounceable_ = destination_address.bounceable; - if (!send_grams_.source_) { - return TonlibError::EmptyField("destination"); + return TonlibError::EmptyField("source"); } + if (send_grams_.amount_ < 0) { + return TonlibError::InvalidField("amount", "can't be negative"); + } + // Use this limit as a preventive check + if (send_grams_.message_.size() > ton::Wallet::max_message_size) { + return TonlibError::MessageTooLong(); + } + TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_)); TRY_RESULT(source_address, get_account_address(send_grams_.source_->account_address_)); - source_address_ = std::move(source_address); - send_query(tonlib_api::generic_getAccountState( - tonlib_api::make_object(send_grams_.source_->account_address_)), - [actor_id = actor_id(this)](auto r_res) { - send_closure(actor_id, &GenericSendGrams::on_source_state, std::move(r_res)); - }); - send_query(tonlib_api::generic_getAccountState( - tonlib_api::make_object(send_grams_.destination_->account_address_)), - [actor_id = actor_id(this)](auto r_res) { - send_closure(actor_id, &GenericSendGrams::on_destination_state, std::move(r_res)); - }); + has_private_key_ = bool(send_grams_.private_key_); + if (has_private_key_) { + TRY_RESULT(input_key, from_tonlib(*send_grams_.private_key_)); + is_fake_key_ = send_grams_.private_key_->get_id() == tonlib_api::inputKeyFake::ID; + public_key_ = td::Ed25519::PublicKey(input_key.key.public_key.copy()); + send_query(int_api::GetPrivateKey{std::move(input_key)}, [actor_id = actor_id(this)](auto r_res) { + send_closure(actor_id, &GenericCreateSendGrams::on_private_key, std::move(r_res)); + }); + } + + send_query(int_api::GetAccountState{source_address}, [actor_id = actor_id(this)](auto r_res) { + send_closure(actor_id, &GenericCreateSendGrams::on_source_state, std::move(r_res)); + }); + + send_query(int_api::GetAccountState{destination_address}, [actor_id = actor_id(this)](auto r_res) { + send_closure(actor_id, &GenericCreateSendGrams::on_destination_state, std::move(r_res)); + }); + return do_loop(); } - static tonlib_api::object_ptr clone(const tonlib_api::object_ptr& ptr) { - if (!ptr) { - return nullptr; - } - return tonlib_api::make_object(ptr->public_key_, ptr->secret_.copy()); + void on_private_key(td::Result r_key) { + check(do_on_private_key(std::move(r_key))); } - static tonlib_api::object_ptr clone(const tonlib_api::object_ptr& ptr) { - if (!ptr) { - return nullptr; - } - return tonlib_api::make_object(clone(ptr->key_), ptr->local_password_.copy()); + td::Status do_on_private_key(td::Result r_key) { + TRY_RESULT(key, std::move(r_key)); + private_key_ = td::Ed25519::PrivateKey(std::move(key.private_key)); + return do_loop(); } - void on_source_state(td::Result> r_state) { + void on_source_state(td::Result> r_state) { check(do_on_source_state(std::move(r_state))); } - td::Status do_on_source_state(td::Result> r_state) { + td::Status do_on_source_state(td::Result> r_state) { TRY_RESULT(state, std::move(r_state)); - source_state_ = std::move(state); - if (source_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && send_grams_.private_key_ && - send_grams_.private_key_->key_) { - TRY_RESULT(key_bytes, get_public_key(send_grams_.private_key_->key_->public_key_)); - auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key)); - - if (GenericAccount::get_address(0 /*zerochain*/, TestWallet::get_init_state(key)).addr == source_address_.addr) { - auto state = ton::move_tl_object_as(source_state_); - source_state_ = tonlib_api::make_object( - tonlib_api::make_object(state->account_state_->balance_, 0, nullptr, - state->account_state_->sync_utime_)); - } else if (GenericAccount::get_address(0 /*zerochain*/, Wallet::get_init_state(key)).addr == - source_address_.addr) { - auto state = ton::move_tl_object_as(source_state_); - source_state_ = tonlib_api::make_object( - tonlib_api::make_object(state->account_state_->balance_, 0, nullptr, - state->account_state_->sync_utime_)); - } + source_ = std::move(state); + if (source_->get_wallet_type() == AccountState::Empty && public_key_) { + source_->guess_type_by_public_key(public_key_.value()); } + + //TODO: pass default type through api + if (source_->get_wallet_type() == AccountState::Empty && public_key_ && is_fake_key_) { + source_->guess_type_default(public_key_.value()); + } + return do_loop(); } - void on_destination_state(td::Result> r_state) { + void on_destination_state(td::Result> r_state) { check(do_on_destination_state(std::move(r_state))); } - td::Status do_on_destination_state(td::Result> r_state) { + td::Status do_on_destination_state(td::Result> r_state) { TRY_RESULT(state, std::move(r_state)); - destination_state_ = std::move(state); - if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounceable_) { + destination_ = std::move(state); + if (destination_->is_frozen()) { //FIXME: after restoration of frozen accounts will be supported - if (!static_cast(*destination_state_) - .account_state_->frozen_hash_.empty()) { - return TonlibError::TransferToFrozen(); - //return TonlibError::DangerousTransaction("Transfer to frozen wallet"); - } - if (send_grams_.allow_send_to_uninited_) { - TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_)); - destination_address.bounceable = false; - auto new_destination_address = destination_address.rserialize(true); - LOG(INFO) << "Change destination address from bounceable to non-bounceable " - << send_grams_.destination_->account_address_ << " -> " << new_destination_address; - send_grams_.destination_->account_address_ = std::move(new_destination_address); - } else { + return TonlibError::TransferToFrozen(); + } + if (destination_->get_wallet_type() == AccountState::Empty && destination_->get_address().bounceable) { + if (!send_grams_.allow_send_to_uninited_) { return TonlibError::DangerousTransaction("Transfer to uninited wallet"); } + destination_->make_non_bounceable(); + LOG(INFO) << "Change destination address from bounceable to non-bounceable "; } return do_loop(); } td::Status do_loop() { - if (!source_state_ || !destination_state_) { + if (!source_ || !destination_) { return td::Status::OK(); } - downcast_call( - *source_state_, - td::overloaded( - [&](tonlib_api::generic_accountStateTestGiver& test_giver_state) { - auto amount = send_grams_.amount_; - send_query(tonlib_api::testGiver_sendGrams(std::move(send_grams_.destination_), - test_giver_state.account_state_->seqno_, amount, - std::move(send_grams_.message_)), - std::move(promise_)); - stop(); - }, - [&](tonlib_api::generic_accountStateTestWallet& test_wallet_state) { - auto amount = send_grams_.amount_; - auto balance = test_wallet_state.account_state_->balance_; - if (false && amount == balance) { - amount = -1; - } else if (amount >= balance) { - promise_.set_error(TonlibError::NotEnoughFunds()); - return stop(); - } - send_query(tonlib_api::testWallet_sendGrams( - std::move(send_grams_.private_key_), std::move(send_grams_.destination_), - test_wallet_state.account_state_->seqno_, amount, std::move(send_grams_.message_)), - std::move(promise_)); - stop(); - }, - [&](tonlib_api::generic_accountStateWallet& wallet_state) { - auto amount = send_grams_.amount_; - auto balance = wallet_state.account_state_->balance_; - if (false && amount == balance) { - amount = -1; - } else if (amount >= balance) { - promise_.set_error(TonlibError::NotEnoughFunds()); - return stop(); - } - send_query( - tonlib_api::wallet_sendGrams(std::move(send_grams_.private_key_), std::move(send_grams_.destination_), - wallet_state.account_state_->seqno_, - send_grams_.timeout_ == 0 - ? 60 + wallet_state.account_state_->sync_utime_ - : send_grams_.timeout_ + wallet_state.account_state_->sync_utime_, - amount, std::move(send_grams_.message_)), - std::move(promise_)); - stop(); - }, - [&](tonlib_api::generic_accountStateUninited&) { - promise_.set_error(TonlibError::AccountNotInited()); - stop(); - }, - [&](tonlib_api::generic_accountStateRaw&) { - promise_.set_error(TonlibError::AccountTypeUnknown()); - stop(); - })); + if (has_private_key_ && !private_key_) { + return td::Status::OK(); + } + + Query::Raw raw; + + auto amount = send_grams_.amount_; + if (amount > source_->get_balance()) { + return TonlibError::NotEnoughFunds(); + } + if (amount == source_->get_balance()) { + amount = -1; + } + auto message = send_grams_.message_; + switch (source_->get_wallet_type()) { + case AccountState::Empty: + return TonlibError::AccountNotInited(); + case AccountState::Unknown: + return TonlibError::AccountTypeUnknown(); + case AccountState::Giver: { + raw.message_body = ton::TestGiver::make_a_gift_message(0, amount, message, destination_->get_address()); + break; + } + + case AccountState::SimpleWallet: { + if (!private_key_) { + return TonlibError::EmptyField("private_key"); + } + if (message.size() > ton::TestWallet::max_message_size) { + return TonlibError::MessageTooLong(); + } + TRY_RESULT(seqno, ton::TestWallet(source_->get_smc_state()).get_seqno()); + raw.message_body = ton::TestWallet::make_a_gift_message(private_key_.unwrap(), seqno, amount, message, + destination_->get_address()); + break; + } + case AccountState::Wallet: { + if (!private_key_) { + return TonlibError::EmptyField("private_key"); + } + if (message.size() > ton::Wallet::max_message_size) { + return TonlibError::MessageTooLong(); + } + TRY_RESULT(seqno, ton::Wallet(source_->get_smc_state()).get_seqno()); + auto valid_until = source_->get_sync_time(); + valid_until += send_grams_.timeout_ == 0 ? 60 : send_grams_.timeout_; + raw.valid_until = valid_until; + raw.message_body = ton::Wallet::make_a_gift_message(private_key_.unwrap(), seqno, valid_until, amount, message, + destination_->get_address()); + break; + } + } + + raw.new_state = source_->get_new_state(); + raw.message = ton::GenericAccount::create_ext_message(source_->get_address(), raw.new_state, raw.message_body); + raw.source = std::move(source_); + raw.destination = std::move(destination_); + + promise_.set_value(td::make_unique(std::move(raw))); + stop(); return td::Status::OK(); } }; +td::int64 TonlibClient::register_query(td::unique_ptr query) { + auto query_id = ++next_query_id_; + queries_[query_id] = std::move(query); + return query_id; +} + +td::Result> TonlibClient::get_query_info(td::int64 id) { + auto it = queries_.find(id); + if (it == queries_.end()) { + return TonlibError::InvalidQueryId(); + } + return tonlib_api::make_object(id, it->second->get_valid_until(), + it->second->get_body_hash().as_slice().str()); +} + +void TonlibClient::finish_create_query(td::Result> r_query, + td::Promise>&& promise) { + TRY_RESULT_PROMISE(promise, query, std::move(r_query)); + auto id = register_query(std::move(query)); + promise.set_result(get_query_info(id)); +} +void TonlibClient::finish_send_query(td::Result> r_query, + td::Promise>&& promise) { + TRY_RESULT_PROMISE(promise, query, std::move(r_query)); + auto result = tonlib_api::make_object(query->get_valid_until(), + query->get_body_hash().as_slice().str()); + auto id = register_query(std::move(query)); + make_request(tonlib_api::query_send(id), + promise.wrap([result = std::move(result)](auto&&) mutable { return std::move(result); })); +} +td::Status TonlibClient::do_request(tonlib_api::generic_createSendGramsQuery& request, + td::Promise>&& promise) { + auto id = actor_id_++; + actors_[id] = td::actor::create_actor( + "GenericSendGrams", actor_shared(this, id), std::move(request), + [promise = std::move(promise), self = actor_id(this)](td::Result> r_query) mutable { + send_closure(self, &TonlibClient::finish_create_query, std::move(r_query), std::move(promise)); + }); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(const tonlib_api::raw_createQuery& request, + td::Promise>&& promise) { + if (!request.destination_) { + return TonlibError::EmptyField("destination"); + } + TRY_RESULT(account_address, get_account_address(request.destination_->account_address_)); + + td::optional smc_state; + if (!request.init_code_.empty()) { + TRY_RESULT_PREFIX(code, vm::std_boc_deserialize(request.init_code_), TonlibError::InvalidBagOfCells("init_code")); + TRY_RESULT_PREFIX(data, vm::std_boc_deserialize(request.init_data_), TonlibError::InvalidBagOfCells("init_data")); + smc_state = ton::SmartContract::State{std::move(code), std::move(data)}; + } + TRY_RESULT_PREFIX(body, vm::std_boc_deserialize(request.body_), TonlibError::InvalidBagOfCells("body")); + + td::Promise> new_promise = + [promise = std::move(promise), self = actor_id(this)](td::Result> r_query) mutable { + send_closure(self, &TonlibClient::finish_create_query, std::move(r_query), std::move(promise)); + }; + + make_request(int_api::GetAccountState{account_address}, + new_promise.wrap([smc_state = std::move(smc_state), body = std::move(body)](auto&& source) mutable { + Query::Raw raw; + if (smc_state) { + source->set_new_state(smc_state.unwrap()); + } + raw.new_state = source->get_new_state(); + raw.message_body = std::move(body); + raw.message = + ton::GenericAccount::create_ext_message(source->get_address(), raw.new_state, raw.message_body); + raw.source = std::move(source); + raw.destination = nullptr; + return td::make_unique(std::move(raw)); + })); + return td::Status::OK(); +} + td::Status TonlibClient::do_request(tonlib_api::generic_sendGrams& request, td::Promise>&& promise) { - if (request.timeout_ < 0 || request.timeout_ > 300) { - return TonlibError::InvalidField("timeout", "must be between 0 and 300"); - } auto id = actor_id_++; - actors_[id] = td::actor::create_actor("GenericSendGrams", actor_shared(this, id), - std::move(request), std::move(promise)); + actors_[id] = td::actor::create_actor( + "GenericSendGrams", actor_shared(this, id), + tonlib_api::generic_createSendGramsQuery(std::move(request.private_key_), std::move(request.source_), + std::move(request.destination_), request.amount_, request.timeout_, + request.allow_send_to_uninited_, std::move(request.message_)), + [promise = std::move(promise), self = actor_id(this)](td::Result> r_query) mutable { + send_closure(self, &TonlibClient::finish_send_query, std::move(r_query), std::move(promise)); + }); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(const tonlib_api::query_getInfo& request, + td::Promise>&& promise) { + promise.set_result(get_query_info(request.id_)); + return td::Status::OK(); +} + +void TonlibClient::query_estimate_fees(td::int64 id, bool ignore_chksig, td::Result r_state, + td::Promise>&& promise) { + auto it = queries_.find(id); + if (it == queries_.end()) { + promise.set_error(TonlibError::InvalidQueryId()); + return; + } + TRY_RESULT_PROMISE(promise, state, std::move(r_state)); + TRY_RESULT_PROMISE_PREFIX(promise, fees, TRY_VM(it->second->estimate_fees(ignore_chksig, *state.config)), + TonlibError::Internal()); + promise.set_value( + tonlib_api::make_object(fees.first.to_tonlib_api(), fees.second.to_tonlib_api())); +} + +td::Status TonlibClient::do_request(const tonlib_api::query_estimateFees& request, + td::Promise>&& promise) { + auto it = queries_.find(request.id_); + if (it == queries_.end()) { + return TonlibError::InvalidQueryId(); + } + + client_.with_last_config([this, id = request.id_, ignore_chksig = request.ignore_chksig_, + promise = std::move(promise)](td::Result r_state) mutable { + this->query_estimate_fees(id, ignore_chksig, std::move(r_state), std::move(promise)); + }); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(const tonlib_api::query_send& request, + td::Promise>&& promise) { + auto it = queries_.find(request.id_); + if (it == queries_.end()) { + return TonlibError::InvalidQueryId(); + } + + auto message = it->second->get_message(); + if (GET_VERBOSITY_LEVEL() >= VERBOSITY_NAME(DEBUG)) { + std::ostringstream ss; + block::gen::t_Message_Any.print_ref(ss, message); + LOG(DEBUG) << ss.str(); + } + make_request(int_api::SendMessage{std::move(message)}, to_any_promise(std::move(promise))); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(tonlib_api::query_forget& request, + td::Promise>&& promise) { + auto it = queries_.find(request.id_); + if (it == queries_.end()) { + return TonlibError::InvalidQueryId(); + } + promise.set_value(tonlib_api::make_object()); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(tonlib_api::sync& request, td::Promise>&& promise) { + client_.with_last_block(to_any_promise(std::move(promise))); return td::Status::OK(); } @@ -1492,13 +2024,7 @@ td::Status TonlibClient::do_request(const tonlib_api::exportPemKey& request, if (!request.input_key_) { return TonlibError::EmptyField("input_key"); } - if (!request.input_key_->key_) { - return TonlibError::EmptyField("key"); - } - - TRY_RESULT(key_bytes, get_public_key(request.input_key_->key_->public_key_)); - KeyStorage::InputKey input_key{{td::SecureString(key_bytes.key), std::move(request.input_key_->key_->secret_)}, - std::move(request.input_key_->local_password_)}; + TRY_RESULT(input_key, from_tonlib(*request.input_key_)); TRY_RESULT(exported_pem_key, key_storage_.export_pem_key(std::move(input_key), std::move(request.key_password_))); promise.set_value(tonlib_api::make_object(std::move(exported_pem_key.pem))); return td::Status::OK(); @@ -1545,26 +2071,16 @@ td::Status TonlibClient::do_request(const tonlib_api::changeLocalPassword& reque if (!request.input_key_) { return TonlibError::EmptyField("input_key"); } - if (!request.input_key_->key_) { - return TonlibError::EmptyField("key"); - } TRY_RESULT(input_key, from_tonlib(*request.input_key_)); TRY_RESULT(key, key_storage_.change_local_password(std::move(input_key), std::move(request.new_local_password_))); - promise.set_value( - tonlib_api::make_object(request.input_key_->key_->public_key_, std::move(key.secret))); + promise.set_value(tonlib_api::make_object(key.public_key.as_slice().str(), std::move(key.secret))); return td::Status::OK(); } td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryResult& request, td::Promise>&& promise) { send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_, td::BufferSlice(request.bytes_), - [promise = std::move(promise)](td::Result res) mutable { - if (res.is_ok()) { - promise.set_value(tonlib_api::make_object()); - } else { - promise.set_error(res.move_as_error()); - } - }); + to_any_promise(std::move(promise))); return td::Status::OK(); } td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryError& request, @@ -1572,13 +2088,7 @@ td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryError& re send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_, td::Status::Error(request.error_->code_, request.error_->message_) .move_as_error_prefix(TonlibError::LiteServerNetwork()), - [promise = std::move(promise)](td::Result res) mutable { - if (res.is_ok()) { - promise.set_value(tonlib_api::make_object()); - } else { - promise.set_error(res.move_as_error()); - } - }); + to_any_promise(std::move(promise))); return td::Status::OK(); } @@ -1661,4 +2171,131 @@ tonlib_api::object_ptr TonlibClient::do_static_request(const SimpleEncryption::kdf(request.password_, request.salt_, request.iterations_)); } +td::Status TonlibClient::do_request(int_api::GetAccountState request, + td::Promise>&& promise) { + auto actor_id = actor_id_++; + actors_[actor_id] = td::actor::create_actor( + "GetAccountState", client_.get_client(), request.address, actor_shared(this, actor_id), + promise.wrap([address = request.address](auto&& state) mutable { + return td::make_unique(std::move(address), std::move(state)); + })); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(int_api::GetPrivateKey request, td::Promise&& promise) { + TRY_RESULT(pk, key_storage_.load_private_key(std::move(request.input_key))); + promise.set_value(std::move(pk)); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(int_api::SendMessage request, td::Promise&& promise) { + client_.send_query(ton::lite_api::liteServer_sendMessage(vm::std_boc_serialize(request.message).move_as_ok()), + to_any_promise(std::move(promise))); + return td::Status::OK(); +} + +td::Status TonlibClient::do_request(const tonlib_api::liteServer_getInfo& request, + td::Promise>&& promise) { + client_.send_query(ton::lite_api::liteServer_getVersion(), promise.wrap([](auto&& version) { + return tonlib_api::make_object(version->now_, version->version_, + version->capabilities_); + })); + return td::Status::OK(); +} + +template +td::Status TonlibClient::do_request(const tonlib_api::runTests& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::raw_getAccountAddress& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::testWallet_getAccountAddress& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::wallet_getAccountAddress& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::packAccountAddress& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::unpackAccountAddress& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(tonlib_api::getBip39Hints& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(tonlib_api::setLogStream& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::getLogStream& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::setLogVerbosityLevel& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::setLogTagVerbosityLevel& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::getLogVerbosityLevel& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::getLogTagVerbosityLevel& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::getLogTags& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::addLogMessage& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::encrypt& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::decrypt& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} +template +td::Status TonlibClient::do_request(const tonlib_api::kdf& request, P&&) { + UNREACHABLE(); + return TonlibError::Internal(); +} } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h index e2ea77d1c6..7c22e09aa7 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibClient.h @@ -29,9 +29,22 @@ #include "td/actor/actor.h" +#include "td/utils/CancellationToken.h" + #include namespace tonlib { +namespace int_api { +struct GetAccountState; +struct GetPrivateKey; +struct SendMessage; +inline std::string to_string(const int_api::SendMessage&) { + return "Send message"; +} +} // namespace int_api +class AccountState; +class Query; + class TonlibClient : public td::actor::Actor { public: template @@ -64,14 +77,18 @@ class TonlibClient : public td::actor::Actor { td::actor::ActorOwn raw_client_; td::actor::ActorId ext_client_outbound_; td::actor::ActorOwn raw_last_block_; + td::actor::ActorOwn raw_last_config_; ExtClient client_; + td::CancellationTokenSource source_; + std::map> actors_; td::int64 actor_id_{1}; ExtClientRef get_client_ref(); void init_ext_client(); void init_last_block(); + void init_last_config(); bool is_closing_{false}; td::uint32 ref_cnt_{1}; @@ -92,7 +109,9 @@ class TonlibClient : public td::actor::Actor { } void update_last_block_state(LastBlockState state, td::uint32 config_generation_); + void update_sync_state(LastBlockSyncState state, td::uint32 config_generation); void on_result(td::uint64 id, object_ptr response); + void on_update(object_ptr response); static bool is_static_request(td::int32 id); static bool is_uninited_request(td::int32 id); template @@ -121,9 +140,53 @@ class TonlibClient : public td::actor::Actor { static object_ptr do_static_request(const tonlib_api::decrypt& request); static object_ptr do_static_request(const tonlib_api::kdf& request); + template + td::Status do_request(const tonlib_api::runTests& request, P&&); + template + td::Status do_request(const tonlib_api::raw_getAccountAddress& request, P&&); + template + td::Status do_request(const tonlib_api::testWallet_getAccountAddress& request, P&&); + template + td::Status do_request(const tonlib_api::wallet_getAccountAddress& request, P&&); + template + td::Status do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&); + template + td::Status do_request(const tonlib_api::packAccountAddress& request, P&&); + template + td::Status do_request(const tonlib_api::unpackAccountAddress& request, P&&); + template + td::Status do_request(tonlib_api::getBip39Hints& request, P&&); + + template + td::Status do_request(tonlib_api::setLogStream& request, P&&); + template + td::Status do_request(const tonlib_api::getLogStream& request, P&&); + template + td::Status do_request(const tonlib_api::setLogVerbosityLevel& request, P&&); + template + td::Status do_request(const tonlib_api::setLogTagVerbosityLevel& request, P&&); + template + td::Status do_request(const tonlib_api::getLogVerbosityLevel& request, P&&); + template + td::Status do_request(const tonlib_api::getLogTagVerbosityLevel& request, P&&); + template + td::Status do_request(const tonlib_api::getLogTags& request, P&&); + template + td::Status do_request(const tonlib_api::addLogMessage& request, P&&); + + template + td::Status do_request(const tonlib_api::encrypt& request, P&&); + template + td::Status do_request(const tonlib_api::decrypt& request, P&&); + template + td::Status do_request(const tonlib_api::kdf& request, P&&); + template - td::Status do_request(const T& request, P&& promise) { - return td::Status::Error(400, "Function is unsupported"); + void make_request(T&& request, P&& promise) { + auto status = do_request(std::forward(request), std::move(promise)); + if (status.is_error()) { + promise.operator()(std::move(status)); + } } td::Status set_config(object_ptr config); @@ -132,6 +195,11 @@ class TonlibClient : public td::actor::Actor { td::Status do_request(tonlib_api::options_setConfig& request, td::Promise>&& promise); td::Status do_request(const tonlib_api::raw_sendMessage& request, td::Promise>&& promise); + td::Status do_request(const tonlib_api::raw_createAndSendMessage& request, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::raw_createQuery& request, + td::Promise>&& promise); + td::Status do_request(tonlib_api::raw_getAccountState& request, td::Promise>&& promise); td::Status do_request(tonlib_api::raw_getTransactions& request, @@ -159,6 +227,8 @@ class TonlibClient : public td::actor::Actor { td::Status do_request(tonlib_api::generic_sendGrams& request, td::Promise>&& promise); + td::Status do_request(tonlib_api::sync& request, td::Promise>&& promise); + td::Status do_request(const tonlib_api::createNewKey& request, td::Promise>&& promise); td::Status do_request(const tonlib_api::exportKey& request, td::Promise>&& promise); @@ -183,6 +253,34 @@ class TonlibClient : public td::actor::Actor { td::Status do_request(const tonlib_api::onLiteServerQueryError& request, td::Promise>&& promise); + td::int64 next_query_id_{0}; + std::map> queries_; + td::int64 register_query(td::unique_ptr query); + td::Result> get_query_info(td::int64 id); + void finish_create_query(td::Result> r_query, + td::Promise>&& promise); + void finish_send_query(td::Result> r_query, + td::Promise>&& promise); + void query_estimate_fees(td::int64 id, bool ignore_chksig, td::Result r_state, + td::Promise>&& promise); + + td::Status do_request(const tonlib_api::query_getInfo& request, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::query_estimateFees& request, + td::Promise>&& promise); + td::Status do_request(const tonlib_api::query_send& request, td::Promise>&& promise); + td::Status do_request(tonlib_api::query_forget& request, td::Promise>&& promise); + + td::Status do_request(tonlib_api::generic_createSendGramsQuery& request, + td::Promise>&& promise); + + td::Status do_request(int_api::GetAccountState request, td::Promise>&&); + td::Status do_request(int_api::GetPrivateKey request, td::Promise&&); + td::Status do_request(int_api::SendMessage request, td::Promise&& promise); + + td::Status do_request(const tonlib_api::liteServer_getInfo& request, + td::Promise>&& promise); + void proxy_request(td::int64 query_id, std::string data); friend class TonlibQueryActor; diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibError.h b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibError.h index b521c13689..01447cb1b7 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/TonlibError.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/TonlibError.h @@ -27,6 +27,7 @@ // INVALID_MNEMONIC // INVALID_BAG_OF_CELLS // INVALID_PUBLIC_KEY +// INVALID_QUERY_ID // INVALID_ACCOUNT_ADDRESS // INVALID_CONFIG // INVALID_PEM_KEY @@ -65,6 +66,9 @@ struct TonlibError { static td::Status InvalidAccountAddress() { return td::Status::Error(400, "INVALID_ACCOUNT_ADDRESS"); } + static td::Status InvalidQueryId() { + return td::Status::Error(400, "INVALID_QUERY_ID"); + } static td::Status InvalidConfig(td::Slice reason) { return td::Status::Error(400, PSLICE() << "INVALID_CONFIG: " << reason); } @@ -110,6 +114,9 @@ struct TonlibError { static td::Status ValidateTransactions() { return td::Status::Error(500, "VALIDATE_TRANSACTION"); } + static td::Status ValidateConfig() { + return td::Status::Error(500, "VALIDATE_CONFIG"); + } static td::Status ValidateZeroState(td::Slice message) { return td::Status::Error(500, PSLICE() << "VALIDATE_ZERO_STATE: " << message); } diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp index f681474e76..f9bcae9447 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/tonlib-cli.cpp @@ -20,6 +20,57 @@ #include #include +// Consider this as a TODO list: +// +// (from lite-client) +// SUPPORTED +// "time\tGet server time\n" +// "remote-version\tShows server time, version and capabilities\n" +// "help []\tThis help\n" // TODO: support [] +// "quit\tExit\n"; +// "sendfile \tLoad a serialized message from and send it to server\n" +// +// "saveaccount[code|data] []\tSaves into specified file the most recent state " +// "runmethod ...\tRuns GET method of account " +// "with specified parameters\n" +// +// WONTSUPPORT +// +// UNSUPPORTED +//"last\tGet last block and state info from server\n" +//"status\tShow connection and local database status\n" +//"getaccount []\tLoads the most recent state of specified account; is in " +//"[:] format\n" +//"(StateInit) or just the code or data of specified account; is in " +//"[:] format\n" +//"allshards []\tShows shard configuration from the most recent masterchain " +//"state or from masterchain state corresponding to \n" +//"getconfig [...]\tShows specified or all configuration parameters from the latest masterchain state\n" +//"getconfigfrom [...]\tShows specified or all configuration parameters from the " +//"masterchain state of \n" +//"saveconfig []\tSaves all configuration parameters into specified file\n" +//"gethead \tShows block header for \n" +//"getblock \tDownloads block\n" +//"dumpblock \tDownloads and dumps specified block\n" +//"getstate \tDownloads state corresponding to specified block\n" +//"dumpstate \tDownloads and dumps state corresponding to specified block\n" +//"dumptrans \tDumps one transaction of specified account\n" +//"lasttrans[dump] []\tShows or dumps specified transaction and " +//"several preceding " +//"ones\n" +//"listblocktrans[rev] [ ]\tLists block transactions, " +//"starting immediately after or before the specified one\n" +//"blkproofchain[step] []\tDownloads and checks proof of validity of the /"second " +//"indicated block (or the last known masterchain block) starting from given block\n" +//"byseqno \tLooks up a block by workchain, shard and seqno, and shows its " +//"header\n" +//"bylt \tLooks up a block by workchain, shard and logical time, and shows its " +//"header\n" +//"byutime \tLooks up a block by workchain, shard and creation time, and " +//"shows its header\n" +//"known\tShows the list of all known block ids\n" +//"privkey \tLoads a private key from file\n" + class TonlibCli : public td::actor::Actor { public: struct Options { @@ -94,7 +145,7 @@ class TonlibCli : public td::actor::Actor { td::actor::ActorShared id_; }; ref_cnt_++; - client_ = td::actor::create_actor("Tonlib", td::make_unique(actor_shared(this))); + client_ = td::actor::create_actor("Tonlib", td::make_unique(actor_shared(this, 1))); td::mkdir(options_.key_dir).ignore(); @@ -144,6 +195,9 @@ class TonlibCli : public td::actor::Actor { void hangup_shared() override { CHECK(ref_cnt_ > 0); ref_cnt_--; + if (get_link_token() == 1) { + io_.reset(); + } try_stop(); } void try_stop() { @@ -198,8 +252,23 @@ class TonlibCli : public td::actor::Actor { } return true; }; + + td::Promise cmd_promise = [line = line.clone()](td::Result res) { + if (res.is_ok()) { + // on_ok + } else { + td::TerminalIO::out() << "Query {" << line.as_slice() << "} FAILED: \n\t" << res.error() << "\n"; + } + }; + if (cmd == "help") { - td::TerminalIO::out() << "help - show this help\n"; + td::TerminalIO::out() << "help\tThis help\n"; + td::TerminalIO::out() << "time\tGet server time\n"; + td::TerminalIO::out() << "remote-version\tShows server time, version and capabilities\n"; + td::TerminalIO::out() << "sendfile \tLoad a serialized message from and send it to server\n"; + td::TerminalIO::out() << "exit\tExit\n"; + td::TerminalIO::out() << "quit\tExit\n"; + td::TerminalIO::out() << "genkey - generate new secret key\n"; td::TerminalIO::out() << "keys - show all stored keys\n"; td::TerminalIO::out() << "unpackaddress
- validate and parse address\n"; @@ -207,6 +276,7 @@ class TonlibCli : public td::actor::Actor { td::TerminalIO::out() << "importkey - import key\n"; td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n"; td::TerminalIO::out() << "exportkey [] - export key\n"; + td::TerminalIO::out() << "exportkeypem [] - export key\n"; td::TerminalIO::out() << "setconfig [] [] [] - set lite server config\n"; td::TerminalIO::out() << "getstate - get state of simple wallet with requested key\n"; td::TerminalIO::out() @@ -216,12 +286,10 @@ class TonlibCli : public td::actor::Actor { " to .\n" << "\t could also be 'giver'\n" << "\t could also be 'giver' or smartcontract address\n"; - td::TerminalIO::out() << "exit - exit from this programm\n"; } else if (cmd == "genkey") { generate_key(); - } else if (cmd == "exit") { + } else if (cmd == "exit" || cmd == "quit") { is_closing_ = true; - io_.reset(); client_.reset(); ref_cnt_--; try_stop(); @@ -231,8 +299,8 @@ class TonlibCli : public td::actor::Actor { //delete_key(parser.read_word()); } else if (cmd == "deletekeys") { delete_all_keys(); - } else if (cmd == "exportkey") { - export_key(parser.read_word()); + } else if (cmd == "exportkey" || cmd == "exportkeypem") { + export_key(cmd.str(), parser.read_word()); } else if (cmd == "importkey") { import_key(parser.read_all()); } else if (cmd == "setconfig") { @@ -263,7 +331,53 @@ class TonlibCli : public td::actor::Actor { set_bounceable(addr, to_bool(bounceable, true)); } else if (cmd == "netstats") { dump_netstats(); + // reviewed from here + } else if (cmd == "sync") { + sync(std::move(cmd_promise)); + } else if (cmd == "time") { + remote_time(std::move(cmd_promise)); + } else if (cmd == "remote-version") { + remote_version(std::move(cmd_promise)); + } else if (cmd == "sendfile") { + send_file(parser.read_word(), std::move(cmd_promise)); + } else { + cmd_promise.set_error(td::Status::Error(PSLICE() << "Unkwnown query `" << cmd << "`")); } + if (cmd_promise) { + cmd_promise.set_value(td::Unit()); + } + } + + void remote_time(td::Promise promise) { + send_query(tonlib_api::make_object(), promise.wrap([](auto&& info) { + td::TerminalIO::out() << "Lite server time is: " << info->now_ << "\n"; + return td::Unit(); + })); + } + + void remote_version(td::Promise promise) { + send_query(tonlib_api::make_object(), promise.wrap([](auto&& info) { + td::TerminalIO::out() << "Lite server time is: " << info->now_ << "\n"; + td::TerminalIO::out() << "Lite server version is: " << info->version_ << "\n"; + td::TerminalIO::out() << "Lite server capabilities are: " << info->capabilities_ << "\n"; + return td::Unit(); + })); + } + + void send_file(td::Slice name, td::Promise promise) { + TRY_RESULT_PROMISE(promise, data, td::read_file_str(name.str())); + send_query(tonlib_api::make_object(std::move(data)), promise.wrap([](auto&& info) { + td::TerminalIO::out() << "Query was sent\n"; + return td::Unit(); + })); + } + + void sync(td::Promise promise) { + using tonlib_api::make_object; + send_query(make_object(), promise.wrap([](auto&&) { + td::TerminalIO::out() << "synchronized\n"; + return td::Unit(); + })); } void dump_netstats() { @@ -285,15 +399,41 @@ class TonlibCli : public td::actor::Actor { void on_tonlib_result(std::uint64_t id, tonlib_api::object_ptr result) { if (id == 0) { - if (result->get_id() == tonlib_api::updateSendLiteServerQuery::ID) { - auto update = tonlib_api::move_object_as(std::move(result)); - CHECK(!raw_client_.empty()); - snd_bytes_ += update->data_.size(); - send_closure(raw_client_, &ton::adnl::AdnlExtClient::send_query, "query", td::BufferSlice(update->data_), - td::Timestamp::in(5), - [actor_id = actor_id(this), id = update->id_](td::Result res) { - send_closure(actor_id, &TonlibCli::on_adnl_result, id, std::move(res)); - }); + switch (result->get_id()) { + case tonlib_api::updateSendLiteServerQuery::ID: { + auto update = tonlib_api::move_object_as(std::move(result)); + CHECK(!raw_client_.empty()); + snd_bytes_ += update->data_.size(); + send_closure(raw_client_, &ton::adnl::AdnlExtClient::send_query, "query", td::BufferSlice(update->data_), + td::Timestamp::in(5), + [actor_id = actor_id(this), id = update->id_](td::Result res) { + send_closure(actor_id, &TonlibCli::on_adnl_result, id, std::move(res)); + }); + return; + } + case tonlib_api::updateSyncState::ID: { + auto update = tonlib_api::move_object_as(std::move(result)); + switch (update->sync_state_->get_id()) { + case tonlib_api::syncStateDone::ID: { + td::TerminalIO::out() << "synchronization: DONE\n"; + break; + } + case tonlib_api::syncStateInProgress::ID: { + auto progress = tonlib_api::move_object_as(update->sync_state_); + auto from = progress->from_seqno_; + auto to = progress->to_seqno_; + auto at = progress->current_seqno_; + auto d = to - from; + if (d <= 0) { + td::TerminalIO::out() << "synchronization: ???\n"; + } else { + td::TerminalIO::out() << "synchronization: " << 100 * (at - from) / d << "%\n"; + } + break; + } + } + return; + } } } auto it = query_handlers_.find(id); @@ -394,7 +534,7 @@ class TonlibCli : public td::actor::Actor { info.public_key = key->public_key_; info.secret = std::move(key->secret_); keys_.push_back(std::move(info)); - export_key(key->public_key_, keys_.size() - 1, std::move(password)); + export_key("exportkey", key->public_key_, keys_.size() - 1, std::move(password)); store_keys(); }); } @@ -583,11 +723,11 @@ class TonlibCli : public td::actor::Actor { td::TerminalIO::out() << "Ok\n"; }); } - void export_key(td::Slice key) { + void export_key(std::string cmd, td::Slice key) { if (key.empty()) { dump_keys(); td::TerminalIO::out() << "Choose public key (hex prefix or #N)"; - cont_ = [this](td::Slice key) { this->export_key(key); }; + cont_ = [this, cmd](td::Slice key) { this->export_key(cmd, key); }; return; } auto r_key_i = to_key_i(key); @@ -601,24 +741,40 @@ class TonlibCli : public td::actor::Actor { << "public key: " << td::buffer_to_hex(keys_[key_i].public_key) << "\n"; td::TerminalIO::out() << "Enter password (could be empty)"; - cont_ = [this, key = key.str(), key_i](td::Slice password) { this->export_key(key, key_i, password); }; + cont_ = [this, cmd, key = key.str(), key_i](td::Slice password) { this->export_key(cmd, key, key_i, password); }; } - void export_key(std::string key, size_t key_i, td::Slice password) { + void export_key(std::string cmd, std::string key, size_t key_i, td::Slice password) { using tonlib_api::make_object; - send_query(make_object(make_object( - make_object(keys_[key_i].public_key, keys_[key_i].secret.copy()), - td::SecureString(password))), - [this, key = std::move(key), key_i](auto r_res) { - if (r_res.is_error()) { - td::TerminalIO::out() << "Can't export key id: [" << key << "] " << r_res.error() << "\n"; - return; - } - dump_key(key_i); - for (auto& word : r_res.ok()->word_list_) { - td::TerminalIO::out() << " " << word.as_slice() << "\n"; - } - }); + if (cmd == "exportkey") { + send_query(make_object(make_object( + make_object(keys_[key_i].public_key, keys_[key_i].secret.copy()), + td::SecureString(password))), + [this, key = std::move(key), key_i](auto r_res) { + if (r_res.is_error()) { + td::TerminalIO::out() << "Can't export key id: [" << key << "] " << r_res.error() << "\n"; + return; + } + dump_key(key_i); + for (auto& word : r_res.ok()->word_list_) { + td::TerminalIO::out() << " " << word.as_slice() << "\n"; + } + }); + } else { + send_query(make_object( + make_object( + make_object(keys_[key_i].public_key, keys_[key_i].secret.copy()), + td::SecureString(password)), + td::SecureString("cucumber")), + [this, key = std::move(key), key_i](auto r_res) { + if (r_res.is_error()) { + td::TerminalIO::out() << "Can't export key id: [" << key << "] " << r_res.error() << "\n"; + return; + } + dump_key(key_i); + td::TerminalIO::out() << "\n" << r_res.ok()->pem_.as_slice() << "\n"; + }); + } } void import_key(td::Slice slice, std::vector words = {}) { @@ -656,7 +812,7 @@ class TonlibCli : public td::actor::Actor { info.public_key = key->public_key_; info.secret = std::move(key->secret_); keys_.push_back(std::move(info)); - export_key(key->public_key_, keys_.size() - 1, std::move(password)); + export_key("exportkey", key->public_key_, keys_.size() - 1, std::move(password)); store_keys(); }); } @@ -820,18 +976,39 @@ class TonlibCli : public td::actor::Actor { ? make_object( make_object(from.public_key, from.secret.copy()), td::SecureString(password)) : nullptr; - send_query( - make_object(std::move(key), std::move(from.address), std::move(to.address), - grams, 60, allow_send_to_uninited, std::move(msg)), - [this](auto r_res) { - if (r_res.is_error()) { - td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n"; - on_error(); - return; - } - td::TerminalIO::out() << to_string(r_res.ok()); - on_ok(); - }); + send_query(make_object(std::move(key), std::move(from.address), + std::move(to.address), grams, 60, + allow_send_to_uninited, std::move(msg)), + [self = this](auto r_res) { + if (r_res.is_error()) { + td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n"; + self->on_error(); + return; + } + td::TerminalIO::out() << to_string(r_res.ok()); + self->send_query(make_object(r_res.ok()->id_, false), + [self](auto r_res) { + if (r_res.is_error()) { + td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n"; + self->on_error(); + return; + } + td::TerminalIO::out() << to_string(r_res.ok()); + self->on_ok(); + }); + + self->send_query(make_object(r_res.ok()->id_), [self](auto r_res) { + if (r_res.is_error()) { + td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n"; + self->on_error(); + return; + } + td::TerminalIO::out() << to_string(r_res.ok()); + self->on_ok(); + }); + + self->on_ok(); + }); } void init_simple_wallet(td::Slice key) { diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/utils.cpp b/submodules/ton/tonlib-src/tonlib/tonlib/utils.cpp index 5cef21f56d..fec9144311 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/utils.cpp +++ b/submodules/ton/tonlib-src/tonlib/tonlib/utils.cpp @@ -20,20 +20,9 @@ #include "td/utils/misc.h" #include "vm/cellslice.h" namespace tonlib { -int VERBOSITY_NAME(tonlib_query) = VERBOSITY_NAME(INFO); -int VERBOSITY_NAME(last_block) = VERBOSITY_NAME(INFO); -int VERBOSITY_NAME(lite_server) = VERBOSITY_NAME(INFO); +int VERBOSITY_NAME(tonlib_query) = VERBOSITY_NAME(DEBUG); +int VERBOSITY_NAME(last_block) = VERBOSITY_NAME(DEBUG); +int VERBOSITY_NAME(last_config) = VERBOSITY_NAME(DEBUG); +int VERBOSITY_NAME(lite_server) = VERBOSITY_NAME(DEBUG); -td::Result> binary_bitstring_to_cellslice(td::Slice literal) { - unsigned char buff[128]; - if (!begins_with(literal, "b{") || !ends_with(literal, "}")) { - return td::Status::Error("Invalid binary bitstring constant"); - } - int bits = - (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff), literal.begin() + 2, literal.end() - 1); - if (bits < 0) { - return td::Status::Error("Invalid binary bitstring constant"); - } - return td::Ref{true, vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize()}; -} } // namespace tonlib diff --git a/submodules/ton/tonlib-src/tonlib/tonlib/utils.h b/submodules/ton/tonlib-src/tonlib/tonlib/utils.h index 840bc10d20..8bcf9ab9b8 100644 --- a/submodules/ton/tonlib-src/tonlib/tonlib/utils.h +++ b/submodules/ton/tonlib-src/tonlib/tonlib/utils.h @@ -23,19 +23,8 @@ #include "block/block-parse.h" namespace tonlib { -template -auto try_f(F&& f) noexcept -> decltype(f()) { - try { - return f(); - } catch (vm::VmError error) { - return td::Status::Error(PSLICE() << "Got a vm exception: " << error.get_msg()); - } -} - -#define TRY_VM(f) try_f([&] { return f; }) - extern int VERBOSITY_NAME(tonlib_query); extern int VERBOSITY_NAME(last_block); +extern int VERBOSITY_NAME(last_config); extern int VERBOSITY_NAME(lite_server); -td::Result> binary_bitstring_to_cellslice(td::Slice literal); } // namespace tonlib