Update wallet API

This commit is contained in:
Peter 2019-10-31 22:34:12 +04:00
parent 2c294c7e48
commit e2fad91f81
95 changed files with 8637 additions and 5180 deletions

View File

@ -4789,7 +4789,7 @@ Any member of this group will be able to see messages in the channel.";
"Wallet.Info.Send" = "Send";
"Wallet.Info.RefreshErrorTitle" = "No network";
"Wallet.Info.RefreshErrorText" = "Couldn't refresh balance. Please make sure your internet connection is working and try again.";
"Wallet.Info.RefreshErrorNetworkText" = "The wallet state can not be retrieved at this time. Please try again later.";
"Wallet.Info.RefreshErrorNetworkText" = "Wallet state can not be retrieved at this time. Please try again later.";
"Wallet.Info.UnknownTransaction" = "Empty Transaction";
"Wallet.Info.TransactionTo" = "to";
"Wallet.Info.TransactionFrom" = "from";
@ -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$@?\n\nFees: ~%3$@ grams";
"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n\n%2$@?\n\nBlockchain fees: ~%3$@ grams";
"Wallet.Send.ConfirmationConfirm" = "Confirm";
"Wallet.Send.Send" = "Send";
"Wallet.Send.OwnAddressAlertTitle" = "Warning";
@ -4828,8 +4828,9 @@ Any member of this group will be able to see messages in the channel.";
"Wallet.Send.OwnAddressAlertProceed" = "Proceed";
"Wallet.Send.TransactionInProgress" = "Please wait until the current transaction is completed.";
"Wallet.Send.SyncInProgress" = "Please wait while the wallet finishes syncing with the TON Blockchain.";
"Wallet.Settings.Title" = "Wallet Settings";
"Wallet.Settings.Configuration" = "Configuration";
"Wallet.Settings.Title" = "Settings";
"Wallet.Settings.Configuration" = "Server Settings";
"Wallet.Settings.ConfigurationInfo" = "Advanced Settings";
"Wallet.Settings.BackupWallet" = "Backup Wallet";
"Wallet.Settings.DeleteWallet" = "Delete Wallet";
"Wallet.Settings.DeleteWalletInfo" = "This will disconnect the wallet from this app. You will be able to restore your wallet using 24 secret words or import another wallet.\n\nGram Wallets are located in the decentralized TON Blockchain. If you want a wallet to be deleted, simply transfer all the grams from it and leave it empty.";
@ -4888,7 +4889,7 @@ Any member of this group will be able to see messages in the channel.";
"Wallet.TransactionInfo.OtherFeeInfoUrl" = "Blockchain validators collect a tiny fee for processing your decentralized transactions. [More info]()";
"AppWallet.TransactionInfo.FeeInfoURL" = "https://telegram.org/wallet/fee";
"Wallet.WordCheck.Title" = "Test Time!";
"Wallet.WordCheck.Text" = "Lets check that you wrote them down correctly. Please enter words\n**%1$@**, **%2$@** and **%3$@** below:";
"Wallet.WordCheck.Text" = "Lets check that you wrote them down correctly. Please enter the words\n**%1$@**, **%2$@** and **%3$@**";
"Wallet.WordCheck.Continue" = "Continue";
"Wallet.WordCheck.IncorrectHeader" = "Incorrect words!";
"Wallet.WordCheck.IncorrectText" = "The secret words you have entered do not match the ones in the list.";
@ -4924,8 +4925,23 @@ Any member of this group will be able to see messages in the channel.";
"Conversation.WalletRequiredNotNow" = "Not Now";
"Conversation.WalletRequiredSetup" = "Set Up";
"Wallet.Configuration.Title" = "Configuration";
"Wallet.Configuration.Title" = "Server Settings";
"Wallet.Configuration.Apply" = "Save";
"Wallet.Configuration.SourceHeader" = "SOURCE";
"Wallet.Configuration.SourceURL" = "URL";
"Wallet.Configuration.SourceJSON" = "JSON";
"Wallet.Configuration.SourceInfo" = "Using a different configuration allows you to change Lite Server addresses.";
"Wallet.Configuration.BlockchainIdHeader" = "BLOCKCHAIN ID";
"Wallet.Configuration.BlockchainIdPlaceholder" = "Blockchain ID";
"Wallet.Configuration.BlockchainIdInfo" = "This setting is for developers. Change it only if you are working on creating your own TON network.";
"Wallet.Configuration.ApplyErrorTitle" = "Error";
"Wallet.Configuration.ApplyErrorTextURLInvalid" = "The URL you have entered is invalid. Please try again.";
"Wallet.Configuration.ApplyErrorTextURLUnreachable" = "There was an error while downloading configuration from %@\nPlease try again.";
"Wallet.Configuration.ApplyErrorTextURLInvalidData" = "This blockchain configuration is invalid. Please try again.";
"Wallet.Configuration.ApplyErrorTextJSONInvalidData" = "This blockchain configuration is invalid. Please try again.";
"Wallet.Configuration.BlockchainNameChangedTitle" = "Warning";
"Wallet.Configuration.BlockchainNameChangedText" = "Are you sure you want to change the blockchain ID? You don't need this unless you're testing your own TON network.\n\nIf you proceed, you will need to reconnect your wallet using 24 secret words.";
"Wallet.Configuration.BlockchainNameChangedProceed" = "Proceed";
"Wallet.CreateInvoice.Title" = "Create Invoice";

View File

@ -80,13 +80,16 @@ apple_library(
],
deps = [
"//submodules/WalletUI:WalletUI",
"//submodules/WalletCore:WalletCore",
"//submodules/BuildConfig:BuildConfig",
"//submodules/OverlayStatusController:OverlayStatusController",
]
+ framework_binary_dependencies(framework_dependencies),
frameworks = [
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
"$SDKROOT/System/Library/Frameworks/UIKit.framework",
"$SDKROOT/System/Library/Frameworks/VideoToolbox.framework",
"$SDKROOT/System/Library/Frameworks/AVFoundation.framework",
],
)

View File

@ -53,10 +53,10 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSFaceIDUsageDescription</key>
<string>For better security, please allow TON Wallet to use your Face ID to authenticate payments.</string>
<key>NSCameraUsageDescription</key>
<string>Please allow TON Wallet access to your camera for scanning QR codes.</string>
<key>NSFaceIDUsageDescription</key>
<string>For better security, please allow TON Wallet to use your Face ID to authenticate payments.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Please allow TON Wallet access to your Photo Stream in case you need to scan a QR code from a picture.</string>
<key>UIDeviceFamily</key>
@ -75,7 +75,7 @@
<key>UIRequiresPersistentWiFi</key>
<true/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDefault</string>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>

View File

@ -30,6 +30,14 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="Wallet/SplashCornerL" translatesAutoresizingMaskIntoConstraints="NO" id="4bZ-PB-VJX">
<rect key="frame" x="0.0" y="260" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="Wallet/SplashCornerR" translatesAutoresizingMaskIntoConstraints="NO" id="K7L-Vs-8lO">
<rect key="frame" x="404" y="260" width="10" height="10"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
</view>
@ -39,4 +47,8 @@
<point key="canvasLocation" x="-137.68115942028987" y="-95.089285714285708"/>
</navigationController>
</objects>
<resources>
<image name="Wallet/SplashCornerL" width="10" height="10"/>
<image name="Wallet/SplashCornerR" width="10" height="10"/>
</resources>
</document>

42
Wallet/README.md Normal file
View File

@ -0,0 +1,42 @@
# TON Wallet iOS Source Code Compilation Guide
1. Install Xcode 11.1
```
https://apps.apple.com/ae/app/xcode/id497799835?mt=12
```
Make sure to launch Xcode at least once and set up command-line tools paths (Xcode — Preferences — Locations — Command Line Tools)
2. Install Homebrew
```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
3. Install the required tools
```
brew tap AdoptOpenJDK/openjdk
brew cask install adoptopenjdk8
brew install cmake ant
```
4. Build Buck
```
mkdir -p $HOME/buck_source
cd tools/buck
sh ./prepare_buck_source.sh $HOME/buck_source
```
5. Now you can build Wallet application (IPA)
Note:
It is recommended to use an artifact cache to optimize build speed. Prepend any of the following commands with BUCK_DIR_CACHE="path/to/existing/directory"
```BUCK="$HOME/buck_source/buck/buck-out/gen/programs/buck.pex" DISTRIBUTION_CODE_SIGN_IDENTITY="iPhone Distribution: XXXXXXX (XXXXXXXXXX)" DEVELOPMENT_TEAM="XXXXXXXXXX" WALLET_BUNDLE_ID="wallet.bundle.id" BUILD_NUMBER=30 WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP="wallet provisioning profile name" CODESIGNING_SOURCE_DATA_PATH="$HOME/wallet_codesigning" sh Wallet/example_wallet_env.sh make -f Wallet.makefile wallet_app
```
6. If needed, generate Xcode project
```
BUCK="$HOME/buck_source/buck/buck-out/gen/programs/buck.pex" DISTRIBUTION_CODE_SIGN_IDENTITY="iPhone Distribution: XXXXXXX (XXXXXXXXXX)" DEVELOPMENT_TEAM="XXXXXXXXXX" WALLET_BUNDLE_ID="wallet.bundle.id" BUILD_NUMBER=30 WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP="wallet provisioning profile name" CODESIGNING_SOURCE_DATA_PATH="$HOME/wallet_codesigning" sh Wallet/example_wallet_env.sh make -f Wallet.makefile wallet_project
```

View File

@ -1,5 +1,6 @@
import UIKit
import Display
import OverlayStatusController
import SwiftSignalKit
import BuildConfig
import WalletUI
@ -334,7 +335,10 @@ private final class WalletStorageInterfaceImpl: WalletStorageInterface {
}
private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let storage: WalletStorageInterface
var storage: WalletStorageInterface {
return self.storageImpl
}
private let storageImpl: WalletStorageInterfaceImpl
let tonInstance: TonInstance
let keychain: TonKeychain
let presentationData: WalletPresentationData
@ -354,6 +358,23 @@ private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerCon
return .single(Data())
}
func downloadFile(url: URL) -> Signal<Data, WalletDownloadFileError> {
return download(url: url)
|> mapError { _ in
return .generic
}
}
func updateResolvedWalletConfiguration(source: LocalWalletConfigurationSource, blockchainName: String, resolvedValue: String) -> Signal<Never, NoError> {
return self.storageImpl.updateMergedLocalWalletConfiguration { configuration in
var configuration = configuration
configuration.configuration.source = source
configuration.configuration.blockchainName = blockchainName
configuration.resolved = ResolvedLocalWalletConfiguration(source: source, value: resolvedValue)
return configuration
}
}
func presentNativeController(_ controller: UIViewController) {
self.window.presentNative(controller)
}
@ -417,9 +438,9 @@ private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerCon
picker.presentingViewController?.dismiss(animated: true, completion: nil)
}
init(basePath: String, storage: WalletStorageInterfaceImpl, config: String, blockchainName: String, navigationBarTheme: NavigationBarTheme, window: Window1) {
init(basePath: String, storage: WalletStorageInterfaceImpl, config: String, blockchainName: String, presentationData: WalletPresentationData, navigationBarTheme: NavigationBarTheme, window: Window1) {
let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: basePath + "/keys"), withIntermediateDirectories: true, attributes: nil)
self.storage = storage
self.storageImpl = storage
self.window = window
@ -481,8 +502,42 @@ private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerCon
}
})
#endif
self.presentationData = presentationData
super.init()
}
}
@objc(AppDelegate)
final class AppDelegate: NSObject, UIApplicationDelegate {
var window: UIWindow?
private var mainWindow: Window1?
private var walletContext: WalletContextImpl?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
let statusBarHost = ApplicationStatusBarHost()
let (window, hostView) = nativeWindowHostView()
let mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)
self.mainWindow = mainWindow
hostView.containerView.backgroundColor = UIColor.white
self.window = window
let accentColor = UIColor(rgb: 0x007ee5)
self.presentationData = WalletPresentationData(
let navigationBarTheme = NavigationBarTheme(
buttonColor: accentColor,
disabledButtonColor: UIColor(rgb: 0xd0d0d0),
primaryTextColor: .black,
backgroundColor: UIColor(rgb: 0xf7f7f7),
separatorColor: UIColor(rgb: 0xb1b1b1),
badgeBackgroundColor: UIColor(rgb: 0xff3b30),
badgeStrokeColor: UIColor(rgb: 0xff3b30),
badgeTextColor: .white
)
let presentationData = WalletPresentationData(
theme: WalletTheme(
info: WalletInfoTheme(
buttonBackgroundColor: accentColor,
@ -566,37 +621,6 @@ private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerCon
)
)
super.init()
}
}
@objc(AppDelegate)
final class AppDelegate: NSObject, UIApplicationDelegate {
var window: UIWindow?
private var mainWindow: Window1?
private var walletContext: WalletContextImpl?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
let statusBarHost = ApplicationStatusBarHost()
let (window, hostView) = nativeWindowHostView()
let mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)
self.mainWindow = mainWindow
hostView.containerView.backgroundColor = UIColor.white
self.window = window
let accentColor = UIColor(rgb: 0x007ee5)
let navigationBarTheme = NavigationBarTheme(
buttonColor: accentColor,
disabledButtonColor: UIColor(rgb: 0xd0d0d0),
primaryTextColor: .black,
backgroundColor: UIColor(rgb: 0xf7f7f7),
separatorColor: UIColor(rgb: 0xb1b1b1),
badgeBackgroundColor: UIColor(rgb: 0xff3b30),
badgeStrokeColor: UIColor(rgb: 0xff3b30),
badgeTextColor: .white
)
let navigationController = NavigationController(
mode: .single,
theme: NavigationControllerTheme(
@ -608,6 +632,8 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
mainWindow.viewController = navigationController
navigationController.setViewControllers([WalletApplicationSplashScreen(theme: presentationData.theme)], animated: false)
self.window?.makeKeyAndVisible()
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
@ -634,7 +660,7 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
guard let parsedUrl = URL(string: url) else {
return .complete()
}
return downloadFile(url: parsedUrl)
return download(url: parsedUrl)
|> retry(1.0, maxDelay: 5.0, onQueue: .mainQueue())
|> mapToSignal { data -> Signal<(ResolvedLocalWalletConfiguration, String), NoError> in
if let string = String(data: data, encoding: .utf8) {
@ -666,13 +692,38 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
let _ = (resolvedInitialConfig
|> deliverOnMainQueue).start(next: { (initialResolvedConfig, initialConfigBlockchainName) in
let walletContext = WalletContextImpl(basePath: documentsPath, storage: storage, config: initialResolvedConfig.value, blockchainName: initialConfigBlockchainName, navigationBarTheme: navigationBarTheme, window: mainWindow)
let walletContext = WalletContextImpl(basePath: documentsPath, storage: storage, config: initialResolvedConfig.value, blockchainName: initialConfigBlockchainName, presentationData: presentationData, navigationBarTheme: navigationBarTheme, window: mainWindow)
self.walletContext = walletContext
let _ = (updatedConfigValue
|> deliverOnMainQueue).start(next: { resolved, blockchainName in
let _ = walletContext.tonInstance.updateConfig(config: resolved.value, blockchainName: blockchainName).start()
})
let beginWithController: (ViewController) -> Void = { controller in
navigationController.setViewControllers([controller], animated: false)
var previousBlockchainName = initialConfigBlockchainName
let _ = (updatedConfigValue
|> deliverOnMainQueue).start(next: { resolved, blockchainName in
let _ = walletContext.tonInstance.validateConfig(config: resolved.value, blockchainName: blockchainName).start(error: { _ in
}, completed: {
let _ = walletContext.tonInstance.updateConfig(config: resolved.value, blockchainName: blockchainName).start()
if previousBlockchainName != blockchainName {
previousBlockchainName = blockchainName
let overlayController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
mainWindow.present(overlayController, on: .root)
let _ = (deleteAllLocalWalletsData(storage: walletContext.storage, tonInstance: walletContext.tonInstance)
|> deliverOnMainQueue).start(error: { [weak overlayController] _ in
overlayController?.dismiss()
}, completed: { [weak overlayController] in
overlayController?.dismiss()
navigationController.setViewControllers([WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)], animated: true)
})
}
})
})
}
let _ = (combineLatest(queue: .mainQueue(),
walletContext.storage.getWalletRecords(),
@ -681,39 +732,32 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|> deliverOnMainQueue).start(next: { records, publicKey in
if let record = records.first {
if let publicKey = publicKey {
print("publicKey = \(publicKey.base64EncodedString())")
if record.info.encryptedSecret.publicKey == publicKey {
if record.exportCompleted {
let _ = (walletAddress(publicKey: record.info.publicKey, tonInstance: walletContext.tonInstance)
|> deliverOnMainQueue).start(next: { address in
let infoScreen = WalletInfoScreen(context: walletContext, walletInfo: record.info, address: address, enableDebugActions: false)
navigationController.setViewControllers([infoScreen], animated: false)
beginWithController(infoScreen)
})
} else {
let createdScreen = WalletSplashScreen(context: walletContext, mode: .created(record.info, nil), walletCreatedPreloadState: nil)
navigationController.setViewControllers([createdScreen], animated: false)
beginWithController(createdScreen)
}
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageReset(.changed), walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
beginWithController(splashScreen)
}
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: WalletSplashMode.secureStorageReset(.notAvailable), walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
beginWithController(splashScreen)
}
} else {
if publicKey != nil {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .intro, walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
beginWithController(splashScreen)
} else {
let splashScreen = WalletSplashScreen(context: walletContext, mode: .secureStorageNotAvailable, walletCreatedPreloadState: nil)
navigationController.setViewControllers([splashScreen], animated: false)
beginWithController(splashScreen)
}
}
})
@ -727,7 +771,7 @@ private enum DownloadFileError {
case network
}
private func downloadFile(url: URL) -> Signal<Data, DownloadFileError> {
private func download(url: URL) -> Signal<Data, DownloadFileError> {
return Signal { subscriber in
let completed = Atomic<Bool>(value: false)
let downloadTask = URLSession.shared.downloadTask(with: url, completionHandler: { location, _, error in
@ -761,6 +805,6 @@ struct MergedLocalWalletConfiguration: Codable, Equatable {
private extension MergedLocalWalletConfiguration {
static var `default`: MergedLocalWalletConfiguration {
return MergedLocalWalletConfiguration(configuration: LocalWalletConfiguration(source: .url("https://test.ton.org/config.json"), blockchainName: "testchain"), resolved: nil)
return MergedLocalWalletConfiguration(configuration: LocalWalletConfiguration(source: .url("https://test.ton.org/config.json"), blockchainName: "testnet"), resolved: nil)
}
}

View File

@ -23,7 +23,7 @@
"Wallet.Info.Send" = "Send";
"Wallet.Info.RefreshErrorTitle" = "No network";
"Wallet.Info.RefreshErrorText" = "Couldn't refresh balance. Please make sure your internet connection is working and try again.";
"Wallet.Info.RefreshErrorNetworkText" = "The wallet state can not be retrieved at this time. Please try again later.";
"Wallet.Info.RefreshErrorNetworkText" = "Wallet state can not be retrieved at this time. Please try again later.";
"Wallet.Info.UnknownTransaction" = "Empty Transaction";
"Wallet.Info.TransactionTo" = "to";
"Wallet.Info.TransactionFrom" = "from";
@ -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$@?\n\nFees: ~%3$@ grams";
"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n\n%2$@?\n\nBlockchain fees: ~%3$@ grams";
"Wallet.Send.ConfirmationConfirm" = "Confirm";
"Wallet.Send.Send" = "Send";
"Wallet.Send.OwnAddressAlertTitle" = "Warning";
@ -62,8 +62,9 @@
"Wallet.Send.OwnAddressAlertProceed" = "Proceed";
"Wallet.Send.TransactionInProgress" = "Please wait until the current transaction is completed.";
"Wallet.Send.SyncInProgress" = "Please wait while the wallet finishes syncing with the TON Blockchain.";
"Wallet.Settings.Title" = "Wallet Settings";
"Wallet.Settings.Configuration" = "Configuration";
"Wallet.Settings.Title" = "Settings";
"Wallet.Settings.Configuration" = "Server Settings";
"Wallet.Settings.ConfigurationInfo" = "Advanced Settings";
"Wallet.Settings.BackupWallet" = "Backup Wallet";
"Wallet.Settings.DeleteWallet" = "Delete Wallet";
"Wallet.Settings.DeleteWalletInfo" = "This will disconnect the wallet from this app. You will be able to restore your wallet using 24 secret words or import another wallet.\n\nGram Wallets are located in the decentralized TON Blockchain. If you want a wallet to be deleted, simply transfer all the grams from it and leave it empty.";
@ -119,7 +120,7 @@
"Wallet.TransactionInfo.OtherFeeInfo" = "Blockchain validators collect a tiny fee for processing your decentralized transactions.";
"Wallet.TransactionInfo.OtherFeeInfoUrl" = "Blockchain validators collect a tiny fee for processing your decentralized transactions. [More info]()";
"Wallet.WordCheck.Title" = "Test Time!";
"Wallet.WordCheck.Text" = "Lets check that you wrote them down correctly. Please enter words\n**%1$@**, **%2$@** and **%3$@** below:";
"Wallet.WordCheck.Text" = "Lets check that you wrote them down correctly. Please enter the words\n**%1$@**, **%2$@** and **%3$@**";
"Wallet.WordCheck.Continue" = "Continue";
"Wallet.WordCheck.IncorrectHeader" = "Incorrect words!";
"Wallet.WordCheck.IncorrectText" = "The secret words you have entered do not match the ones in the list.";
@ -149,8 +150,23 @@
"Wallet.Send.SendAnyway" = "Send Anyway";
"Wallet.Receive.CreateInvoice" = "Create Invoice";
"Wallet.Receive.CreateInvoiceInfo" = "You can specify the amount and purpose of the payment to save the sender some time.";
"Wallet.Configuration.Title" = "Configuration";
"Wallet.Configuration.Title" = "Server Settings";
"Wallet.Configuration.Apply" = "Save";
"Wallet.Configuration.SourceHeader" = "SOURCE";
"Wallet.Configuration.SourceURL" = "URL";
"Wallet.Configuration.SourceJSON" = "JSON";
"Wallet.Configuration.SourceInfo" = "Using a different configuration allows you to change Lite Server addresses.";
"Wallet.Configuration.BlockchainIdHeader" = "BLOCKCHAIN ID";
"Wallet.Configuration.BlockchainIdPlaceholder" = "Blockchain ID";
"Wallet.Configuration.BlockchainIdInfo" = "This setting is for developers. Change it only if you are working on creating your own TON network.";
"Wallet.Configuration.ApplyErrorTitle" = "Error";
"Wallet.Configuration.ApplyErrorTextURLInvalid" = "The URL you have entered is invalid. Please try again.";
"Wallet.Configuration.ApplyErrorTextURLUnreachable" = "There was an error while downloading configuration from %@\nPlease try again.";
"Wallet.Configuration.ApplyErrorTextURLInvalidData" = "This blockchain configuration is invalid. Please try again.";
"Wallet.Configuration.ApplyErrorTextJSONInvalidData" = "This blockchain configuration is invalid. Please try again.";
"Wallet.Configuration.BlockchainNameChangedTitle" = "Warning";
"Wallet.Configuration.BlockchainNameChangedText" = "Are you sure you want to change the blockchain ID? You don't need this unless you're testing your own TON network.\n\nIf you proceed, you will need to reconnect your wallet using 24 secret words.";
"Wallet.Configuration.BlockchainNameChangedProceed" = "Proceed";
"Wallet.CreateInvoice.Title" = "Create Invoice";
"Wallet.Navigation.Close" = "Close";
"Wallet.Navigation.Back" = "Back";

74
Wallet/example_wallet_env.sh Executable file
View File

@ -0,0 +1,74 @@
#!/bin/bash
custom_realpath() {
OURPWD=$PWD
cd "$(dirname "$1")"
LINK=$(readlink "$(basename "$1")")
while [ "$LINK" ]; do
cd "$(dirname "$LINK")"
LINK=$(readlink "$(basename "$1")")
done
REALPATH="$PWD/$(basename "$1")"
cd "$OURPWD"
echo "$REALPATH"
}
export TELEGRAM_ENV_SET="1"
export HOCKEYAPP_ID=""
export IS_INTERNAL_BUILD="false"
export IS_APPSTORE_BUILD="true"
export APPSTORE_ID="1"
export APP_SPECIFIC_URL_SCHEME=""
export API_ID="0"
export API_HASH=""
export DEVELOPMENT_CODE_SIGN_IDENTITY="iPhone Developer: AAAAA AAAAA (XXXXXXXXXX)"
if [ -z "$DISTRIBUTION_CODE_SIGN_IDENTITY" ]; then
export DISTRIBUTION_CODE_SIGN_IDENTITY="iPhone Distribution: AAAAA AAAAA (XXXXXXXXXX)"
fi
if [ -z "$DEVELOPMENT_TEAM" ]; then
export DEVELOPMENT_TEAM="XXXXXXXXXX"
fi
if [ -z "$WALLET_BUNDLE_ID" ]; then
export WALLET_BUNDLE_ID="reverse.dns.notation"
fi
if [ -z "$BUILD_NUMBER" ]; then
echo "BUILD_NUMBER is not defined"
exit 1
fi
export WALLET_ENTITLEMENTS_APP="Wallet.entitlements"
export WALLET_DEVELOPMENT_PROVISIONING_PROFILE_APP="development profile name"
if [ -z "$WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP" ]; then
export WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP="distribution profile name"
fi
BASE_DIR="$(custom_realpath .)"
BASE_PATH=$(dirname "$(custom_realpath $0)")
BUILDBOX_DIR="buildbox"
if [ -z "$CODESIGNING_SOURCE_DATA_PATH" ]; then
echo "CODESIGNING_SOURCE_DATA_PATH is not defined"
exit 1
fi
if [ ! -d "$CODESIGNING_SOURCE_DATA_PATH/profiles" ] || [ ! -d "$CODESIGNING_SOURCE_DATA_PATH/certs" ]; then
echo "Expected codesigning directory layout:"
echo "$CODESIGNING_SOURCE_DATA_PATH/profiles/appstore/*.mobileprovision"
echo "$CODESIGNING_SOURCE_DATA_PATH/certs/distribution/*.{cer,p12}"
exit 1
fi
rm -rf "$BASE_DIR/$BUILDBOX_DIR/transient-data/teams/$DEVELOPMENT_TEAM/codesigning"
mkdir -p "$BASE_DIR/$BUILDBOX_DIR/transient-data/teams/$DEVELOPMENT_TEAM/codesigning"
cp -R "$CODESIGNING_SOURCE_DATA_PATH/"* "$BASE_DIR/$BUILDBOX_DIR/transient-data/teams/$DEVELOPMENT_TEAM/codesigning/"
export CODESIGNING_DATA_PATH="$BUILDBOX_DIR/transient-data/teams/$DEVELOPMENT_TEAM/codesigning"
export CODESIGNING_CERTS_VARIANT="distribution"
export CODESIGNING_PROFILES_VARIANT="appstore"
export PACKAGE_METHOD="appstore"
$@

View File

@ -0,0 +1,157 @@
diff --git a/.gitignore b/.gitignore
index 78ce658b9a..30c0369ab7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
# IntelliJ build
/intellij-out/
+/.idea/
# Buck
/buck-out
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 7ff823b554..0000000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ProjectModuleManager">
- <modules>
- <module fileurl="file://$PROJECT_DIR$/buck.iml" filepath="$PROJECT_DIR$/buck.iml" />
- <module fileurl="file://$PROJECT_DIR$/tools/consistency_checker/consistency_checker.iml" filepath="$PROJECT_DIR$/tools/consistency_checker/consistency_checker.iml" />
- <module fileurl="file://$PROJECT_DIR$/tools/documentation_generator/documentation_generator.iml" filepath="$PROJECT_DIR$/tools/documentation_generator/documentation_generator.iml" />
- <module fileurl="file://$PROJECT_DIR$/tools/build/modules/modules.iml" filepath="$PROJECT_DIR$/tools/build/modules/modules.iml" />
- <module fileurl="file://$PROJECT_DIR$/src/com/facebook/buck/multitenant/multitenant.iml" filepath="$PROJECT_DIR$/src/com/facebook/buck/multitenant/multitenant.iml" />
- <module fileurl="file://$PROJECT_DIR$/programs/programs.iml" filepath="$PROJECT_DIR$/programs/programs.iml" />
- <module fileurl="file://$PROJECT_DIR$/skunkworks/protobuck/protobuck.iml" filepath="$PROJECT_DIR$/skunkworks/protobuck/protobuck.iml" />
- <module fileurl="file://$PROJECT_DIR$/python-dsl/python-dsl.iml" filepath="$PROJECT_DIR$/python-dsl/python-dsl.iml" />
- <module fileurl="file://$PROJECT_DIR$/scripts/scripts.iml" filepath="$PROJECT_DIR$/scripts/scripts.iml" />
- </modules>
- </component>
-</project>
\ No newline at end of file
diff --git a/src/com/facebook/buck/apple/AppleBundle.java b/src/com/facebook/buck/apple/AppleBundle.java
index d895ab9a79..ad42beb302 100644
--- a/src/com/facebook/buck/apple/AppleBundle.java
+++ b/src/com/facebook/buck/apple/AppleBundle.java
@@ -992,7 +992,11 @@ public class AppleBundle extends AbstractBuildRuleWithDeclaredAndExtraDeps
keys.put("DTPlatformName", new NSString(platform.getName()));
keys.put("DTPlatformVersion", new NSString(sdkVersion));
keys.put("DTSDKName", new NSString(sdkName + sdkVersion));
- keys.put("MinimumOSVersion", new NSString(minOSVersion));
+ if (infoPlistSubstitutions.containsKey("MinimumOSVersion")) {
+ keys.put("MinimumOSVersion", new NSString(infoPlistSubstitutions.get("MinimumOSVersion")));
+ } else {
+ keys.put("MinimumOSVersion", new NSString(minOSVersion));
+ }
if (platformBuildVersion.isPresent()) {
keys.put("DTPlatformBuild", new NSString(platformBuildVersion.get()));
keys.put("DTSDKBuild", new NSString(platformBuildVersion.get()));
@@ -1185,9 +1189,10 @@ public class AppleBundle extends AbstractBuildRuleWithDeclaredAndExtraDeps
// .framework bundles will be code-signed when they're copied into the containing bundle.
private boolean needCodeSign() {
- return binary.isPresent()
+ return false;
+ /*return binary.isPresent()
&& ApplePlatform.needsCodeSign(platform.getName())
- && !extension.equals(FRAMEWORK_EXTENSION);
+ && !extension.equals(FRAMEWORK_EXTENSION);*/
}
@Override
diff --git a/src/com/facebook/buck/apple/MultiarchFileInfos.java b/src/com/facebook/buck/apple/MultiarchFileInfos.java
index c078b2e134..030f9fc289 100644
--- a/src/com/facebook/buck/apple/MultiarchFileInfos.java
+++ b/src/com/facebook/buck/apple/MultiarchFileInfos.java
@@ -177,7 +177,12 @@ public class MultiarchFileInfos {
cxxBuckConfig.shouldCacheLinks(),
BuildTargetPaths.getGenPath(
projectFilesystem, buildTarget, multiarchOutputPathFormat));
- graphBuilder.addToIndex(multiarchFile);
+ Optional<BuildRule> existingRule2 = graphBuilder.getRuleOptional(multiarchFile.getBuildTarget());
+ if (existingRule2.isPresent()) {
+ return existingRule2.get();
+ } else {
+ graphBuilder.addToIndex(multiarchFile);
+ }
return multiarchFile;
} else {
return new NoopBuildRule(buildTarget, projectFilesystem);
diff --git a/src/com/facebook/buck/features/apple/project/ProjectGenerator.java b/src/com/facebook/buck/features/apple/project/ProjectGenerator.java
index 8db968b982..b10f793d8e 100644
--- a/src/com/facebook/buck/features/apple/project/ProjectGenerator.java
+++ b/src/com/facebook/buck/features/apple/project/ProjectGenerator.java
@@ -825,6 +825,7 @@ public class ProjectGenerator {
Optional.of(xcodeDescriptions.getXCodeDescriptions()));
if (bundleRequiresRemovalOfAllTransitiveFrameworks(targetNode)) {
copiedRules = rulesWithoutFrameworkBundles(copiedRules);
+ copiedRules = rulesWithoutDylibs(copiedRules);
} else if (bundleRequiresAllTransitiveFrameworks(binaryNode, bundleLoaderNode)) {
copiedRules =
ImmutableSet.<TargetNode<?>>builder()
@@ -954,6 +955,22 @@ public class ProjectGenerator {
.toImmutableList();
}
+ private ImmutableList<TargetNode<?>> rulesWithoutDylibs(
+ Iterable<TargetNode<?>> copiedRules) {
+ return RichStream.from(copiedRules)
+ .filter(
+ input ->
+ TargetNodes.castArg(input, AppleLibraryDescriptionArg.class)
+ .map(argTargetNode -> {
+ if (argTargetNode.getBuildTarget().getFlavors().contains(CxxDescriptionEnhancer.SHARED_FLAVOR)) {
+ return false;
+ }
+ return true;
+ })
+ .orElse(true))
+ .toImmutableList();
+ }
+
private ImmutableList<TargetNode<?>> rulesWithoutBundleLoader(
Iterable<TargetNode<?>> copiedRules, TargetNode<?> bundleLoader) {
return RichStream.from(copiedRules).filter(x -> !bundleLoader.equals(x)).toImmutableList();
@@ -2316,8 +2333,9 @@ public class ProjectGenerator {
.transform(
bundleExtension -> {
switch (bundleExtension) {
- case APP:
case APPEX:
+ return false;
+ case APP:
case PLUGIN:
case BUNDLE:
case XCTEST:
@@ -2515,7 +2533,7 @@ public class ProjectGenerator {
librarySearchPaths.add("$DT_TOOLCHAIN_DIR/usr/lib/swift/$PLATFORM_NAME");
if (options.shouldLinkSystemSwift()) {
- librarySearchPaths.add("$DT_TOOLCHAIN_DIR/usr/lib/swift-5.0/$PLATFORM_NAME");
+ //librarySearchPaths.add("$DT_TOOLCHAIN_DIR/usr/lib/swift-5.0/$PLATFORM_NAME");
}
}
@@ -3444,7 +3462,7 @@ public class ProjectGenerator {
PBXFileReference fileReference = getLibraryFileReference(targetNode);
PBXBuildFile buildFile = new PBXBuildFile(fileReference);
- if (fileReference.getExplicitFileType().equals(Optional.of("wrapper.framework"))) {
+ if (fileReference.getExplicitFileType().equals(Optional.of("wrapper.framework")) || fileReference.getExplicitFileType().equals(Optional.of("compiled.mach-o.dylib"))) {
UnflavoredBuildTargetView buildTarget =
targetNode.getBuildTarget().getUnflavoredBuildTarget();
if (frameworkTargets.contains(buildTarget)) {
@@ -4696,6 +4714,9 @@ public class ProjectGenerator {
private static boolean bundleRequiresRemovalOfAllTransitiveFrameworks(
TargetNode<? extends HasAppleBundleFields> targetNode) {
+ if (targetNode.getConstructorArg().getXcodeProductType().equals(Optional.of("com.apple.product-type.app-extension"))) {
+ return true;
+ }
return isFrameworkBundle(targetNode.getConstructorArg());
}

View File

@ -0,0 +1,7 @@
#!/bin/bash
ls []
if [ ! -f "" ]; then
exit 1
fi

View File

@ -22,12 +22,30 @@ def clean_files(base_dir, dirs, files):
if re.match('.*\\.xcodeproj', dir) or re.match('.*\\.xcworkspace', dir):
shutil.rmtree(base_dir + '/' + dir, ignore_errors=True)
def clean_dep_files(base_dir, dirs, files):
for file in files:
if re.match('^\\.git$', file) or re.match('^.*/\\.git$', file):
os.remove(base_dir + '/' + file)
for dir in dirs:
if re.match('^\\.git$', dir) or re.match('^.*/\\.git$', dir):
shutil.rmtree(base_dir + '/' + dir, ignore_errors=True)
if len(sys.argv) != 2:
print('Usage: extract_wallet_source.py destination')
sys.exit(1)
destination = sys.argv[1]
initial_dirs, initial_files = get_file_list(destination)
for file in initial_files:
if re.match('^\\.git/.*$', file):
continue
os.remove(destination + '/' + file)
for dir in initial_dirs:
if dir == '.git' or re.match('^\\.git/.*$', dir):
continue
shutil.rmtree(destination + '/' + dir, ignore_errors=True)
deps_data = os.popen('make -f Wallet.makefile --silent wallet_deps').read()
deps = json.loads(deps_data)
@ -45,6 +63,8 @@ for dep in deps:
for dep_path in paths:
shutil.copytree(dep_path, destination + '/' + dep_path)
dep_dirs, dep_files = get_file_list(destination + '/' + dep_path)
clean_dep_files(destination + '/' + dep_path, dep_dirs, dep_files)
result_dirs, result_files = get_file_list(destination)
clean_files(destination, result_dirs, result_files)
@ -53,6 +73,9 @@ with open(destination + '/BUCK', 'w+b') as file:
pass
shutil.copytree('Config', destination + '/' + 'Config')
shutil.copytree('tools/buck', destination + '/' + 'tools/buck')
shutil.copy('Wallet/README.md', destination + '/' + 'README.md')
copy_files = [
'.buckconfig',

View File

@ -124,6 +124,14 @@ final class WalletContextImpl: WalletContext {
return self.context.sharedContext.applicationBindings.applicationInForeground
}
func downloadFile(url: URL) -> Signal<Data, WalletDownloadFileError> {
return .fail(.generic)
}
func updateResolvedWalletConfiguration(source: LocalWalletConfigurationSource, blockchainName: String, resolvedValue: String) -> Signal<Never, NoError> {
return .complete()
}
init(context: AccountContext, tonContext: TonContext) {
self.context = context

View File

@ -113,14 +113,23 @@ NS_ASSUME_NONNULL_BEGIN
@end
@interface TONValidatedConfig : NSObject
@property (nonatomic, readonly) int64_t defaultWalletId;
- (instancetype)initWithDefaultWalletId:(int64_t)defaultWalletId;
@end
@interface TON : NSObject
- (instancetype)initWithKeystoreDirectory:(NSString *)keystoreDirectory config:(NSString *)config blockchainName:(NSString *)blockchainName performExternalRequest:(void (^)(TONExternalRequest * _Nonnull))performExternalRequest enableExternalRequests:(bool)enableExternalRequests syncStateUpdated:(void (^)(float))syncStateUpdated;
- (SSignal *)updateConfig:(NSString *)config blockchainName:(NSString *)blockchainName;
- (SSignal *)validateConfig:(NSString *)config blockchainName:(NSString *)blockchainName;
- (SSignal *)createKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword;
- (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey;
- (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey initialWalletId:(int64_t)initialWalletId;
- (SSignal *)getAccountStateWithAddress:(NSString *)accountAddress;
- (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;

View File

@ -202,6 +202,18 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
@end
@implementation TONValidatedConfig
- (instancetype)initWithDefaultWalletId:(int64_t)defaultWalletId {
self = [super init];
if (self != nil) {
_defaultWalletId = defaultWalletId;
}
return self;
}
@end
using tonlib_api::make_object;
@interface TONReceiveThreadParams : NSObject
@ -477,6 +489,39 @@ typedef enum {
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
}
- (SSignal *)validateConfig:(NSString *)config blockchainName:(NSString *)blockchainName {
return [[[[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
_nextRequestId += 1;
_requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr<tonlib_api::Object> &object) {
if (object->get_id() == tonlib_api::error::ID) {
auto error = tonlib_api::move_object_as<tonlib_api::error>(object);
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
} else if (object->get_id() == tonlib_api::options_configInfo::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::options_configInfo>(object);
[subscriber putNext:[[TONValidatedConfig alloc] initWithDefaultWalletId:result->default_wallet_id_]];
[subscriber putCompletion];
} else {
assert(false);
}
}];
auto query = make_object<tonlib_api::options_validateConfig>(
make_object<tonlib_api::config>(
config.UTF8String,
blockchainName.UTF8String,
_enableExternalRequests,
false
)
);
_client->send({ requestId, std::move(query) });
return [[SBlockDisposable alloc] initWithBlock:^{
}];
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
}
- (SSignal *)createKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword {
return [[[[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
uint64_t requestId = _nextRequestId;
@ -513,7 +558,7 @@ typedef enum {
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
}
- (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey {
- (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey initialWalletId:(int64_t)initialWalletId {
return [[[[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
NSData *publicKeyData = [publicKey dataUsingEncoding:NSUTF8StringEncoding];
if (publicKeyData == nil) {
@ -537,9 +582,10 @@ typedef enum {
}
}];
auto query = make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(
makeString(publicKeyData)
auto query = make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(
makeString(publicKeyData),
initialWalletId
)
);
_client->send({ requestId, std::move(query) });
@ -574,7 +620,15 @@ typedef enum {
}
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
[subscriber putCompletion];
} else {
} else if (object->get_id() == tonlib_api::generic_accountStateWalletV3::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateWalletV3>(object);
TONTransactionId *lastTransactionId = nil;
if (result->account_state_->last_transaction_id_ != nullptr) {
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
}
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
[subscriber putCompletion];
}else {
assert(false);
}
}];
@ -628,7 +682,7 @@ typedef enum {
}];
auto query = make_object<tonlib_api::generic_createSendGramsQuery>(
make_object<tonlib_api::inputKey>(
make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(
makeString(publicKeyData),
makeSecureString(key.secret)
@ -777,7 +831,7 @@ typedef enum {
}
}];
auto query = make_object<tonlib_api::exportKey>(
make_object<tonlib_api::inputKey>(
make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(
makeString(publicKeyData),
makeSecureString(key.secret)

View File

@ -51,8 +51,8 @@ public protocol TonNetworkProxy: class {
private final class TonInstanceImpl {
private let queue: Queue
private let basePath: String
private let config: String
private let blockchainName: String
fileprivate var config: String
fileprivate var blockchainName: String
private let proxy: TonNetworkProxy?
private var instance: TON?
fileprivate let syncStateProgress = ValuePromise<Float>(0.0)
@ -122,6 +122,8 @@ public final class TonInstance {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
impl.config = config
impl.blockchainName = blockchainName
impl.withInstance { ton in
let cancel = ton.updateConfig(config, blockchainName: blockchainName).start(next: nil, error: { _ in
}, completed: {
@ -136,6 +138,34 @@ public final class TonInstance {
}
}
public func validateConfig(config: String, blockchainName: String) -> Signal<WalletValidateConfigResult, WalletValidateConfigError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
impl.withInstance { ton in
let cancel = ton.validateConfig(config, blockchainName: blockchainName).start(next: { result in
guard let result = result as? TONValidatedConfig else {
subscriber.putError(.generic)
return
}
subscriber.putNext(WalletValidateConfigResult(defaultWalletId: result.defaultWalletId))
subscriber.putCompletion()
}, error: { error in
guard let _ = error as? TONError else {
subscriber.putError(.generic)
return
}
subscriber.putError(.generic)
}, completed: nil)
disposable.set(ActionDisposable {
cancel?.dispose()
})
}
}
return disposable
}
}
fileprivate func exportKey(key: TONKey, localPassword: Data) -> Signal<[String], NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
@ -226,31 +256,70 @@ public final class TonInstance {
}
}
fileprivate func walletAddress(publicKey: WalletPublicKey) -> Signal<String, NoError> {
fileprivate func getInitialWalletId() -> Signal<Int64, WalletValidateConfigError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
let config = impl.config
let blockchainName = impl.blockchainName
impl.withInstance { ton in
let cancel = ton.getWalletAccountAddress(withPublicKey: publicKey.rawValue).start(next: { address in
guard let address = address as? String else {
let cancel = ton.validateConfig(config, blockchainName: blockchainName).start(next: { result in
guard let result = result as? TONValidatedConfig else {
subscriber.putError(.generic)
return
}
subscriber.putNext(address)
subscriber.putNext(result.defaultWalletId)
subscriber.putCompletion()
}, error: { _ in
}, completed: {
})
}, error: { error in
guard let _ = error as? TONError else {
subscriber.putError(.generic)
return
}
subscriber.putError(.generic)
}, completed: nil)
disposable.set(ActionDisposable {
cancel?.dispose()
})
}
}
return disposable
}
}
fileprivate func walletAddress(publicKey: WalletPublicKey) -> Signal<String, NoError> {
return self.getInitialWalletId()
|> `catch` { _ -> Signal<Int64, NoError> in
return .single(0)
}
|> mapToSignal { initialWalletId -> Signal<String, NoError> in
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
impl.withInstance { ton in
let cancel = ton.getWalletAccountAddress(withPublicKey: publicKey.rawValue, initialWalletId: initialWalletId).start(next: { address in
guard let address = address as? String else {
return
}
subscriber.putNext(address)
subscriber.putCompletion()
}, error: { _ in
subscriber.putNext("ERROR")
subscriber.putCompletion()
}, completed: {
})
disposable.set(ActionDisposable {
cancel?.dispose()
})
}
}
return disposable
}
}
}
private func getWalletStateRaw(address: String) -> Signal<TONAccountState, GetWalletStateError> {
return Signal { subscriber in
let disposable = MetaDisposable()
@ -1263,3 +1332,12 @@ public protocol WalletStorageInterface {
func localWalletConfiguration() -> Signal<LocalWalletConfiguration, NoError>
func updateLocalWalletConfiguration(_ f: @escaping (LocalWalletConfiguration) -> LocalWalletConfiguration) -> Signal<Never, NoError>
}
public struct WalletValidateConfigResult {
public var defaultWalletId: Int64
}
public enum WalletValidateConfigError {
case generic
}

View File

@ -45,38 +45,47 @@ private enum WalletConfigurationScreenEntryTag: ItemListItemTag {
}
private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
case modeHeader(WalletTheme, String)
case modeUrl(WalletTheme, String, Bool)
case modeCustomString(WalletTheme, String, Bool)
case modeInfo(WalletTheme, String)
case configUrl(WalletTheme, WalletStrings, String, String)
case configString(WalletTheme, String, String)
case blockchainNameHeader(WalletTheme, String)
case blockchainName(WalletTheme, WalletStrings, String, String)
case blockchainNameInfo(WalletTheme, String)
var section: ItemListSectionId {
switch self {
case .modeUrl, .modeCustomString:
case .modeHeader, .modeUrl, .modeCustomString, .modeInfo:
return WalletConfigurationScreenSection.mode.rawValue
case .configUrl, .configString:
return WalletConfigurationScreenSection.configString.rawValue
case .blockchainNameHeader, .blockchainName:
case .blockchainNameHeader, .blockchainName, .blockchainNameInfo:
return WalletConfigurationScreenSection.blockchainName.rawValue
}
}
var stableId: Int32 {
switch self {
case .modeUrl:
case .modeHeader:
return 0
case .modeCustomString:
case .modeUrl:
return 1
case .configUrl:
case .modeCustomString:
return 2
case .configString:
case .modeInfo:
return 3
case .blockchainNameHeader:
case .configUrl:
return 4
case .blockchainName:
case .configString:
return 5
case .blockchainNameHeader:
return 6
case .blockchainName:
return 7
case .blockchainNameInfo:
return 8
}
}
@ -87,6 +96,8 @@ private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
func item(_ arguments: Any) -> ListViewItem {
let arguments = arguments as! WalletConfigurationScreenArguments
switch self {
case let .modeHeader(theme, text):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .modeUrl(theme, text, isSelected):
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: isSelected, zeroSeparatorInsets: false, sectionId: self.section, action: {
arguments.updateSelectedMode(.url)
@ -95,14 +106,18 @@ private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: isSelected, zeroSeparatorInsets: false, sectionId: self.section, action: {
arguments.updateSelectedMode(.customString)
})
case let .modeInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
case let .configUrl(theme, strings, placeholder, text):
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: ""), text: text, placeholder: placeholder, sectionId: self.section, textUpdated: { value in
return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: nil, sectionId: self.section, style: .blocks, capitalization: false, autocorrection: false, returnKeyType: .done, minimalHeight: nil, textUpdated: { value in
arguments.updateState { state in
var state = state
state.configUrl = value
return state
}
}, action: {})
}, shouldUpdateText: { _ in
return true
}, processPaste: nil, updatedFocus: nil, tag: WalletConfigurationScreenEntryTag.configStringText, action: nil, inlineAction: nil)
case let .configString(theme, placeholder, text):
return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: nil, sectionId: self.section, style: .blocks, capitalization: false, autocorrection: false, returnKeyType: .done, minimalHeight: nil, textUpdated: { value in
arguments.updateState { state in
@ -119,6 +134,8 @@ private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: ""), text: value, placeholder: title, sectionId: self.section, textUpdated: { value in
arguments.updateBlockchainName(value)
}, action: {})
case let .blockchainNameInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
}
}
}
@ -145,18 +162,21 @@ private struct WalletConfigurationScreenState: Equatable {
private func walletConfigurationScreenEntries(presentationData: WalletPresentationData, state: WalletConfigurationScreenState) -> [WalletConfigurationScreenEntry] {
var entries: [WalletConfigurationScreenEntry] = []
entries.append(.modeUrl(presentationData.theme, "URL", state.mode == .url))
entries.append(.modeCustomString(presentationData.theme, "Custom", state.mode == .customString))
entries.append(.modeHeader(presentationData.theme, presentationData.strings.Wallet_Configuration_SourceHeader))
entries.append(.modeUrl(presentationData.theme, presentationData.strings.Wallet_Configuration_SourceURL, state.mode == .url))
entries.append(.modeCustomString(presentationData.theme, presentationData.strings.Wallet_Configuration_SourceJSON, state.mode == .customString))
entries.append(.modeInfo(presentationData.theme, presentationData.strings.Wallet_Configuration_SourceInfo))
switch state.mode {
case .url:
entries.append(.configUrl(presentationData.theme, presentationData.strings, "URL", state.configUrl))
entries.append(.configUrl(presentationData.theme, presentationData.strings, presentationData.strings.Wallet_Configuration_SourceURL, state.configUrl))
case .customString:
entries.append(.configString(presentationData.theme, "JSON", state.configString))
entries.append(.configString(presentationData.theme, presentationData.strings.Wallet_Configuration_SourceJSON, state.configString))
}
entries.append(.blockchainNameHeader(presentationData.theme, "BLOCKCHAIN NAME"))
entries.append(.blockchainName(presentationData.theme, presentationData.strings, "Blockchain Name", state.blockchainName))
entries.append(.blockchainNameHeader(presentationData.theme, presentationData.strings.Wallet_Configuration_BlockchainIdHeader))
entries.append(.blockchainName(presentationData.theme, presentationData.strings, presentationData.strings.Wallet_Configuration_BlockchainIdPlaceholder, state.blockchainName))
entries.append(.blockchainNameInfo(presentationData.theme, presentationData.strings.Wallet_Configuration_BlockchainIdInfo))
return entries
}
@ -170,6 +190,10 @@ private final class WalletConfigurationScreenImpl: ItemListController, WalletCon
}
}
private func presentError(context: WalletContext, present: ((ViewController, Any?) -> Void)?, title: String?, text: String) {
present?(standardTextAlertController(theme: context.presentationData.theme.alert, title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: context.presentationData.strings.Wallet_Alert_OK, action: {})]), nil)
}
func walletConfigurationScreen(context: WalletContext, currentConfiguration: LocalWalletConfiguration) -> ViewController {
var configUrl = ""
var configString = ""
@ -237,15 +261,74 @@ func walletConfigurationScreen(context: WalletContext, currentConfiguration: Loc
source = .string(state.configString)
}
}
let _ = (context.storage.updateLocalWalletConfiguration { current in
var current = current
current.source = source
current.blockchainName = blockchainName
return current
}
|> deliverOnMainQueue).start(completed: {
if currentConfiguration.source != source || currentConfiguration.blockchainName != blockchainName {
let applyResolved: (String) -> Void = { resolvedConfig in
let proceed: () -> Void = {
let _ = (context.updateResolvedWalletConfiguration(source: source, blockchainName: blockchainName, resolvedValue: resolvedConfig)
|> deliverOnMainQueue).start(completed: {
dismissImpl?()
})
}
if blockchainName != currentConfiguration.blockchainName {
presentControllerImpl?(standardTextAlertController(theme: context.presentationData.theme.alert, title: context.presentationData.strings.Wallet_Configuration_BlockchainNameChangedTitle, text: context.presentationData.strings.Wallet_Configuration_BlockchainNameChangedText, actions: [
TextAlertAction(type: .genericAction, title: context.presentationData.strings.Wallet_Alert_Cancel, action: {}),
TextAlertAction(type: .destructiveAction, title: context.presentationData.strings.Wallet_Configuration_BlockchainNameChangedProceed, action: {
proceed()
}),
]), nil)
} else {
proceed()
}
}
let presentationData = context.presentationData
switch source {
case let .url(url):
if let parsedUrl = URL(string: url) {
let statusController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
presentControllerImpl?(statusController, nil)
let _ = (context.downloadFile(url: parsedUrl)
|> deliverOnMainQueue).start(next: { data in
statusController.dismiss()
guard let string = String(data: data, encoding: .utf8) else {
let presentationData = context.presentationData
presentError(context: context, present: presentControllerImpl, title: presentationData.strings.Wallet_Configuration_ApplyErrorTitle, text: presentationData.strings.Wallet_Configuration_ApplyErrorTextURLInvalidData)
return
}
let _ = (context.tonInstance.validateConfig(config: string, blockchainName: blockchainName)
|> deliverOnMainQueue).start(error: { _ in
let presentationData = context.presentationData
presentError(context: context, present: presentControllerImpl, title: presentationData.strings.Wallet_Configuration_ApplyErrorTitle, text: presentationData.strings.Wallet_Configuration_ApplyErrorTextURLInvalidData)
}, completed: {
applyResolved(string)
})
}, error: { _ in
statusController.dismiss()
let presentationData = context.presentationData
presentError(context: context, present: presentControllerImpl, title: presentationData.strings.Wallet_Configuration_ApplyErrorTitle, text: presentationData.strings.Wallet_Configuration_ApplyErrorTextURLUnreachable(url).0)
})
} else {
presentError(context: context, present: presentControllerImpl, title: presentationData.strings.Wallet_Configuration_ApplyErrorTitle, text: presentationData.strings.Wallet_Configuration_ApplyErrorTextURLInvalid)
return
}
case let .string(string):
let _ = (context.tonInstance.validateConfig(config: string, blockchainName: blockchainName)
|> deliverOnMainQueue).start(error: { _ in
let presentationData = context.presentationData
presentError(context: context, present: presentControllerImpl, title: presentationData.strings.Wallet_Configuration_ApplyErrorTitle, text: presentationData.strings.Wallet_Configuration_ApplyErrorTextJSONInvalidData)
}, completed: {
applyResolved(string)
})
}
} else {
dismissImpl?()
})
}
})
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Wallet_Configuration_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Wallet_Navigation_Back), animateChanges: false)

View File

@ -8,6 +8,10 @@ public enum WalletContextGetServerSaltError {
case generic
}
public enum WalletDownloadFileError {
case generic
}
public protocol WalletContext {
var storage: WalletStorageInterface { get }
var tonInstance: TonInstance { get }
@ -21,6 +25,9 @@ public protocol WalletContext {
var inForeground: Signal<Bool, NoError> { get }
func getServerSalt() -> Signal<Data, WalletContextGetServerSaltError>
func downloadFile(url: URL) -> Signal<Data, WalletDownloadFileError>
func updateResolvedWalletConfiguration(source: LocalWalletConfigurationSource, blockchainName: String, resolvedValue: String) -> Signal<Never, NoError>
func presentNativeController(_ controller: UIViewController)

View File

@ -1100,3 +1100,66 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
}
}
}
private final class WalletApplicationSplashScreenNode: ASDisplayNode {
private let headerBackgroundNode: ASDisplayNode
private let headerCornerNode: ASImageNode
init(theme: WalletTheme) {
self.headerBackgroundNode = ASDisplayNode()
self.headerBackgroundNode.backgroundColor = .black
self.headerCornerNode = ASImageNode()
self.headerCornerNode.displaysAsynchronously = false
self.headerCornerNode.displayWithoutProcessing = true
self.headerCornerNode.image = generateImage(CGSize(width: 20.0, height: 10.0), rotatedContext: { size, context in
context.setFillColor(UIColor.black.cgColor)
context.fill(CGRect(origin: CGPoint(), size: size))
context.setBlendMode(.copy)
context.setFillColor(UIColor.clear.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: 20.0, height: 20.0)))
})?.stretchableImage(withLeftCapWidth: 10, topCapHeight: 1)
super.init()
self.backgroundColor = theme.list.itemBlocksBackgroundColor
self.addSubnode(self.headerBackgroundNode)
self.addSubnode(self.headerCornerNode)
}
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
let headerHeight = navigationHeight + 260.0
transition.updateFrame(node: self.headerBackgroundNode, frame: CGRect(origin: CGPoint(x: -1.0, y: 0), size: CGSize(width: layout.size.width + 2.0, height: headerHeight)))
transition.updateFrame(node: self.headerCornerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: headerHeight), size: CGSize(width: layout.size.width, height: 10.0)))
}
}
public final class WalletApplicationSplashScreen: ViewController {
private let theme: WalletTheme
public init(theme: WalletTheme) {
self.theme = theme
let navigationBarTheme = NavigationBarTheme(buttonColor: .white, disabledButtonColor: .white, primaryTextColor: .white, backgroundColor: .clear, separatorColor: .clear, badgeBackgroundColor: theme.navigationBar.badgeBackgroundColor, badgeStrokeColor: theme.navigationBar.badgeStrokeColor, badgeTextColor: theme.navigationBar.badgeTextColor)
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: "", close: "")))
self.statusBar.statusBarStyle = .White
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func loadDisplayNode() {
self.displayNode = WalletApplicationSplashScreenNode(theme: self.theme)
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
(self.displayNode as! WalletApplicationSplashScreenNode).containerLayoutUpdated(layout: layout, navigationHeight: self.navigationHeight, transition: transition)
}
}

View File

@ -324,6 +324,6 @@ func walletStringsFormattedNumber(_ count: Int32, _ groupingSeparator: String =
}
}
func OverlayStatusController(theme: WalletTheme, type: OverlayStatusControllerType) -> ViewController {
public func OverlayStatusController(theme: WalletTheme, type: OverlayStatusControllerType) -> ViewController {
return OverlayStatusController(style: theme.keyboardAppearance == .dark ? .dark : .light, type: type)
}

View File

@ -28,13 +28,14 @@ private enum WalletSettingsSection: Int32 {
private enum WalletSettingsEntry: ItemListNodeEntry {
case configuration(WalletTheme, String)
case configurationInfo(WalletTheme, String)
case exportWallet(WalletTheme, String)
case deleteWallet(WalletTheme, String)
case deleteWalletInfo(WalletTheme, String)
var section: ItemListSectionId {
switch self {
case .configuration:
case .configuration, .configurationInfo:
return WalletSettingsSection.configuration.rawValue
case .exportWallet:
return WalletSettingsSection.exportWallet.rawValue
@ -47,12 +48,14 @@ private enum WalletSettingsEntry: ItemListNodeEntry {
switch self {
case .configuration:
return 0
case .exportWallet:
case .configurationInfo:
return 1
case .deleteWallet:
case .exportWallet:
return 2
case .deleteWalletInfo:
case .deleteWallet:
return 3
case .deleteWalletInfo:
return 4
}
}
@ -67,6 +70,8 @@ private enum WalletSettingsEntry: ItemListNodeEntry {
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openConfiguration()
})
case let .configurationInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
case let .exportWallet(theme, text):
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.exportWallet()
@ -89,6 +94,7 @@ private func walletSettingsControllerEntries(presentationData: WalletPresentatio
if supportsCustomConfigurations {
entries.append(.configuration(presentationData.theme, presentationData.strings.Wallet_Settings_Configuration))
entries.append(.configurationInfo(presentationData.theme, presentationData.strings.Wallet_Settings_ConfigurationInfo))
}
entries.append(.exportWallet(presentationData.theme, presentationData.strings.Wallet_Settings_BackupWallet))
entries.append(.deleteWallet(presentationData.theme, presentationData.strings.Wallet_Settings_DeleteWallet))

View File

@ -190,243 +190,261 @@ public final class WalletStrings: Equatable {
public var Wallet_Updated_JustNow: String { return self._s[0]! }
public var Wallet_WordCheck_IncorrectText: String { return self._s[1]! }
public var Wallet_Month_ShortNovember: String { return self._s[2]! }
public var Wallet_Info_Send: String { return self._s[3]! }
public var Wallet_TransactionInfo_SendGrams: String { return self._s[4]! }
public var Wallet_Configuration_BlockchainIdPlaceholder: String { return self._s[3]! }
public var Wallet_Info_Send: String { return self._s[4]! }
public var Wallet_TransactionInfo_SendGrams: String { return self._s[5]! }
public func Wallet_Info_TransactionBlockchainFee(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[5]!, self._r[5]!, [_0])
return formatWithArgumentRanges(self._s[6]!, self._r[6]!, [_0])
}
public var Wallet_Sent_Title: String { return self._s[6]! }
public var Wallet_Receive_ShareUrlInfo: String { return self._s[7]! }
public var Wallet_RestoreFailed_Title: String { return self._s[8]! }
public var Wallet_TransactionInfo_CopyAddress: String { return self._s[10]! }
public var Wallet_Settings_BackupWallet: String { return self._s[11]! }
public var Wallet_Send_NetworkErrorTitle: String { return self._s[12]! }
public var Wallet_Month_ShortJune: String { return self._s[13]! }
public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[14]! }
public var Wallet_Created_Title: String { return self._s[15]! }
public var Wallet_Send_SyncInProgress: String { return self._s[16]! }
public var Wallet_Info_YourBalance: String { return self._s[17]! }
public var Wallet_TransactionInfo_CommentHeader: String { return self._s[18]! }
public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[19]! }
public var Wallet_Sent_Title: String { return self._s[7]! }
public var Wallet_Receive_ShareUrlInfo: String { return self._s[8]! }
public var Wallet_RestoreFailed_Title: String { return self._s[9]! }
public var Wallet_TransactionInfo_CopyAddress: String { return self._s[11]! }
public var Wallet_Settings_BackupWallet: String { return self._s[12]! }
public var Wallet_Send_NetworkErrorTitle: String { return self._s[13]! }
public var Wallet_Month_ShortJune: String { return self._s[14]! }
public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[15]! }
public var Wallet_Created_Title: String { return self._s[16]! }
public func Wallet_Configuration_ApplyErrorTextURLUnreachable(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[17]!, self._r[17]!, [_0])
}
public var Wallet_Send_SyncInProgress: String { return self._s[18]! }
public var Wallet_Info_YourBalance: String { return self._s[19]! }
public var Wallet_Configuration_ApplyErrorTextURLInvalidData: String { return self._s[20]! }
public var Wallet_TransactionInfo_CommentHeader: String { return self._s[21]! }
public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[22]! }
public func Wallet_Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[20]!, self._r[20]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[23]!, self._r[23]!, [_1, _2, _3])
}
public var Wallet_WordImport_IncorrectText: String { return self._s[21]! }
public var Wallet_Month_GenJanuary: String { return self._s[22]! }
public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[23]! }
public var Wallet_Receive_ShareAddress: String { return self._s[24]! }
public var Wallet_WordImport_Title: String { return self._s[25]! }
public var Wallet_TransactionInfo_Title: String { return self._s[26]! }
public var Wallet_Words_NotDoneText: String { return self._s[28]! }
public var Wallet_RestoreFailed_EnterWords: String { return self._s[29]! }
public var Wallet_WordImport_Text: String { return self._s[30]! }
public var Wallet_RestoreFailed_Text: String { return self._s[32]! }
public var Wallet_TransactionInfo_NoAddress: String { return self._s[33]! }
public var Wallet_Navigation_Back: String { return self._s[34]! }
public var Wallet_Intro_Terms: String { return self._s[35]! }
public var Wallet_Settings_ConfigurationInfo: String { return self._s[24]! }
public var Wallet_WordImport_IncorrectText: String { return self._s[25]! }
public var Wallet_Month_GenJanuary: String { return self._s[26]! }
public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[27]! }
public var Wallet_Receive_ShareAddress: String { return self._s[28]! }
public var Wallet_WordImport_Title: String { return self._s[29]! }
public var Wallet_TransactionInfo_Title: String { return self._s[30]! }
public var Wallet_Words_NotDoneText: String { return self._s[32]! }
public var Wallet_RestoreFailed_EnterWords: String { return self._s[33]! }
public var Wallet_WordImport_Text: String { return self._s[34]! }
public var Wallet_RestoreFailed_Text: String { return self._s[36]! }
public var Wallet_TransactionInfo_NoAddress: String { return self._s[37]! }
public var Wallet_Navigation_Back: String { return self._s[38]! }
public var Wallet_Intro_Terms: String { return self._s[39]! }
public func Wallet_Send_Balance(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[36]!, self._r[36]!, [_0])
return formatWithArgumentRanges(self._s[40]!, self._r[40]!, [_0])
}
public func Wallet_Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[37]!, self._r[37]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[41]!, self._r[41]!, [_1, _2, _3])
}
public var Wallet_TransactionInfo_AddressCopied: String { return self._s[38]! }
public var Wallet_TransactionInfo_AddressCopied: String { return self._s[42]! }
public func Wallet_Info_TransactionDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[39]!, self._r[39]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[43]!, self._r[43]!, [_1, _2, _3])
}
public var Wallet_Send_NetworkErrorText: String { return self._s[40]! }
public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[41]! }
public var Wallet_Intro_ImportExisting: String { return self._s[42]! }
public var Wallet_Receive_CommentInfo: String { return self._s[43]! }
public var Wallet_WordCheck_Continue: String { return self._s[44]! }
public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[45]! }
public var Wallet_Completed_Text: String { return self._s[46]! }
public var Wallet_WordCheck_IncorrectHeader: String { return self._s[48]! }
public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[49]! }
public var Wallet_Receive_Title: String { return self._s[50]! }
public var Wallet_Info_WalletCreated: String { return self._s[51]! }
public var Wallet_Navigation_Cancel: String { return self._s[52]! }
public var Wallet_CreateInvoice_Title: String { return self._s[53]! }
public var Wallet_Send_NetworkErrorText: String { return self._s[44]! }
public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[45]! }
public var Wallet_Intro_ImportExisting: String { return self._s[46]! }
public var Wallet_Receive_CommentInfo: String { return self._s[47]! }
public var Wallet_WordCheck_Continue: String { return self._s[48]! }
public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[49]! }
public var Wallet_Completed_Text: String { return self._s[50]! }
public var Wallet_WordCheck_IncorrectHeader: String { return self._s[52]! }
public var Wallet_Configuration_SourceHeader: String { return self._s[53]! }
public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[54]! }
public var Wallet_Receive_Title: String { return self._s[55]! }
public var Wallet_Info_WalletCreated: String { return self._s[56]! }
public var Wallet_Navigation_Cancel: String { return self._s[57]! }
public var Wallet_CreateInvoice_Title: String { return self._s[58]! }
public func Wallet_WordCheck_Text(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[54]!, self._r[54]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[59]!, self._r[59]!, [_1, _2, _3])
}
public var Wallet_TransactionInfo_SenderHeader: String { return self._s[55]! }
public var Wallet_TransactionInfo_SenderHeader: String { return self._s[60]! }
public func Wallet_Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[56]!, self._r[56]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[61]!, self._r[61]!, [_1, _2, _3])
}
public var Wallet_Month_GenAugust: String { return self._s[57]! }
public var Wallet_Info_UnknownTransaction: String { return self._s[58]! }
public var Wallet_Receive_CreateInvoice: String { return self._s[59]! }
public var Wallet_Month_GenSeptember: String { return self._s[60]! }
public var Wallet_Month_GenJuly: String { return self._s[61]! }
public var Wallet_Receive_AddressHeader: String { return self._s[62]! }
public var Wallet_Send_AmountText: String { return self._s[63]! }
public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[64]! }
public var Wallet_Month_GenAugust: String { return self._s[62]! }
public var Wallet_Info_UnknownTransaction: String { return self._s[63]! }
public var Wallet_Receive_CreateInvoice: String { return self._s[64]! }
public var Wallet_Month_GenSeptember: String { return self._s[65]! }
public var Wallet_Month_GenJuly: String { return self._s[66]! }
public var Wallet_Receive_AddressHeader: String { return self._s[67]! }
public var Wallet_Send_AmountText: String { return self._s[68]! }
public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[69]! }
public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[65]!, self._r[65]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[70]!, self._r[70]!, [_1, _2, _3])
}
public func Wallet_Updated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[66]!, self._r[66]!, [_0])
return formatWithArgumentRanges(self._s[71]!, self._r[71]!, [_0])
}
public var Wallet_Configuration_Title: String { return self._s[68]! }
public var Wallet_Words_Title: String { return self._s[69]! }
public var Wallet_Month_ShortMay: String { return self._s[70]! }
public var Wallet_WordCheck_Title: String { return self._s[71]! }
public var Wallet_Words_NotDoneResponse: String { return self._s[72]! }
public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[73]! }
public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[74]! }
public var Wallet_Configuration_Title: String { return self._s[73]! }
public var Wallet_Configuration_BlockchainIdHeader: String { return self._s[74]! }
public var Wallet_Words_Title: String { return self._s[75]! }
public var Wallet_Month_ShortMay: String { return self._s[76]! }
public var Wallet_WordCheck_Title: String { return self._s[77]! }
public var Wallet_Words_NotDoneResponse: String { return self._s[78]! }
public var Wallet_Configuration_SourceURL: String { return self._s[79]! }
public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[80]! }
public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[81]! }
public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[75]!, self._r[75]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[82]!, self._r[82]!, [_1, _2, _3])
}
public var Wallet_Info_Address: String { return self._s[76]! }
public var Wallet_Intro_CreateWallet: String { return self._s[77]! }
public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[78]! }
public var Wallet_Info_Address: String { return self._s[83]! }
public var Wallet_Intro_CreateWallet: String { return self._s[84]! }
public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[85]! }
public func Wallet_SecureStorageReset_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[79]!, self._r[79]!, [_0])
return formatWithArgumentRanges(self._s[86]!, self._r[86]!, [_0])
}
public var Wallet_Send_SendAnyway: String { return self._s[80]! }
public var Wallet_UnknownError: String { return self._s[81]! }
public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[82]! }
public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[84]! }
public var Wallet_Words_NotDoneOk: String { return self._s[85]! }
public var Wallet_Intro_Title: String { return self._s[86]! }
public var Wallet_Info_Receive: String { return self._s[87]! }
public var Wallet_Completed_ViewWallet: String { return self._s[88]! }
public var Wallet_Month_ShortJuly: String { return self._s[89]! }
public var Wallet_Month_ShortApril: String { return self._s[90]! }
public var Wallet_Send_SendAnyway: String { return self._s[87]! }
public var Wallet_UnknownError: String { return self._s[88]! }
public var Wallet_Configuration_ApplyErrorTextURLInvalid: String { return self._s[89]! }
public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[90]! }
public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[92]! }
public var Wallet_Configuration_SourceInfo: String { return self._s[93]! }
public var Wallet_Words_NotDoneOk: String { return self._s[94]! }
public var Wallet_Intro_Title: String { return self._s[95]! }
public var Wallet_Info_Receive: String { return self._s[96]! }
public var Wallet_Completed_ViewWallet: String { return self._s[97]! }
public var Wallet_Month_ShortJuly: String { return self._s[98]! }
public var Wallet_Month_ShortApril: String { return self._s[99]! }
public func Wallet_Info_TransactionDateHeader(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[91]!, self._r[91]!, [_1, _2])
return formatWithArgumentRanges(self._s[100]!, self._r[100]!, [_1, _2])
}
public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[92]! }
public var Wallet_Receive_ShareInvoiceUrl: String { return self._s[101]! }
public func Wallet_Time_PreciseDate_m10(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[93]!, self._r[93]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[102]!, self._r[102]!, [_1, _2, _3])
}
public var Wallet_Send_UninitializedText: String { return self._s[95]! }
public var Wallet_Send_UninitializedText: String { return self._s[104]! }
public func Wallet_Sent_Text(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[96]!, self._r[96]!, [_0])
return formatWithArgumentRanges(self._s[105]!, self._r[105]!, [_0])
}
public var Wallet_Month_GenNovember: String { return self._s[97]! }
public var Wallet_Month_GenNovember: String { return self._s[106]! }
public func Wallet_Time_PreciseDate_m5(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[98]!, self._r[98]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[107]!, self._r[107]!, [_1, _2, _3])
}
public var Wallet_Month_GenApril: String { return self._s[99]! }
public var Wallet_Month_ShortMarch: String { return self._s[100]! }
public var Wallet_Month_GenFebruary: String { return self._s[101]! }
public var Wallet_Qr_ScanCode: String { return self._s[102]! }
public var Wallet_Receive_AddressCopied: String { return self._s[103]! }
public var Wallet_Send_UninitializedTitle: String { return self._s[104]! }
public var Wallet_Send_Send: String { return self._s[105]! }
public var Wallet_Info_RefreshErrorTitle: String { return self._s[106]! }
public var Wallet_Month_GenJune: String { return self._s[107]! }
public var Wallet_Send_AddressHeader: String { return self._s[108]! }
public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[109]! }
public var Wallet_Send_Confirmation: String { return self._s[110]! }
public var Wallet_Completed_Title: String { return self._s[111]! }
public var Wallet_Alert_OK: String { return self._s[112]! }
public var Wallet_Settings_DeleteWallet: String { return self._s[113]! }
public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[114]! }
public var Wallet_Month_ShortSeptember: String { return self._s[115]! }
public var Wallet_Info_TransactionTo: String { return self._s[116]! }
public var Wallet_Send_ConfirmationConfirm: String { return self._s[117]! }
public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[118]! }
public var Wallet_Receive_AmountText: String { return self._s[119]! }
public var Wallet_Receive_CopyAddress: String { return self._s[120]! }
public var Wallet_Intro_Text: String { return self._s[122]! }
public var Wallet_Configuration_Apply: String { return self._s[123]! }
public var Wallet_Month_GenApril: String { return self._s[108]! }
public var Wallet_Month_ShortMarch: String { return self._s[109]! }
public var Wallet_Month_GenFebruary: String { return self._s[110]! }
public var Wallet_Qr_ScanCode: String { return self._s[111]! }
public var Wallet_Receive_AddressCopied: String { return self._s[112]! }
public var Wallet_Send_UninitializedTitle: String { return self._s[113]! }
public var Wallet_Send_Send: String { return self._s[114]! }
public var Wallet_Info_RefreshErrorTitle: String { return self._s[115]! }
public var Wallet_Month_GenJune: String { return self._s[116]! }
public var Wallet_Send_AddressHeader: String { return self._s[117]! }
public var Wallet_SecureStorageReset_BiometryTouchId: String { return self._s[118]! }
public var Wallet_Send_Confirmation: String { return self._s[119]! }
public var Wallet_Completed_Title: String { return self._s[120]! }
public var Wallet_Alert_OK: String { return self._s[121]! }
public var Wallet_Settings_DeleteWallet: String { return self._s[122]! }
public var Wallet_SecureStorageReset_PasscodeText: String { return self._s[123]! }
public var Wallet_Month_ShortSeptember: String { return self._s[124]! }
public var Wallet_Info_TransactionTo: String { return self._s[125]! }
public var Wallet_Send_ConfirmationConfirm: String { return self._s[126]! }
public var Wallet_TransactionInfo_OtherFeeInfo: String { return self._s[127]! }
public var Wallet_Receive_AmountText: String { return self._s[128]! }
public var Wallet_Receive_CopyAddress: String { return self._s[129]! }
public var Wallet_Intro_Text: String { return self._s[131]! }
public var Wallet_Configuration_Apply: String { return self._s[132]! }
public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[124]!, self._r[124]!, [_0])
return formatWithArgumentRanges(self._s[133]!, self._r[133]!, [_0])
}
public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[125]!, self._r[125]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[134]!, self._r[134]!, [_1, _2, _3])
}
public var Wallet_RestoreFailed_CreateWallet: String { return self._s[126]! }
public var Wallet_Weekday_Yesterday: String { return self._s[127]! }
public var Wallet_Receive_AmountHeader: String { return self._s[128]! }
public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[129]! }
public var Wallet_Month_ShortFebruary: String { return self._s[130]! }
public var Wallet_Alert_Cancel: String { return self._s[131]! }
public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[132]! }
public var Wallet_Info_TransactionFrom: String { return self._s[133]! }
public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[134]! }
public var Wallet_Send_OwnAddressAlertText: String { return self._s[135]! }
public var Wallet_Words_NotDoneTitle: String { return self._s[136]! }
public var Wallet_Month_ShortOctober: String { return self._s[137]! }
public var Wallet_Month_GenMay: String { return self._s[138]! }
public var Wallet_Intro_CreateErrorTitle: String { return self._s[139]! }
public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[140]! }
public var Wallet_Month_ShortJanuary: String { return self._s[141]! }
public var Wallet_Month_GenMarch: String { return self._s[142]! }
public var Wallet_Sending_Text: String { return self._s[143]! }
public var Wallet_Month_GenOctober: String { return self._s[144]! }
public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[145]! }
public var Wallet_ContextMenuCopy: String { return self._s[146]! }
public var Wallet_RestoreFailed_CreateWallet: String { return self._s[135]! }
public var Wallet_Weekday_Yesterday: String { return self._s[136]! }
public var Wallet_Receive_AmountHeader: String { return self._s[137]! }
public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[138]! }
public var Wallet_Month_ShortFebruary: String { return self._s[139]! }
public var Wallet_Configuration_SourceJSON: String { return self._s[140]! }
public var Wallet_Alert_Cancel: String { return self._s[141]! }
public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[142]! }
public var Wallet_Configuration_ApplyErrorTextJSONInvalidData: String { return self._s[143]! }
public var Wallet_Info_TransactionFrom: String { return self._s[144]! }
public var Wallet_Send_ErrorDecryptionFailed: String { return self._s[145]! }
public var Wallet_Send_OwnAddressAlertText: String { return self._s[146]! }
public var Wallet_Words_NotDoneTitle: String { return self._s[147]! }
public var Wallet_Month_ShortOctober: String { return self._s[148]! }
public var Wallet_Month_GenMay: String { return self._s[149]! }
public var Wallet_Intro_CreateErrorTitle: String { return self._s[150]! }
public var Wallet_SecureStorageReset_BiometryFaceId: String { return self._s[151]! }
public var Wallet_Month_ShortJanuary: String { return self._s[152]! }
public var Wallet_Month_GenMarch: String { return self._s[153]! }
public var Wallet_Sending_Text: String { return self._s[154]! }
public var Wallet_Month_GenOctober: String { return self._s[155]! }
public var Wallet_Receive_CopyInvoiceUrl: String { return self._s[156]! }
public var Wallet_ContextMenuCopy: String { return self._s[157]! }
public func Wallet_Time_PreciseDate_m6(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[147]!, self._r[147]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[158]!, self._r[158]!, [_1, _2, _3])
}
public var Wallet_Info_Updating: String { return self._s[149]! }
public var Wallet_Created_ExportErrorTitle: String { return self._s[150]! }
public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[151]! }
public var Wallet_Sending_Title: String { return self._s[152]! }
public var Wallet_Navigation_Done: String { return self._s[153]! }
public var Wallet_Settings_Title: String { return self._s[154]! }
public var Wallet_Info_Updating: String { return self._s[160]! }
public var Wallet_Created_ExportErrorTitle: String { return self._s[161]! }
public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[162]! }
public var Wallet_Sending_Title: String { return self._s[163]! }
public var Wallet_Navigation_Done: String { return self._s[164]! }
public var Wallet_Configuration_BlockchainIdInfo: String { return self._s[165]! }
public var Wallet_Configuration_BlockchainNameChangedTitle: String { return self._s[166]! }
public var Wallet_Settings_Title: String { return self._s[167]! }
public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[155]!, self._r[155]!, [_0])
return formatWithArgumentRanges(self._s[168]!, self._r[168]!, [_0])
}
public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[156]! }
public var Wallet_Weekday_Today: String { return self._s[158]! }
public var Wallet_Month_ShortDecember: String { return self._s[159]! }
public var Wallet_Words_Text: String { return self._s[160]! }
public var Wallet_WordCheck_ViewWords: String { return self._s[161]! }
public var Wallet_Send_AddressInfo: String { return self._s[162]! }
public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[169]! }
public var Wallet_Weekday_Today: String { return self._s[171]! }
public var Wallet_Month_ShortDecember: String { return self._s[172]! }
public var Wallet_Words_Text: String { return self._s[173]! }
public var Wallet_Configuration_BlockchainNameChangedProceed: String { return self._s[174]! }
public var Wallet_WordCheck_ViewWords: String { return self._s[175]! }
public var Wallet_Send_AddressInfo: String { return self._s[176]! }
public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[163]!, self._r[163]!, [_0])
return formatWithArgumentRanges(self._s[177]!, self._r[177]!, [_0])
}
public var Wallet_Intro_NotNow: String { return self._s[164]! }
public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[165]! }
public var Wallet_Navigation_Close: String { return self._s[166]! }
public var Wallet_Month_GenDecember: String { return self._s[168]! }
public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[169]! }
public var Wallet_WordImport_IncorrectTitle: String { return self._s[170]! }
public var Wallet_Send_AddressText: String { return self._s[171]! }
public var Wallet_Receive_AmountInfo: String { return self._s[172]! }
public var Wallet_Intro_NotNow: String { return self._s[178]! }
public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[179]! }
public var Wallet_Navigation_Close: String { return self._s[180]! }
public var Wallet_Month_GenDecember: String { return self._s[182]! }
public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[183]! }
public var Wallet_WordImport_IncorrectTitle: String { return self._s[184]! }
public var Wallet_Send_AddressText: String { return self._s[185]! }
public var Wallet_Receive_AmountInfo: String { return self._s[186]! }
public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[173]!, self._r[173]!, [_1, _2, _3])
}
public var Wallet_Month_ShortAugust: String { return self._s[174]! }
public var Wallet_Qr_Title: String { return self._s[175]! }
public var Wallet_Settings_Configuration: String { return self._s[176]! }
public var Wallet_WordCheck_TryAgain: String { return self._s[177]! }
public var Wallet_Info_TransactionPendingHeader: String { return self._s[178]! }
public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[179]! }
public var Wallet_Send_TransactionInProgress: String { return self._s[180]! }
public var Wallet_Created_Text: String { return self._s[181]! }
public var Wallet_Created_Proceed: String { return self._s[182]! }
public var Wallet_Words_Done: String { return self._s[183]! }
public var Wallet_WordImport_Continue: String { return self._s[184]! }
public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[185]! }
public var Wallet_WordImport_CanNotRemember: String { return self._s[186]! }
public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[187]!, self._r[187]!, [_1, _2, _3])
}
public var Wallet_Month_ShortAugust: String { return self._s[188]! }
public var Wallet_Qr_Title: String { return self._s[189]! }
public var Wallet_Settings_Configuration: String { return self._s[190]! }
public var Wallet_WordCheck_TryAgain: String { return self._s[191]! }
public var Wallet_Info_TransactionPendingHeader: String { return self._s[192]! }
public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[193]! }
public var Wallet_Configuration_ApplyErrorTitle: String { return self._s[194]! }
public var Wallet_Send_TransactionInProgress: String { return self._s[195]! }
public var Wallet_Created_Text: String { return self._s[196]! }
public var Wallet_Created_Proceed: String { return self._s[197]! }
public var Wallet_Words_Done: String { return self._s[198]! }
public var Wallet_WordImport_Continue: String { return self._s[199]! }
public var Wallet_TransactionInfo_StorageFeeHeader: String { return self._s[200]! }
public var Wallet_WordImport_CanNotRemember: String { return self._s[201]! }
public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[202]!, self._r[202]!, [_1, _2, _3])
}
public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[188]!, self._r[188]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[203]!, self._r[203]!, [_1, _2, _3])
}
public var Wallet_Created_ExportErrorText: String { return self._s[190]! }
public var Wallet_Created_ExportErrorText: String { return self._s[205]! }
public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[191]!, self._r[191]!, [_0])
return formatWithArgumentRanges(self._s[206]!, self._r[206]!, [_0])
}
public var Wallet_Settings_DeleteWalletInfo: String { return self._s[192]! }
public var Wallet_Intro_CreateErrorText: String { return self._s[193]! }
public var Wallet_Sent_ViewWallet: String { return self._s[194]! }
public var Wallet_Send_ErrorInvalidAddress: String { return self._s[195]! }
public var Wallet_Settings_DeleteWalletInfo: String { return self._s[207]! }
public var Wallet_Intro_CreateErrorText: String { return self._s[208]! }
public var Wallet_Sent_ViewWallet: String { return self._s[209]! }
public var Wallet_Send_ErrorInvalidAddress: String { return self._s[210]! }
public var Wallet_Configuration_BlockchainNameChangedText: String { return self._s[211]! }
public func Wallet_Time_PreciseDate_m7(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
return formatWithArgumentRanges(self._s[196]!, self._r[196]!, [_1, _2, _3])
return formatWithArgumentRanges(self._s[212]!, self._r[212]!, [_1, _2, _3])
}
public var Wallet_Send_Title: String { return self._s[197]! }
public var Wallet_Info_RefreshErrorText: String { return self._s[198]! }
public var Wallet_SecureStorageReset_Title: String { return self._s[199]! }
public var Wallet_Receive_CommentHeader: String { return self._s[200]! }
public var Wallet_Info_ReceiveGrams: String { return self._s[201]! }
public var Wallet_Send_Title: String { return self._s[213]! }
public var Wallet_Info_RefreshErrorText: String { return self._s[214]! }
public var Wallet_SecureStorageReset_Title: String { return self._s[215]! }
public var Wallet_Receive_CommentHeader: String { return self._s[216]! }
public var Wallet_Info_ReceiveGrams: String { return self._s[217]! }
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
let form = getPluralizationForm(self.lc, value)
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "TopLeft.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "TopRight.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -9,7 +9,7 @@ get_filename_component(TON_REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPAT
get_filename_component(TON_REAL_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
if (TON_REAL_BINARY_DIR STREQUAL TON_REAL_SOURCE_DIR)
message(" Out-of-source build should be used to build TDLib.")
message(" Out-of-source build should be used to build TON.")
message(" You need to remove the files already created by CMake and")
message(" rerun CMake from a new directory:")
message(" rm -rf CMakeFiles CMakeCache.txt")
@ -341,7 +341,7 @@ if (NOT CMAKE_CROSSCOMPILING)
if (TDUTILS_MIME_TYPE)
set(TDMIME_AUTO tdmime_auto)
endif()
add_custom_target(prepare_cross_compiling DEPENDS tl_generate_common tlb_generate_block ${TDMIME_AUTO})
add_custom_target(prepare_cross_compiling DEPENDS tl_generate_common tlb_generate_block gen_fif ${TDMIME_AUTO})
endif()
#TESTS

View File

@ -207,6 +207,7 @@ set(SMC_ENVELOPE_SOURCE
smc-envelope/TestGiver.cpp
smc-envelope/TestWallet.cpp
smc-envelope/Wallet.cpp
smc-envelope/WalletV3.cpp
smc-envelope/GenericAccount.h
smc-envelope/MultisigWallet.h
@ -215,6 +216,7 @@ set(SMC_ENVELOPE_SOURCE
smc-envelope/TestGiver.h
smc-envelope/TestWallet.h
smc-envelope/Wallet.h
smc-envelope/WalletV3.h
)
set(ED25519_TEST_SOURCE
@ -350,6 +352,7 @@ if (NOT CMAKE_CROSSCOMPILING)
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/wallet3-code SOURCE smartcont/wallet3-code.fc NAME wallet3)
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)

View File

@ -13514,34 +13514,80 @@ const ValidatorDescr t_ValidatorDescr;
//
// code for type `ValidatorSet`
//
constexpr unsigned char ValidatorSet::cons_tag[1];
constexpr unsigned char ValidatorSet::cons_tag[2];
int ValidatorSet::get_tag(const vm::CellSlice& cs) const {
switch (cs.bselect(6, 0x30)) {
case 0:
return cs.bit_at(6) ? validators_ext : validators;
default:
return -1;
}
}
int ValidatorSet::check_tag(const vm::CellSlice& cs) const {
return cs.prefetch_ulong(8) == 17 ? validators : -1;
switch (get_tag(cs)) {
case validators:
return cs.prefetch_ulong(8) == 17 ? validators : -1;
case validators_ext:
return cs.prefetch_ulong(8) == 18 ? validators_ext : -1;
}
return -1;
}
bool ValidatorSet::skip(vm::CellSlice& cs) const {
int total, main;
return cs.advance(72)
&& cs.fetch_uint_to(16, total)
&& cs.fetch_uint_to(16, main)
&& main <= total
&& 1 <= main
&& t_Hashmap_16_ValidatorDescr.skip(cs);
switch (get_tag(cs)) {
case validators: {
int total, main;
return cs.advance(72)
&& cs.fetch_uint_to(16, total)
&& cs.fetch_uint_to(16, main)
&& main <= total
&& 1 <= main
&& t_Hashmap_16_ValidatorDescr.skip(cs);
}
case validators_ext: {
int total, main;
return cs.advance(72)
&& cs.fetch_uint_to(16, total)
&& cs.fetch_uint_to(16, main)
&& main <= total
&& 1 <= main
&& cs.advance(64)
&& t_HashmapE_16_ValidatorDescr.skip(cs);
}
}
return false;
}
bool ValidatorSet::validate_skip(vm::CellSlice& cs, bool weak) const {
int total, main;
return cs.fetch_ulong(8) == 17
&& cs.advance(64)
&& cs.fetch_uint_to(16, total)
&& cs.fetch_uint_to(16, main)
&& main <= total
&& 1 <= main
&& t_Hashmap_16_ValidatorDescr.validate_skip(cs, weak);
switch (get_tag(cs)) {
case validators: {
int total, main;
return cs.fetch_ulong(8) == 17
&& cs.advance(64)
&& cs.fetch_uint_to(16, total)
&& cs.fetch_uint_to(16, main)
&& main <= total
&& 1 <= main
&& t_Hashmap_16_ValidatorDescr.validate_skip(cs, weak);
}
case validators_ext: {
int total, main;
return cs.fetch_ulong(8) == 18
&& cs.advance(64)
&& cs.fetch_uint_to(16, total)
&& cs.fetch_uint_to(16, main)
&& main <= total
&& 1 <= main
&& cs.advance(64)
&& t_HashmapE_16_ValidatorDescr.validate_skip(cs, weak);
}
}
return false;
}
bool ValidatorSet::unpack(vm::CellSlice& cs, ValidatorSet::Record& data) const {
bool ValidatorSet::unpack(vm::CellSlice& cs, ValidatorSet::Record_validators& data) const {
return cs.fetch_ulong(8) == 17
&& cs.fetch_uint_to(32, data.utime_since)
&& cs.fetch_uint_to(32, data.utime_until)
@ -13552,13 +13598,31 @@ bool ValidatorSet::unpack(vm::CellSlice& cs, ValidatorSet::Record& data) const {
&& t_Hashmap_16_ValidatorDescr.fetch_to(cs, data.list);
}
bool ValidatorSet::cell_unpack(Ref<vm::Cell> cell_ref, ValidatorSet::Record& data) const {
bool ValidatorSet::cell_unpack(Ref<vm::Cell> cell_ref, ValidatorSet::Record_validators& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ValidatorSet::pack(vm::CellBuilder& cb, const ValidatorSet::Record& data) const {
bool ValidatorSet::unpack(vm::CellSlice& cs, ValidatorSet::Record_validators_ext& data) const {
return cs.fetch_ulong(8) == 18
&& cs.fetch_uint_to(32, data.utime_since)
&& cs.fetch_uint_to(32, data.utime_until)
&& cs.fetch_uint_to(16, data.total)
&& cs.fetch_uint_to(16, data.main)
&& data.main <= data.total
&& 1 <= data.main
&& cs.fetch_uint_to(64, data.total_weight)
&& t_HashmapE_16_ValidatorDescr.fetch_to(cs, data.list);
}
bool ValidatorSet::cell_unpack(Ref<vm::Cell> cell_ref, ValidatorSet::Record_validators_ext& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ValidatorSet::pack(vm::CellBuilder& cb, const ValidatorSet::Record_validators& data) const {
return cb.store_long_bool(17, 8)
&& cb.store_ulong_rchk_bool(data.utime_since, 32)
&& cb.store_ulong_rchk_bool(data.utime_until, 32)
@ -13569,26 +13633,65 @@ bool ValidatorSet::pack(vm::CellBuilder& cb, const ValidatorSet::Record& data) c
&& t_Hashmap_16_ValidatorDescr.store_from(cb, data.list);
}
bool ValidatorSet::cell_pack(Ref<vm::Cell>& cell_ref, const ValidatorSet::Record& data) const {
bool ValidatorSet::cell_pack(Ref<vm::Cell>& cell_ref, const ValidatorSet::Record_validators& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ValidatorSet::pack(vm::CellBuilder& cb, const ValidatorSet::Record_validators_ext& data) const {
return cb.store_long_bool(18, 8)
&& cb.store_ulong_rchk_bool(data.utime_since, 32)
&& cb.store_ulong_rchk_bool(data.utime_until, 32)
&& cb.store_ulong_rchk_bool(data.total, 16)
&& cb.store_ulong_rchk_bool(data.main, 16)
&& data.main <= data.total
&& 1 <= data.main
&& cb.store_ulong_rchk_bool(data.total_weight, 64)
&& t_HashmapE_16_ValidatorDescr.store_from(cb, data.list);
}
bool ValidatorSet::cell_pack(Ref<vm::Cell>& cell_ref, const ValidatorSet::Record_validators_ext& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ValidatorSet::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
int total, main;
return cs.fetch_ulong(8) == 17
&& pp.open("validators")
&& pp.fetch_uint_field(cs, 32, "utime_since")
&& pp.fetch_uint_field(cs, 32, "utime_until")
&& cs.fetch_uint_to(16, total)
&& pp.field_int(total, "total")
&& cs.fetch_uint_to(16, main)
&& pp.field_int(main, "main")
&& main <= total
&& 1 <= main
&& pp.field("list")
&& t_Hashmap_16_ValidatorDescr.print_skip(pp, cs)
&& pp.close();
switch (get_tag(cs)) {
case validators: {
int total, main;
return cs.fetch_ulong(8) == 17
&& pp.open("validators")
&& pp.fetch_uint_field(cs, 32, "utime_since")
&& pp.fetch_uint_field(cs, 32, "utime_until")
&& cs.fetch_uint_to(16, total)
&& pp.field_int(total, "total")
&& cs.fetch_uint_to(16, main)
&& pp.field_int(main, "main")
&& main <= total
&& 1 <= main
&& pp.field("list")
&& t_Hashmap_16_ValidatorDescr.print_skip(pp, cs)
&& pp.close();
}
case validators_ext: {
int total, main;
return cs.fetch_ulong(8) == 18
&& pp.open("validators_ext")
&& pp.fetch_uint_field(cs, 32, "utime_since")
&& pp.fetch_uint_field(cs, 32, "utime_until")
&& cs.fetch_uint_to(16, total)
&& pp.field_int(total, "total")
&& cs.fetch_uint_to(16, main)
&& pp.field_int(main, "main")
&& main <= total
&& 1 <= main
&& pp.fetch_uint_field(cs, 64, "total_weight")
&& pp.field("list")
&& t_HashmapE_16_ValidatorDescr.print_skip(pp, cs)
&& pp.close();
}
}
return pp.fail("unknown constructor for ValidatorSet");
}
const ValidatorSet t_ValidatorSet;
@ -17308,6 +17411,7 @@ const HashmapE t_HashmapE_16_CryptoSignaturePair{16, t_CryptoSignaturePair};
const Maybe t_Maybe_Ref_InMsg{t_Ref_InMsg};
const RefT t_Ref_TYPE_1673{t_McBlockExtra_aux};
const Hashmap t_Hashmap_16_ValidatorDescr{16, t_ValidatorDescr};
const HashmapE t_HashmapE_16_ValidatorDescr{16, t_ValidatorDescr};
const Hashmap t_Hashmap_32_True{32, t_True};
const NatWidth t_natwidth_12{12};
const NatWidth t_natwidth_32{32};

View File

@ -5912,35 +5912,50 @@ extern const ValidatorDescr t_ValidatorDescr;
//
struct ValidatorSet final : TLB_Complex {
enum { validators };
enum { validators, validators_ext };
static constexpr int cons_len_exact = 8;
static constexpr unsigned char cons_tag[1] = { 17 };
struct Record;
static constexpr unsigned char cons_tag[2] = { 17, 18 };
struct Record_validators;
struct Record_validators_ext;
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, Record& data) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record& data) const;
bool pack(vm::CellBuilder& cb, const Record& data) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record& data) const;
bool unpack(vm::CellSlice& cs, Record_validators& data) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record_validators& data) const;
bool pack(vm::CellBuilder& cb, const Record_validators& data) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record_validators& data) const;
bool unpack(vm::CellSlice& cs, Record_validators_ext& data) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record_validators_ext& data) const;
bool pack(vm::CellBuilder& cb, const Record_validators_ext& data) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record_validators_ext& data) const;
bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "ValidatorSet";
}
int check_tag(const vm::CellSlice& cs) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
int get_tag(const vm::CellSlice& cs) const override;
};
struct ValidatorSet::Record {
struct ValidatorSet::Record_validators {
typedef ValidatorSet type_class;
unsigned utime_since; // utime_since : uint32
unsigned utime_until; // utime_until : uint32
int total; // total : ## 16
int main; // main : ## 16
Ref<CellSlice> list; // list : Hashmap 16 ValidatorDescr
Record() = default;
Record(unsigned _utime_since, unsigned _utime_until, int _total, int _main, Ref<CellSlice> _list) : utime_since(_utime_since), utime_until(_utime_until), total(_total), main(_main), list(std::move(_list)) {}
Record_validators() = default;
Record_validators(unsigned _utime_since, unsigned _utime_until, int _total, int _main, Ref<CellSlice> _list) : utime_since(_utime_since), utime_until(_utime_until), total(_total), main(_main), list(std::move(_list)) {}
};
struct ValidatorSet::Record_validators_ext {
typedef ValidatorSet type_class;
unsigned utime_since; // utime_since : uint32
unsigned utime_until; // utime_until : uint32
int total; // total : ## 16
int main; // main : ## 16
unsigned long long total_weight; // total_weight : uint64
Ref<CellSlice> list; // list : HashmapE 16 ValidatorDescr
Record_validators_ext() = default;
Record_validators_ext(unsigned _utime_since, unsigned _utime_until, int _total, int _main, unsigned long long _total_weight, Ref<CellSlice> _list) : utime_since(_utime_since), utime_until(_utime_until), total(_total), main(_main), total_weight(_total_weight), list(std::move(_list)) {}
};
extern const ValidatorSet t_ValidatorSet;
@ -7438,6 +7453,8 @@ extern const Maybe t_Maybe_Ref_InMsg;
extern const RefT t_Ref_TYPE_1673;
// Hashmap 16 ValidatorDescr
extern const Hashmap t_Hashmap_16_ValidatorDescr;
// HashmapE 16 ValidatorDescr
extern const HashmapE t_HashmapE_16_ValidatorDescr;
// Hashmap 32 True
extern const Hashmap t_Hashmap_32_True;
// ## 12

View File

@ -551,6 +551,9 @@ validator_addr#73 public_key:SigPubKey weight:uint64 adnl_addr:bits256 = Validat
validators#11 utime_since:uint32 utime_until:uint32
total:(## 16) main:(## 16) { main <= total } { main >= 1 }
list:(Hashmap 16 ValidatorDescr) = ValidatorSet;
validators_ext#12 utime_since:uint32 utime_until:uint32
total:(## 16) main:(## 16) { main <= total } { main >= 1 }
total_weight:uint64 list:(HashmapE 16 ValidatorDescr) = ValidatorSet;
_ config_addr:bits256 = ConfigParam 0;
_ elector_addr:bits256 = ConfigParam 1;

View File

@ -387,11 +387,25 @@ td::Result<std::unique_ptr<ValidatorSet>> Config::unpack_validator_set(Ref<vm::C
if (vset_root.is_null()) {
return td::Status::Error("validator set is absent");
}
gen::ValidatorSet::Record rec;
if (!tlb::unpack_cell(std::move(vset_root), rec)) {
return td::Status::Error("validator set is invalid");
gen::ValidatorSet::Record_validators_ext rec;
Ref<vm::Cell> dict_root;
if (!tlb::unpack_cell(vset_root, rec)) {
gen::ValidatorSet::Record_validators rec0;
if (!tlb::unpack_cell(std::move(vset_root), rec0)) {
return td::Status::Error("validator set is invalid");
}
rec.utime_since = rec0.utime_since;
rec.utime_until = rec0.utime_until;
rec.total = rec0.total;
rec.main = rec0.main;
dict_root = vm::Dictionary::construct_root_from(*rec0.list);
rec.total_weight = 0;
} else if (rec.total_weight) {
dict_root = rec.list->prefetch_ref();
} else {
return td::Status::Error("validator set cannot have zero total weight");
}
vm::Dictionary dict{vm::Dictionary::construct_root_from(*rec.list), 16};
vm::Dictionary dict{std::move(dict_root), 16};
td::BitArray<16> key_buffer;
auto last = dict.get_minmax_key(key_buffer.bits(), 16, true);
if (last.is_null() || (int)key_buffer.to_ulong() != rec.total - 1) {
@ -428,6 +442,9 @@ td::Result<std::unique_ptr<ValidatorSet>> Config::unpack_validator_set(Ref<vm::C
ptr->list.emplace_back(sig_pubkey.pubkey, descr.weight, ptr->total_weight, descr.adnl_addr);
ptr->total_weight += descr.weight;
}
if (rec.total_weight && rec.total_weight != ptr->total_weight) {
return td::Status::Error("validator set declares incorrect total weight");
}
return std::move(ptr);
}
@ -517,19 +534,16 @@ td::Result<std::vector<StoragePrices>> Config::get_storage_prices() const {
return std::move(res);
}
td::Result<GasLimitsPrices> Config::get_gas_limits_prices(bool is_masterchain) const {
td::Result<GasLimitsPrices> Config::do_get_gas_limits_prices(td::Ref<vm::Cell> cell, int id) {
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));
auto cs = vm::load_cell_slice(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;
} else {
cs = vm::load_cell_slice(cell);
}
auto f = [&](const auto& r, td::uint64 spec_limit) {
res.gas_limit = r.gas_limit;
@ -553,6 +567,14 @@ td::Result<GasLimitsPrices> Config::get_gas_limits_prices(bool is_masterchain) c
}
return res;
}
td::Result<GasLimitsPrices> Config::get_gas_limits_prices(bool is_masterchain) const {
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");
}
return do_get_gas_limits_prices(std::move(cell), id);
}
td::Result<MsgPrices> Config::get_msg_prices(bool is_masterchain) const {
auto id = is_masterchain ? 24 : 25;
@ -1071,47 +1093,47 @@ std::vector<ton::BlockId> ShardConfig::get_shard_hash_ids(
std::vector<ton::BlockId> 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<vm::CellSlice> 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<std::pair<Ref<vm::Cell>, 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))) {
[&res, &mcout, mc_shard_hash_ = mc_shard_hash_, &filter ](Ref<vm::CellSlice> 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;
}
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;
},
std::stack<std::pair<Ref<vm::Cell>, 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;
},
true);
if (!ok) {
return {};
@ -1467,8 +1489,8 @@ td::Result<std::vector<ton::StdSmcAddress>> Config::get_special_smartcontracts(b
return td::Status::Error(-666, "configuration loaded without fundamental smart contract list");
}
std::vector<ton::StdSmcAddress> res;
if (!special_smc_dict->check_for_each([&res, &without_config, conf_addr = config_addr.bits()](
Ref<vm::CellSlice> cs_ref, td::ConstBitPtr key, int n) {
if (!special_smc_dict->check_for_each([&res, &without_config, conf_addr = config_addr.bits() ](
Ref<vm::CellSlice> cs_ref, td::ConstBitPtr key, int n) {
if (cs_ref->size_ext() || n != 256) {
return false;
}

View File

@ -540,6 +540,7 @@ class Config {
static td::Result<std::unique_ptr<ValidatorSet>> unpack_validator_set(Ref<vm::Cell> valset_root);
td::Result<std::vector<StoragePrices>> get_storage_prices() const;
td::Result<GasLimitsPrices> get_gas_limits_prices(bool is_masterchain = false) const;
static td::Result<GasLimitsPrices> do_get_gas_limits_prices(td::Ref<vm::Cell> cell, int id);
td::Result<MsgPrices> get_msg_prices(bool is_masterchain = false) const;
static CatchainValidatorsConfig unpack_catchain_validators_config(Ref<vm::Cell> cell);
CatchainValidatorsConfig get_catchain_validators_config() const;

View File

@ -139,7 +139,7 @@ recursive append-long-bytes {
// ( 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"
base64url>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@

View File

@ -68,7 +68,7 @@ sym_idx_t SymTableBase::gen_lookup(std::string str, int mode, sym_idx_t idx) {
if (!(mode & 1)) {
return not_found;
}
if (def_sym >= ((long)p * 3) / 4) {
if (def_sym >= ((long long)p * 3) / 4) {
throw SymTableOverflow{def_sym};
}
sym_table[h1] = std::make_unique<Symbol>(str, idx <= 0 ? sym_idx_t(h1) : -idx);

View File

@ -1,4 +1,5 @@
"Asm.fif" include
"TonUtil.fif" include
31 -1<< constant wc_undef
0 constant wc_base
@ -187,6 +188,7 @@ dictnew constant special-dict
// restricted wallet creation
"auto/wallet-code.fif" include =: WCode0
"auto/restricted-wallet-code.fif" include =: RWCode1
"auto/restricted-wallet2-code.fif" include =: RWCode2
@ -200,7 +202,7 @@ dictnew constant special-dict
0 // ticktock
2 // mode: create
register_smc
Masterchain 6 .Addr cr
Masterchain swap 6 .Addr cr
} : create-wallet1
// D x t -- D'
@ -225,5 +227,18 @@ dictnew constant special-dict
0 // ticktock
2 // mode: create
register_smc
Masterchain 6 .Addr cr
Masterchain swap 6 .Addr cr
} : create-wallet2
// pubkey amount
{ over ."Key " pubkey>$ type ." -> "
WCode0 // code
<b 1 32 u, 3 roll 256 u, b> // data
empty_cell // libs
3 roll // balance
0 // split_depth
0 // ticktock
2 // mode: create
register_smc
Masterchain swap 6 .Addr cr
} : create-wallet0

View File

@ -1 +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==");
with_tvm_code("config", "te6ccgECJwEAA48AART/APSkE/Sg8sgLAQIBIAIDAgLHBAUCAvEjJAIBzQYHAAaqglsCASAICQIBIBUWAgEgCgsCASAQEQIBIAwNAgEgDg8A6QB0NMD+kAwIPpEAaQDcbATsSPHALGSXwPgAtMf0z8ighBOVlNUuo49MgHU0XH4MyBukjB/lNDXC//iA3AEupsyIfAEIfgjvAK8sJEC4p2AJFjwAYIQ7nZPS/AG4DGCEO52T2/wB+AQJF8EIMAAAYMesLHypYAAlO1E0NRQM4Ag9BXIzAHPFsntVIAApO1E0NTTH9P/IMcAkW2T9AQB4gHRgABsyBTMEssfy//0AMntVIAIBIBITAgEgFBQANzQ0wcBpu9+sPJJ0x/TH9MP0w8wIMIA8om+8omAAKxwgBjIywVQBc8WFMtuyx/LP8kB+wCAACSAQPAFgAgEgFxgCASAdHgIBIBkaAgEgGxwAWxx+DPQ1wv/+COCEE5Db2RwggDE/8jLEBTL/4Md+gITy2oSyx/LPwHPFslw+wCAAoQhghBDZlAhupwx0x/U0UATgCD0FQHgIYIQTkNvZLqOEDHUIfsE7UMC7VMB8QaC8gDgIYIQUGJLIbqVMTHT/9HgIYIQTkPvBbqTMfAI4DDyYIAEBICYAOTTB4AgsxKwwFPyqdMfAYIQjoEnirryqdP/0z8wgAgEgHyACASAhIgAfHAgcMjKAMs/y/8BzxbJ0IAANPQE0z/T/4AAZMgU9AASyz/L/wHPFoABFFsBcbCeIPkBMSGDB/QOb6ExkN+d1wv/IYMH9A5voTHyquKAArQw7UTQ1IAggCRTMfRqIG6TECNbjjgg0CDXScInjinTB9cLHwHAEfgjEr6wjhUBgCJUEET0blRTIfRuMIAkQBP0WjCTECNb4pQQNF8D4uLIzAHPFsntVIAHZIMI1xgg0x/TH9Mf+CMSufJj7UTQ1NMf0/8gxwCRbZP0BAHiAdFRUrryoSWCEFZvdGWhfrCK4Qb5AVQQdvkQ8qL4AAWkVHUEJcgUzBLLH8v/9ADJ7VT4DxA1RFXwCUMDyBTMEssfy//0AMntVICUBqgPTDyHbPNMHgCCzErDAU/Kp0x8BghCOgSeKuvKp0//TPzAJ+QFAqvkQ8qL4AAGkVHIDJ8gUzBLLH8v/9ADJ7VT4DxA1RxbwD8gUzBLLH8v/9ADJ7VQmADaAIvgzIG6SW23g0IBo1yHIAc8WyYAQ9A5voTA=");

View File

@ -1,6 +1,8 @@
// automatically generated from `smartcont/stdlib.fc` `smartcont/config-code.fc`
PROGRAM{
DECLPROC set_conf_param
DECLPROC load_data
DECLPROC store_data
DECLPROC check_validator_set
DECLPROC send_answer
DECLPROC send_confirmation
@ -9,6 +11,12 @@ PROGRAM{
DECLPROC change_elector_code
1666 DECLMETHOD after_code_upgrade
DECLPROC perform_action
DECLPROC get_validator_descr
DECLPROC unpack_validator_descr
DECLPROC create_new_entry
DECLPROC unpack_suggestion
DECLPROC pack_suggestion
DECLPROC register_vote
DECLPROC recv_external
DECLPROC run_ticktock
set_conf_param PROC:<{
@ -26,22 +34,54 @@ PROGRAM{
ENDC // _14
c4 POP
}>
load_data PROC:<{
//
c4 PUSH // _1
CTOS // cs
LDREF // _6 cs
32 LDU // _6 _8 cs
256 LDU // cfg_dict stored_seqno public_key cs
DUP // cfg_dict stored_seqno public_key cs cs
SEMPTY // cfg_dict stored_seqno public_key cs _15
IF:<{ // cfg_dict stored_seqno public_key cs
NEWDICT // cfg_dict stored_seqno public_key cs _16
}>ELSE<{ // cfg_dict stored_seqno public_key cs
LDDICT // cfg_dict stored_seqno public_key _16 cs
SWAP // cfg_dict stored_seqno public_key cs _16
}> // cfg_dict stored_seqno public_key cs vote_dict
SWAP // cfg_dict stored_seqno public_key vote_dict cs
ENDS
}>
store_data PROC:<{
// cfg_dict stored_seqno public_key vote_dict
NEWC // cfg_dict stored_seqno public_key vote_dict _4
s1 s4 XCHG // vote_dict stored_seqno public_key cfg_dict _4
STREF // vote_dict stored_seqno public_key _5
s1 s2 XCHG // vote_dict public_key stored_seqno _5
32 STU // vote_dict public_key _7
256 STU // vote_dict _9
STDICT // _10
ENDC // _11
c4 POP
}>
check_validator_set PROC:<{
// vset
CTOS // cs
8 LDU // _4 cs
SWAP // cs _4
17 EQINT // cs _8
9 THROWIFNOT
-17 ADDCONST // cs _8
-2 PUSHINT // cs _8 _9=-2
AND // cs _10
9 THROWIF
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
16 LDU // utime_since utime_until total _44 _43
DROP // utime_since utime_until total main
DUP // utime_since utime_until total main main
0 GTINT // utime_since utime_until total main _28
0 GTINT // utime_since utime_until total main _30
9 THROWIFNOT
GEQ // utime_since utime_until _31
GEQ // utime_since utime_until _33
9 THROWIFNOT
}>
send_answer PROC:<{
@ -188,7 +228,7 @@ PROGRAM{
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
IFJMP:<{ // 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
@ -196,52 +236,139 @@ PROGRAM{
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
SWAP // cfg_dict public_key
}> // 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
IFJMP:<{ // 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
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
SWAP // cfg_dict public_key cs old_code
after_code_upgrade CALLDICT
0 THROW
}> // 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
IFJMP:<{ // cfg_dict public_key action cs
NIP
NIP // cfg_dict cs
256 LDU // cfg_dict public_key cs
ENDS
}> // 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
IFJMP:<{ // cfg_dict public_key action cs
NIP // cfg_dict public_key cs
change_elector_code CALLDICT
}> // cfg_dict public_key action cs
DROP // cfg_dict public_key action
32 THROWIF
}>
get_validator_descr PROCREF:<{
// idx
34 PUSHINT // idx _2=34
CONFIGOPTPARAM // idx vset
DUP // idx vset vset
ISNULL // idx vset _4
IFJMP:<{ // idx vset
2DROP //
PUSHNULL // _5
}> // idx vset
CTOS // idx cs
104 PUSHINT // idx cs _17
SDSKIPFIRST // idx cs
NEWC // idx cs _20
SWAP // idx _20 cs
STSLICER // idx _21
ENDC // idx dict
16 PUSHINT // idx dict _25=16
DICTUGET
NULLSWAPIFNOT // _27 _28
DROP // value
}>
unpack_validator_descr PROC:<{
// cs
8 LDU // _2 cs
32 PUSHINT // _2 cs _5=32
NOT // _2 cs _6
s1 s2 XCHG // cs _2 _6
AND // cs _7
83 EQINT // cs _9
41 THROWIFNOT
32 LDU // _12 cs
SWAP
2390828938 PUSHINT // cs _12 _15=2390828938
EQUAL // cs _16
41 THROWIFNOT
256 LDU // _18 cs
64 LDU // _18 _31 _30
DROP // _18 _21
}>
create_new_entry PROC:<{
// cs
0 PUSHINT // cs _1=0
DUP // cs _1=0 _2=0
FALSE // cs _1=0 _2=0 _3
NEWC // cs _1=0 _2=0 _3 _4
1 STI // cs _1=0 _2=0 _6
64 STU // cs _1=0 _8
256 STU // cs _10
SWAP // _10 cs
STSLICER // _11
ENDC // _12
CTOS // _13
}>
unpack_suggestion PROC:<{
// cs
LDDICT // _1 cs
64 LDU // _1 _3 cs
256 LDU // _1 _3 _6 cs
}>
pack_suggestion PROC:<{
// voters sum_weight vset_id body
NEWC // voters sum_weight vset_id body _4
s1 s4 XCHG // body sum_weight vset_id voters _4
STDICT // body sum_weight vset_id _5
s1 s2 XCHG // body vset_id sum_weight _5
64 STU // body vset_id _7
256 STU // body _9
SWAP // _9 body
STSLICER // _10
}>
register_vote PROC:<{
// vote_dict action cs idx weight
2DROP // vote_dict action cs
SWAP
1 PUSHINT // vote_dict cs action _9=1
AND // vote_dict cs _10
IF:<{ // vote_dict cs
DUP // vote_dict cs cs
HASHSU // vote_dict cs _11
NIP // vote_dict hash
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
8 PUSHPOW2 // vote_dict hash vote_dict _13=256
DICTUGET
NULLSWAPIFNOT // vote_dict _23 _24
NIP // vote_dict found?
IFNOT:<{ // vote_dict
}> // vote_dict
}>ELSE<{ // vote_dict cs
256 PLDU // vote_dict hash
OVER
8 PUSHPOW2 // vote_dict hash vote_dict _19=256
DICTUGET
NULLSWAPIFNOT // vote_dict _25 _26
NIP // vote_dict found?
42 THROWIFNOT
}>
SWAP // cfg_dict public_key
}>
recv_external PROC:<{
// in_msg
@ -255,33 +382,55 @@ PROGRAM{
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
load_data INLINECALLDICT // signature in_msg action msg_seqno cs cfg_dict stored_seqno public_key vote_dict
s5 s2 XCPU // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key msg_seqno stored_seqno
EQUAL // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key _28
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
s5 PUSH
1450144869 PUSHINT // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key action _30=1450144869
SUB // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key _31
-2 PUSHINT // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key _31 _32=-2
AND // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key _33
IFNOTJMP:<{ // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key
s0 s3 XCHG // signature in_msg action vote_dict public_key cfg_dict stored_seqno cs
16 LDU // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs
OVER // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs idx
get_validator_descr INLINECALLDICT // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs vdescr
unpack_validator_descr INLINECALLDICT // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs val_pubkey weight
s0 s9 XCHG // signature weight action vote_dict public_key cfg_dict stored_seqno idx cs val_pubkey in_msg
HASHSU // signature weight action vote_dict public_key cfg_dict stored_seqno idx cs val_pubkey _44
s0 s10 s10 XCHG3 // cs weight action vote_dict public_key cfg_dict stored_seqno idx _44 signature val_pubkey
CHKSIGNU // cs weight action vote_dict public_key cfg_dict stored_seqno idx _45
34 THROWIFNOT
ACCEPT
SWAP // cs weight action vote_dict public_key cfg_dict idx stored_seqno
INC // cs weight action vote_dict public_key cfg_dict idx stored_seqno
s2 s0 s3 PUSH3
s7 PUSH // cs weight action vote_dict public_key cfg_dict idx stored_seqno cfg_dict stored_seqno public_key vote_dict
store_data INLINECALLDICT
COMMIT
s3 s5 XCHG
s7 s1 s6 XCHG3 // cfg_dict stored_seqno public_key vote_dict action cs idx weight
register_vote CALLDICT // cfg_dict stored_seqno public_key vote_dict
store_data INLINECALLDICT
}> // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key
s0 s6 XCHG // signature public_key action vote_dict cs cfg_dict stored_seqno in_msg
HASHSU // signature public_key action vote_dict cs cfg_dict stored_seqno _55
s0 s7 s6 XC2PU // stored_seqno public_key action vote_dict cs cfg_dict _55 signature public_key
CHKSIGNU // stored_seqno public_key action vote_dict cs cfg_dict _56
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
s0 s5 XCHG // cfg_dict public_key action vote_dict cs stored_seqno
INC // cfg_dict public_key action vote_dict cs stored_seqno
s5 s0 s4 PUSH3
s5 PUSH // cfg_dict public_key action vote_dict cs stored_seqno cfg_dict stored_seqno public_key vote_dict
store_data INLINECALLDICT
COMMIT
s3 s5 XCHG
s4 s5 s5 XCHG3 // stored_seqno vote_dict cfg_dict public_key action cs
perform_action CALLDICT // stored_seqno vote_dict cfg_dict public_key
s3 s0 s3 XCHG3 // cfg_dict stored_seqno public_key vote_dict
store_data INLINECALLDICT
}>
run_ticktock PROC:<{
// is_tock

View File

@ -1 +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");
with_tvm_code("elector-code", "te6ccgECVQEACskAART/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+gIBzxbJ7VTigAgEgNTYCAUhPUAIBIDc4AgEgPT4CASA5OgIBIDs8AKU8AEH+kQBpLEhwACxlwWgVRMB8ALgUwKAIPQOb6GOJ9M/0//0BPoA+gALoMgVyz8Ty//0AAH6AgH6AlAGzxYBgCBURkT0Q5QwBaAB4hA1QUPwAoADZDEh+kQBpJ8wghD////+cBA0E4BA8Abg7UTQ9AT0BFAzgwf0Zm+hjhBfBIIQ/////nAQNBOAQPAG4TYF+gDRyBL0ABX0AAHPFsntVIIQ+W9zJHCAGMjLBVAEzxZQBPoCEstqEssfyz/JgED7AIABpHD4MyBuk18EcODQ1wv/I/pEAaQCvbGTXwNw4PgAAdQh+wQgxwCSXwSZAe1TAfEGgvIA4n+AAAxwgAgEgP0ACASBKSwA1HACjhMCbyIhbxACbxEkqKsPErYIEqBY5DAxgAQEgQQP+gBD4M9DTD9MPMdMP0XG2CXBtf45GKYMH9HxvoW+hII4wAvoA0x/TH9P/0//RA6PIFct/FMofUkDL/8nQURq2CMjLHxPL/8v/QBSBAaD0QQOklBA0WjDiAbNDMOYwNFi2CFMBuZdfB21wbVMR4G2K5jM0pVySbxHkcCCK5jIyNEJDRABqA4EBoPSSb6FvoSCOIAHTf1EZtggB0x8x1wv/A9Mf0/8x1wv/QTAUbwRQBW8Ck0YWW+IEsxQASgJvIgFvEASkU0i+jhBUZQbwFFMCvJMyMiKSEzDik1A0MOJTNr4BZDQiwABSQ7kSsZdfBG1wbVMR4CD+ICKlkm8R5G8QbxBwUwBtbYrmNDQ0NlJVuvKxQzQBRQT+Bm8iAW8kUx2DB/QOb6HyvfoAMdM/MdcL/1OcuY5aUTqoqw9SQLYIUUShJKo7LqkEUZWgUYmgghCOgSeKI5KAc5KAU+LIywfLH1JAy/9SoMs/I5MTy/+TUAMw4gGAEFRLmfRDcCTIy/8ayz9QBfoCGMoAQBqDB/RDiuIjioriBEZHSEkAEAsQeBBGA18DAAhMg/AKAAZMg1sAFqQqbhBbEFcVEDQSAQEgTAGtPABgCL4M/kAUwG6k18HcOAiji9TJIAg9A5voY4f0x8xINMf0/8wUAS68rn4I1ADoMjLH1jPFkAEgCD0Q5QVE18D4pNEFFvif4rmIG6SMHCQ4lAD8AJ/gTgH8AfADNPgjJbmTXwhw4HD4M26UXwjwE+CAEfgz0PoA+gD6ANMf0VNhuZRfDPAT4ASUXwvwE+AGk18KcOAQOChRMlB38BUgwAAgsysGEFsQShA5Td3wBCOOFDEyMjIyMsgS9AD0AAHPFsntVPAT4fAFMvgjAaCmxCm2CYAQ+DPQTQDQgBDXIdcLD1JwtghTE6CAEsjLB1Iwyx/LHxjLDxfLDxrLPxP0AMlw+DPQ1wv/UxjwCQn0BHAL+QBQZKApoMjLHxnLHxLL/xX0AFAD+gJw+gIWygBANIAg9EPIE/QA9AD0AAHPFsntVH8ApCGAIPR8b6FvoSCOPwLTP9P/Uxe6ji00A/QE+gD6ACirAlGZoVApoMgVyz8Wy/8S9AAB+gIB+gJYzxYBgCBUQUT0Q3CWEDUQNF8D4pNDAzDisxICASBRUgIBIFNUABkIW6SW3CVAfkAAbrigAJUAfADBV8Fk18DcOEC9ARRMYAg9A5voZNfBHDhgEDXIdcL/4Ai+DMh8BiAJPgzWPAYsY4TcMjKABL0APQAAc8Wye1U8Bcwf+BfA3CAAkzwAX+OPiSAIPR8b6FvoSCOJALTHzD4I7tTFL2wjhExVBVE8A4UoFR2E1RzWPACcJRGFVBE4pYQNxZFBTDisxAmEEUU5gZfBm6zgAOEMYAk+DNukltw4XH4M9DXC//4KPpEAaQCvbGSW3DggCL4MyBuk18DcODwBTAyAtCAKNch1wsf+CNRE6FcuZNfBnDgXKHBPJExkTDigBH4M9D6ADADoP4gUgKhcG1wEEUQNHDwBMj0APQAAc8Wye1Uf4A==");

View File

@ -845,7 +845,7 @@ PROGRAM{
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
16 LDU // credits members min_stake max_stake min_total_stake max_stake_factor _13 _258 _257
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
@ -910,44 +910,44 @@ PROGRAM{
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
0 PUSHINT // credits _86 _87=0
NEWDICT // credits _86 _87=0 _88
s1 s1 PUSH2 // credits _86 _87=0 _88 _89=0 _90=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
416 PUSHINT // credits members min_stake max_stake min_total_stake l min_validators n sdict _101
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
128 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _106 key
s1 s9 XCPU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key _106 max_stake
MIN // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f key _109
SWAP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _109 key
32 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _109 _284 _283
NIP // credits members min_stake max_stake min_total_stake l min_validators n sdict cs f _109 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
32 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _118 cs
256 LDU // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _118 _288 _287
NIP // credits members min_stake max_stake min_total_stake l min_validators n sdict pubkey f stake _118 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
4 TUPLE // credits members min_stake max_stake min_total_stake l min_validators n sdict f _126
s0 s5 XCHG2 // credits members min_stake max_stake min_total_stake f min_validators n sdict _126 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
NOT // credits members min_stake max_stake min_total_stake l min_validators n sdict _128
s1 s4 XCHG // credits members min_stake max_stake min_total_stake sdict min_validators n l _128
}> // 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
@ -956,22 +956,22 @@ PROGRAM{
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
0 PUSHINT // credits members min_stake n min_total_stake l i l1 _136=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
UNCONS // credits members min_stake n min_total_stake l i m best_stake _139 l1
SWAP // credits members min_stake n min_total_stake l i m best_stake l1 _139
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
GEQ // credits members min_stake n min_total_stake l stake m best_stake l1 i _145
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
GREATER // credits members min_stake n min_total_stake l i m best_stake l1 tot_stake _148
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
@ -985,144 +985,149 @@ PROGRAM{
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
GEQ // credits members min_stake n min_total_stake l i l1 best_stake m _149
}> // 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
0 EQINT // credits members best_stake m min_total_stake l _151
s4 s2 PUXC // credits members best_stake m _151 l best_stake min_total_stake
LESS // credits members best_stake m _151 l _152
s1 s2 XCHG // credits members best_stake m l _151 _152
OR // credits members best_stake m l _153
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
NEWDICT // credits _154
0 PUSHINT // credits _154 _155=0
NEWDICT // credits _154 _155=0 _156
s1 s1 PUSH2 // credits _154 _155=0 _156 _157=0 _158=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
DEC // credits members best_stake m l l1 _163
REPEAT:<{ // credits members best_stake m l l1
CDR // credits members best_stake m l l1
}>
CAR // credits members best_stake m l _164
CAR // credits members best_stake m l _166
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
s0 s0 PUSH2 // credits members best_stake m l m_stake i=0 tot_stake=0 tot_weight=0
NEWDICT // credits members best_stake m l m_stake i=0 tot_stake=0 tot_weight=0 vset
NEWDICT // credits members best_stake m l m_stake i=0 tot_stake=0 tot_weight=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
s0 s6 XCHG // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l
UNCONS // credits members best_stake m frozen m_stake i tot_stake tot_weight vset _183 l
SWAP // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l _183
4 UNTUPLE // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr
s1 s13 PUSH2
8 PUSHPOW2 // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr pubkey members _188=256
DICTUGET
NULLSWAPIFNOT // credits members best_stake m frozen m_stake i tot_stake vset l stake max_f pubkey adnl_addr val f
NULLSWAPIFNOT // credits members best_stake m frozen m_stake i tot_stake tot_weight 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
LDGRAMS // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr _300 _299
NIP // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr val
64 LDU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr _302 _301
NIP // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr val
256 PLDU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr
s9 s12 PUSH2 // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr i m
LESS // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr _202
IF:<{ // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake max_f pubkey adnl_addr src_addr
s3 s10 XCPU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr max_f m_stake
MUL // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr _204
16 RSHIFT# // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr _206
s4 s(-1) PUXC // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr stake _206
MIN // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l stake src_addr pubkey adnl_addr true_stake
s4 s4 XCPU // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake true_stake
SUB // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake
s4 PUSH // credits members best_stake m frozen m_stake i tot_stake tot_weight 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 tot_weight vset l true_stake src_addr pubkey adnl_addr stake _211
s14 PUSH // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake _211 best_stake
DIV // credits members best_stake m frozen m_stake i tot_stake tot_weight vset l true_stake src_addr pubkey adnl_addr stake weight
s9 s5 XCPU // credits members best_stake m frozen m_stake i weight tot_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 tot_weight vset l true_stake src_addr pubkey adnl_addr stake tot_stake
s8 s9 XCPU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight weight
ADD // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight
2390828938 PUSHINT // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938
s3 PUSH // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938 adnl_addr
IF:<{ // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938
115 PUSHINT // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938 _217=115
}>ELSE<{ // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938
83 PUSHINT // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938 _217=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
NEWC // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938 _217 _220
8 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _216=2390828938 _222
32 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _224
s4 s(-1) PUXC // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight pubkey _224
256 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight _226
s10 s(-1) PUXC // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight weight _226
64 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight vinfo
s3 PUSH // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight vinfo adnl_addr
IF:<{ // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey adnl_addr stake tot_weight vinfo
s1 s3 XCHG // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey tot_weight stake adnl_addr vinfo
256 STU // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey tot_weight 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
DROP // credits members best_stake m frozen m_stake i weight tot_stake vset l true_stake src_addr pubkey tot_weight 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
s11 s8 s8 PUXC2 // credits members best_stake m frozen m_stake i weight tot_stake stake l true_stake src_addr pubkey tot_weight vinfo i vset _233=16
DICTUSETB // credits members best_stake m frozen m_stake i weight tot_stake stake l true_stake src_addr pubkey tot_weight vset
FALSE // credits members best_stake m frozen m_stake i weight tot_stake stake l true_stake src_addr pubkey tot_weight vset _236
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
NEWC // credits members best_stake m frozen m_stake i weight tot_stake stake l true_stake src_addr pubkey tot_weight vset _236 src_addr _237
256 STU // credits members best_stake m frozen m_stake i weight tot_stake stake l true_stake src_addr pubkey tot_weight vset _236 _239
s1 s10 XCHG // credits members best_stake m frozen m_stake i _236 tot_stake stake l true_stake src_addr pubkey tot_weight vset weight _239
64 STU // credits members best_stake m frozen m_stake i _236 tot_stake stake l true_stake src_addr pubkey tot_weight vset _241
s0 s5 XCHG2 // credits members best_stake m frozen m_stake i _236 tot_stake stake l vset src_addr pubkey tot_weight _241 true_stake
STGRAMS // credits members best_stake m frozen m_stake i _236 tot_stake stake l vset src_addr pubkey tot_weight _242
s1 s8 XCHG // credits members best_stake m frozen m_stake i tot_weight tot_stake stake l vset src_addr pubkey _236 _242
1 STI // credits members best_stake m frozen m_stake i tot_weight tot_stake stake l vset src_addr pubkey _244
s0 s1 s10 XCHG3
8 PUSHPOW2 // credits members best_stake m src_addr m_stake i tot_weight tot_stake stake l vset _244 pubkey frozen _245=256
DICTUSETB // credits members best_stake m src_addr m_stake i tot_weight tot_stake stake l vset frozen
}>ELSE<{
s0 s10 XCHG
s0 s11 XCHG
s7 s8 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
3 BLKDROP // credits members best_stake m src_addr m_stake i tot_weight 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
s3 PUSH // credits members best_stake m src_addr m_stake i tot_weight tot_stake stake l vset frozen stake
IF:<{ // credits members best_stake m src_addr m_stake i tot_weight tot_stake stake l vset frozen
s12 s8 s3 XCHG3 // l members best_stake m vset m_stake i tot_weight tot_stake frozen credits src_addr stake
~credit_to CALLDICT // l members best_stake m vset m_stake i tot_weight tot_stake frozen credits
}>ELSE<{
s11 s7 s3 XCHG3
2DROP // l members best_stake m vset m_stake i tot_stake frozen credits
s12 s8 s3 XCHG3
2DROP // l members best_stake m vset m_stake i tot_weight 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
s0 s4 XCHG // l members best_stake m vset m_stake credits tot_weight tot_stake frozen i
INC // l members best_stake m vset m_stake credits tot_weight tot_stake frozen i
s10 PUSH // l members best_stake m vset m_stake credits tot_weight tot_stake frozen i l
ISNULL // l members best_stake m vset m_stake credits tot_weight tot_stake frozen i _251
s5 s11 XCHG
s5 s7 XCHG
s1 s5 XCHG
s3 s4 XCHG
s1 s2 XCHG // credits members best_stake m l m_stake i tot_stake tot_weight vset frozen _251
}> // credits members best_stake m l m_stake i tot_stake tot_weight vset frozen
s4 POP
s4 POP
s4 POP
s6 POP // credits tot_stake best_stake m tot_weight vset frozen
s5 s4 PUXC // credits tot_stake frozen m tot_weight vset tot_stake best_stake
EQUAL // credits tot_stake frozen m tot_weight vset _253
49 THROWIFNOT
s2 s3 XCHG
SWAP // credits vset frozen tot_stake m
s3 s3 s4 XCHG3
SWAP // credits vset tot_weight 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
unpack_elect CALLDICT // ds credits _132 _133 _134 _135 _136 _137 _138
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
@ -1166,109 +1171,111 @@ PROGRAM{
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
try_elect CALLDICT // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt
DUP // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt cnt
0 EQINT // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt failed
DUP // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt failed failed
NOT // ds members elect_at elect_close min_stake total_stake credits vdict total_weight frozen total_stakes cnt failed finished
s11 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
s5 s11 XCHG
s4 s10 XCHG
s3 s9 XCHG
s13 s13 s13 XCHG3 // ds total_weight elect_at frozen total_stakes cnt credits vdict elect_at elect_close min_stake total_stake members failed finished
pack_elect CALLDICT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect
s3 PUSH // ds total_weight elect_at frozen total_stakes cnt credits vdict elect cnt
IFNOTJMP:<{ // ds total_weight elect_at frozen total_stakes cnt credits vdict elect
NIP
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
NEWC // ds elect credits _49
s1 s2 XCHG // ds credits elect _49
STDICT // ds credits _50
STDICT // ds _51
SWAP // _51 ds
STSLICER // _52
ENDC // _53
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
postpone_elections CALLDICT // _55
}> // ds total_weight elect_at frozen total_stakes cnt credits vdict elect
get_validator_conf CALLDICT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect _153 _154 _155 _156
s2 POP // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held elect_end_before
NOW // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held elect_end_before _62
SWAP // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _62 elect_end_before
ADD // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _63
-60 ADDCONST // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _65
s9 PUSH // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held _65 elect_at
MAX // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start
16 PUSHINT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _68=16
CONFIGOPTPARAM // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _69
CTOS // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _70
16 PUSHINT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _70 _71=16
SDSKIPFIRST // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _72
16 PLDU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start main_validators
s7 s(-1) PUXC // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start cnt main_validators
MIN // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76
s1 s3 PUSH2 // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 start elect_for
ADD // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77
18 PUSHINT // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _78=18
NEWC // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _78=18 _79
8 STU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _81
s3 s(-1) PUXC // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 start _81
32 STU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _77 _83
32 STU // ds total_weight elect_at frozen total_stakes cnt credits vdict elect elect_for stake_held start _76 _85
s1 s8 XCHG // ds total_weight elect_at frozen total_stakes _76 credits vdict elect elect_for stake_held start cnt _85
16 STU // ds total_weight elect_at frozen total_stakes _76 credits vdict elect elect_for stake_held start _87
s1 s7 XCHG // ds total_weight elect_at frozen total_stakes start credits vdict elect elect_for stake_held _76 _87
16 STU // ds total_weight elect_at frozen total_stakes start credits vdict elect elect_for stake_held _89
s1 s10 XCHG // ds stake_held elect_at frozen total_stakes start credits vdict elect elect_for total_weight _89
64 STU // ds stake_held elect_at frozen total_stakes start credits vdict elect elect_for _91
s1 s3 XCHG // ds stake_held elect_at frozen total_stakes start credits elect_for elect vdict _91
STDICT // ds stake_held elect_at frozen total_stakes start credits elect_for elect _92
ENDC // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset
0 PUSHINT // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset _95=0
CONFIGOPTPARAM // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset _96
CTOS // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset _97
256 PLDU // ds stake_held elect_at frozen total_stakes start credits elect_for elect vset config_addr
s1 s8 PUSH2 // ds stake_held elect_at frozen total_stakes start credits elect_for elect 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 s9 XCHG // vset stake_held elect_at frozen total_stakes start credits elect_for elect ds
LDDICT // vset stake_held elect_at frozen total_stakes start credits elect_for elect past_elect ds
FALSE // vset stake_held elect_at frozen total_stakes start credits elect_for elect past_elect ds _105
s0 s11 XCHG // _105 stake_held elect_at frozen total_stakes start credits elect_for elect past_elect ds vset
HASHCU // _105 stake_held elect_at frozen total_stakes start credits elect_for elect past_elect ds _106
s6 s4 XCHG2 // _105 stake_held elect_at frozen total_stakes ds credits _106 elect past_elect start elect_for
ADD // _105 stake_held elect_at frozen total_stakes ds credits _106 elect past_elect _107
s9 PUSH // _105 stake_held elect_at frozen total_stakes ds credits _106 elect past_elect _107 stake_held
ADD // _105 stake_held elect_at frozen total_stakes ds credits _106 elect past_elect _108
NEWC // _105 stake_held elect_at frozen total_stakes ds credits _106 elect past_elect _108 _109
32 STU // _105 stake_held elect_at frozen total_stakes ds credits _106 elect past_elect _111
s1 s9 XCHG // _105 past_elect elect_at frozen total_stakes ds credits _106 elect stake_held _111
32 STU // _105 past_elect elect_at frozen total_stakes ds credits _106 elect _113
s1 s2 XCHG // _105 past_elect elect_at frozen total_stakes ds credits elect _106 _113
256 STU // _105 past_elect elect_at frozen total_stakes ds credits elect _115
s1 s5 XCHG // _105 past_elect elect_at elect total_stakes ds credits frozen _115
STDICT // _105 past_elect elect_at elect total_stakes ds credits _116
s0 s3 XCHG2 // _105 past_elect elect_at elect credits ds _116 total_stakes
STGRAMS // _105 past_elect elect_at elect credits ds _117
0 PUSHINT // _105 past_elect elect_at elect credits ds _117 _118=0
STGRAMS // _105 past_elect elect_at elect credits ds _119
s1 s6 XCHG // ds past_elect elect_at elect credits _105 _119
1 STI // ds past_elect elect_at elect credits _121
s0 s3 s4 XCHG3
32 PUSHINT // ds elect credits _119 elect_at past_elect _120=32
32 PUSHINT // ds elect credits _121 elect_at past_elect _122=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
NEWC // ds elect credits past_elect _124
s1 s3 XCHG // ds past_elect credits elect _124
STDICT // ds past_elect credits _125
STDICT // ds past_elect _126
STDICT // ds _127
SWAP // _127 ds
STSLICER // _128
ENDC // _129
c4 POP
TRUE // _129
TRUE // _131
}>
update_active_vset_id PROC:<{
//

View File

@ -0,0 +1 @@
with_tvm_code("wallet3", "te6ccgEBBgEAcwABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQCW8oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj+ACTINdKltMH1AL7AOgwAaTIyx/LH8v/ye1UAATQMAARoJkv2omhrhY/");

View File

@ -0,0 +1,65 @@
// automatically generated from `smartcont/stdlib.fc` `smartcont/wallet3-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
ACCEPT // public_key stored_seqno stored_subwallet cs
WHILE:<{
DUP // public_key stored_seqno stored_subwallet cs cs
SREFS // public_key stored_seqno stored_subwallet cs _51
}>DO<{ // public_key stored_seqno stored_subwallet cs
8 LDU // public_key stored_seqno stored_subwallet mode cs
LDREF // public_key stored_seqno stored_subwallet mode _56 cs
s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode
SENDRAWMSG
}> // public_key stored_seqno stored_subwallet cs
DROP // public_key stored_seqno stored_subwallet
SWAP // public_key stored_subwallet stored_seqno
INC // public_key stored_subwallet _60
NEWC // public_key stored_subwallet _60 _61
32 STU // public_key stored_subwallet _63
32 STU // public_key _65
256 STU // _67
ENDC // _68
c4 POP
}>
seqno PROC:<{
//
c4 PUSH // _0
CTOS // _1
32 PLDU // _3
}>
}END>c

View File

@ -1,15 +1,32 @@
;; Simple configuration smart contract
() set_conf_param(int index, cell value) impure {
var cs = begin_parse(get_data());
var cs = get_data().begin_parse();
var cfg_dict = cs~load_ref();
cfg_dict~idict_set_ref(32, index, value);
set_data(begin_cell().store_ref(cfg_dict).store_slice(cs).end_cell());
}
(cell, int, int, cell) load_data() inline {
var cs = get_data().begin_parse();
var (cfg_dict, stored_seqno, public_key) = (cs~load_ref(), cs~load_uint(32), cs~load_uint(256));
var vote_dict = cs.slice_empty?() ? new_dict() : cs~load_dict();
cs.end_parse();
return (cfg_dict, stored_seqno, public_key, vote_dict);
}
() store_data(cfg_dict, stored_seqno, public_key, vote_dict) impure inline {
set_data(begin_cell()
.store_ref(cfg_dict)
.store_uint(stored_seqno, 32)
.store_uint(public_key, 256)
.store_dict(vote_dict)
.end_cell());
}
(int, int) check_validator_set(cell vset) {
var cs = vset.begin_parse();
throw_unless(9, cs~load_uint(8) == 0x11); ;; validators#11
throw_if(9, (cs~load_uint(8) - 0x11) & -2); ;; validators#11 or validators_ext#12
int utime_since = cs~load_uint(32);
int utime_until = cs~load_uint(32);
int total = cs~load_uint(16);
@ -96,27 +113,79 @@ _ perform_action(cfg_dict, public_key, action, cs) {
var param_value = cs~load_ref();
cs.end_parse();
cfg_dict~idict_set_ref(32, param_index, param_value);
return (cfg_dict, public_key);
} 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);
}
var old_code = get_c3();
set_c3(new_code);
after_code_upgrade(cs, old_code);
throw(0);
return (cfg_dict, public_key);
} elseif (action == 0x50624b21) {
;; change configuration master public key
public_key = cs~load_uint(256);
cs.end_parse();
return (cfg_dict, public_key);
} elseif (action == 0x4e43ef05) {
;; change election smart contract code
change_elector_code(cs);
return (cfg_dict, public_key);
} else {
throw_if(32, action);
return (cfg_dict, public_key);
}
return (cfg_dict, public_key);
}
slice get_validator_descr(int idx) inline_ref {
var vset = config_param(34);
if (vset.null?()) {
return null();
}
var cs = begin_parse(vset);
cs~skip_bits(8 + 32 + 32 + 16 + 16);
var dict = begin_cell().store_slice(cs).end_cell();
var (value, _) = dict.udict_get?(16, idx);
return value;
}
(int, int) unpack_validator_descr(slice cs) inline {
;; ed25519_pubkey#8e81278a pubkey:bits256 = SigPubKey;
;; validator#53 public_key:SigPubKey weight:uint64 = ValidatorDescr;
;; validator_addr#73 public_key:SigPubKey weight:uint64 adnl_addr:bits256 = ValidatorDescr;
throw_unless(41, (cs~load_uint(8) & ~ 0x20) == 0x53);
throw_unless(41, cs~load_uint(32) == 0x8e81278a);
return (cs~load_uint(256), cs~load_uint(64));
}
slice create_new_entry(cs) inline {
return begin_cell().store_int(false, 1).store_uint(0, 64).store_uint(0, 256).store_slice(cs).end_cell().begin_parse();
}
(cell, int, int, slice) unpack_suggestion(slice cs) inline {
return (cs~load_dict(), cs~load_uint(64), cs~load_uint(256), cs);
}
builder pack_suggestion(cell voters, int sum_weight, int vset_id, slice body) inline {
return begin_cell().store_dict(voters).store_uint(sum_weight, 64).store_uint(vset_id, 256).store_slice(body);
}
cell register_vote(vote_dict, action, cs, idx, weight) {
int hash = 0;
var entry = null();
if (action & 1) {
hash = slice_hash(cs);
(entry, var found?) = vote_dict.udict_get?(256, hash);
ifnot (found?) {
entry = create_new_entry(cs);
}
} else {
hash = cs.preload_uint(256);
(entry, var found?) = vote_dict.udict_get?(256, hash);
throw_unless(42, found?);
}
return vote_dict;
}
() recv_external(slice in_msg) impure {
@ -126,16 +195,28 @@ _ perform_action(cfg_dict, public_key, action, cs) {
int msg_seqno = cs~load_uint(32);
var valid_until = cs~load_uint(32);
throw_if(35, valid_until < now());
var cs2 = begin_parse(get_data());
var cfg_dict = cs2~load_ref();
var stored_seqno = cs2~load_uint(32);
var public_key = cs2~load_uint(256);
cs2.end_parse();
var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
throw_unless(33, msg_seqno == stored_seqno);
ifnot ((action - 0x566f7465) & -2) {
var idx = cs~load_uint(16);
var vdescr = get_validator_descr(idx);
var (val_pubkey, weight) = unpack_validator_descr(vdescr);
throw_unless(34, check_signature(slice_hash(in_msg), signature, val_pubkey));
accept_message();
stored_seqno += 1;
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
commit();
vote_dict = register_vote(vote_dict, action, cs, idx, weight);
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
return ();
}
throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key));
accept_message();
stored_seqno += 1;
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
commit();
(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());
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
}
() run_ticktock(int is_tock) impure {

View File

@ -408,7 +408,7 @@ _ compute_total_stake(l, n, m_stake) {
return tot_stake;
}
(cell, cell, cell, int, int) try_elect(credits, members, min_stake, max_stake, min_total_stake, max_stake_factor) {
(cell, cell, int, cell, int, int) try_elect(credits, members, min_stake, max_stake, min_total_stake, max_stake_factor) {
var cs = 16.config_param().begin_parse();
var (max_validators, _, min_validators) = (cs~load_uint(16), cs~load_uint(16), cs~load_uint(16));
cs.end_parse();
@ -435,7 +435,7 @@ _ compute_total_stake(l, n, m_stake) {
} until (~ f);
n = min(n, max_validators);
if (n < min_validators) {
return (credits, new_dict(), new_dict(), 0, 0);
return (credits, new_dict(), 0, new_dict(), 0, 0);
}
var l = nil;
do {
@ -464,7 +464,7 @@ _ compute_total_stake(l, n, m_stake) {
}
} until (i >= n);
if ((m == 0) | (best_stake < min_total_stake)) {
return (credits, new_dict(), new_dict(), 0, 0);
return (credits, new_dict(), 0, new_dict(), 0, 0);
}
;; we have to select first m validators from list l
l1 = touch(l);
@ -476,6 +476,7 @@ _ compute_total_stake(l, n, m_stake) {
;; create both the new validator set and the refund set
int i = 0;
var tot_stake = 0;
var tot_weight = 0;
var vset = new_dict();
var frozen = new_dict();
do {
@ -492,6 +493,7 @@ _ compute_total_stake(l, n, m_stake) {
;; validator_addr#73 public_key:SigPubKey weight:uint64 adnl_addr:bits256 = ValidatorDescr;
var weight = (true_stake << 60) / best_stake;
tot_stake += true_stake;
tot_weight += weight;
var vinfo = begin_cell()
.store_uint(adnl_addr ? 0x73 : 0x53, 8) ;; validator_addr#73 or validator#53
.store_uint(0x8e81278a, 32) ;; ed25519_pubkey#8e81278a
@ -514,7 +516,7 @@ _ compute_total_stake(l, n, m_stake) {
i += 1;
} until (l.null?());
throw_unless(49, tot_stake == best_stake);
return (credits, vset, frozen, tot_stake, m);
return (credits, vset, tot_weight, frozen, tot_stake, m);
}
int conduct_elections(ds, elect, credits) impure {
@ -545,7 +547,7 @@ int conduct_elections(ds, elect, credits) impure {
;; elections finished
return false;
}
(credits, var vdict, var frozen, var total_stakes, var cnt) = try_elect(credits, members, min_stake, max_stake, min_total_stake, max_stake_factor);
(credits, var vdict, var total_weight, var frozen, var total_stakes, var cnt) = try_elect(credits, members, min_stake, max_stake, min_total_stake, max_stake_factor);
;; pack elections; if cnt==0, set failed=true, finished=false.
failed = (cnt == 0);
finished = ~ failed;
@ -561,12 +563,13 @@ int conduct_elections(ds, elect, credits) impure {
var start = max(now() + elect_end_before - 60, elect_at);
var main_validators = config_param(16).begin_parse().skip_bits(16).preload_uint(16);
var vset = begin_cell()
.store_uint(0x11, 8) ;; validators#11
.store_uint(0x12, 8) ;; validators_ext#12
.store_uint(start, 32) ;; utime_since:uint32
.store_uint(start + elect_for, 32) ;; utime_until:uint32
.store_uint(cnt, 16) ;; total:(## 16)
.store_uint(min(cnt, main_validators), 16) ;; main:(## 16)
.store_slice(vdict.begin_parse()) ;; list:(Hashmap 16 ValidatorDescr)
.store_uint(min(cnt, main_validators), 16) ;; main:(## 16)
.store_uint(total_weight, 64) ;; total_weight:uint64
.store_dict(vdict) ;; list:(HashmapE 16 ValidatorDescr)
.end_cell();
var config_addr = config_param(0).begin_parse().preload_uint(256);
send_validator_set_to_config(config_addr, vset, elect_at);

View File

@ -225,6 +225,22 @@ Masterchain swap
"config-master" +suffix +".addr" save-address-verbose
// Other data
/*
*
* Initial wallets (test)
*
*/
// pubkey amount `create-wallet1` or pubkey amount `create-wallet2`
PK'PuZPPXK5Rff9SvtoS7Y9lUuEixvy-J6aishYFj3Qn6P0pJMb GR$100000000 create-wallet1
PK'PuYiB1zAWzr4p8j6I681+sGUrRGcn6Ylf7vXl0xaUl/w6Xfg GR$1700000000 create-wallet0
/*
*
* Create state
*
*/
create_state
cr cr ."new state is:" cr dup <s csr. cr
dup 31 boc+>B dup Bx. cr

View File

@ -0,0 +1,63 @@
#!/usr/bin/fift -s
"TonUtil.fif" include
"Asm.fif" include
{ ."usage: " @' $0 type ." <workchain-id> <wallet-id> [<filename-base>]" cr
."Creates a new advanced wallet with unique 32-bit identifier <wallet-id> in specified workchain, with private key saved to or loaded from <filename-base>.pk" cr
."('new-wallet.pk' by default)" cr 1 halt
} : usage
$# 2- -2 and ' usage if
$1 parse-workchain-id =: wc // set workchain id from command line argument
$2 parse-int =: subwallet-id
def? $3 { @' $3 } { "new-wallet" } cond constant file-base
."Creating new advanced v3 wallet in workchain " wc . cr
."with unique wallet id " subwallet-id . cr
// Create new advanced wallet; code adapted from `auto/wallet3-code.fif`
<{ 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 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
NOW s1 s3 XCHG LEQ 35 THROWIF // signature in_msg subwallet_id cs msg_seqno
c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key
s3 s2 XCPU EQUAL 33 THROWIFNOT // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet
s4 s4 XCPU EQUAL 34 THROWIFNOT // signature in_msg stored_subwallet cs public_key stored_seqno
s0 s4 XCHG HASHSU // signature stored_seqno stored_subwallet cs public_key msg_hash
s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs msg_hash signature public_key
CHKSIGNU 35 THROWIFNOT // public_key stored_seqno stored_subwallet cs
ACCEPT
WHILE:<{
DUP SREFS // public_key stored_seqno stored_subwallet cs _51
}>DO<{ // public_key stored_seqno stored_subwallet cs
8 LDU LDREF s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode
SENDRAWMSG
}> // public_key stored_seqno stored_subwallet cs
ENDS SWAP INC // public_key stored_subwallet seqno'
NEWC 32 STU 32 STU 256 STU ENDC c4 POP
}>c // >libref
// code
<b 0 32 u, subwallet-id 32 u,
file-base +".pk" load-generate-keypair
constant wallet_pk
B,
b> // data
null // no libraries
<b b{0011} s, 3 roll ref, rot ref, swap dict, b> // create StateInit
dup ."StateInit: " <s csr. cr
dup hashu wc swap 2dup 2constant wallet_addr
."new wallet address = " 2dup .addr cr
2dup file-base +".addr" save-address-verbose
."Non-bounceable address (for init): " 2dup 7 .Addr cr
."Bounceable address (for later access): " 6 .Addr cr
<b subwallet-id 32 u, -1 32 i, 0 32 u, b>
dup ."signing message: " <s csr. cr
dup hashu wallet_pk ed25519_sign_uint rot
<b b{1000100} s, wallet_addr addr, b{000010} s, swap <s s, b{0} s, swap B, swap <s s, b>
dup ."External message for initialization is " <s csr. cr
2 boc+>B dup Bx. cr
file-base +"-query.boc" tuck B>file
."(Saved wallet creating query to file " type .")" cr

View File

@ -16,6 +16,7 @@ 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";
forall X -> X null() asm "PUSHNULL";
int now() asm "NOW";
slice my_address() asm "MYADDR";
@ -54,8 +55,10 @@ cell preload_ref(slice s) asm "PLDREF";
;; slice preload_bits(slice s, int len) asm "PLDSLICEX";
(slice, int) load_grams(slice s) asm( -> 1 0) "LDGRAMS";
slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
(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 skip_last_bits(slice s, int len) asm "SDSKIPLAST";
(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";

View File

@ -0,0 +1,50 @@
#!/usr/bin/fift -s
"TonUtil.fif" include
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <subwallet_id> <seqno> <amount> [-B <body-boc>] [<savefile>]" cr
."Creates a request to advanced wallet created by new-wallet-v3.fif, with private key loaded from file <filename-base>.pk "
."and address from <filename-base>.addr, and saves it into <savefile>.boc ('wallet-query.boc' by default)" cr 1 halt
} : usage
def? $7 { @' $6 "-B" $= { @' $7 =: body-boc-file [forget] $7 def? $8 { @' $8 =: $6 [forget] $8 } { [forget] $6 } cond
@' $# 2- =: $# } if } if
$# dup 5 < swap 6 > or ' usage if
true constant bounce
$1 =: file-base
$2 bounce parse-load-address =: bounce 2=: dest_addr
$3 parse-int =: subwallet_id
$4 parse-int =: seqno
$5 $>GR =: amount
def? $6 { @' $6 } { "wallet-query" } cond constant savefile
3 constant send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors
60 constant timeout // external message expires in 60 seconds
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 } { <b 0 32 u, "TESTv3" $, b> } cond
constant body-cell
."Transferring " amount .GR ."to account "
dest_addr 2dup bounce 7 + .Addr ." = " .addr
."subwallet_id=0x" subwallet_id x.
."seqno=0x" seqno x. ."bounce=" bounce . cr
."Body of transfer message is " body-cell <s csr. cr
// create a message
<b b{01} s, bounce 1 i, b{000100} s, dest_addr addr, amount Gram, 0 9 64 32 + + 1+ u,
body-cell <s 2dup s-fits? not rot over 1 i, -rot { drop body-cell ref, } { s, } cond
b>
<b subwallet_id 32 u, now timeout + 32 u, seqno 32 u, send-mode 8 u, swap ref, b>
dup ."signing message: " <s csr. cr
dup hashu wallet_pk ed25519_sign_uint
<b b{1000100} s, wallet_addr addr, 0 Gram, b{00} s,
swap B, swap <s s, b>
dup ."resulting external message: " <s csr. cr
2 boc+>B dup Bx. cr
savefile +".boc" tuck B>file
."Query expires in " timeout . ."seconds" cr
."(Saved to file " type .")" cr

View File

@ -0,0 +1,35 @@
;; Simple wallet smart contract
() recv_internal(slice in_msg) impure {
;; do nothing for internal messages
}
() recv_external(slice in_msg) impure {
var signature = in_msg~load_bits(512);
var cs = in_msg;
var (subwallet_id, valid_until, msg_seqno) = (cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
throw_if(35, valid_until <= now());
var ds = get_data().begin_parse();
var (stored_seqno, stored_subwallet, public_key) = (ds~load_uint(32), ds~load_uint(32), ds~load_uint(256));
ds.end_parse();
throw_unless(33, msg_seqno == stored_seqno);
throw_unless(34, subwallet_id == stored_subwallet);
throw_unless(35, check_signature(slice_hash(in_msg), signature, public_key));
accept_message();
cs~touch();
while (cs.slice_refs()) {
var mode = cs~load_uint(8);
send_raw_message(cs~load_ref(), mode);
}
set_data(begin_cell()
.store_uint(stored_seqno + 1, 32)
.store_uint(stored_subwallet, 32)
.store_uint(public_key, 256)
.end_cell());
}
;; Get methods
int seqno() method_id {
return get_data().begin_parse().preload_uint(32);
}

View File

@ -0,0 +1,130 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "WalletV3.h"
#include "GenericAccount.h"
#include "vm/boc.h"
#include "vm/cells/CellString.h"
#include "td/utils/base64.h"
#include <limits>
namespace ton {
td::Ref<vm::Cell> WalletV3::get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept {
auto code = get_init_code();
auto data = get_init_data(public_key, wallet_id);
return GenericAccount::get_init_state(std::move(code), std::move(data));
}
td::Ref<vm::Cell> WalletV3::get_init_message(const td::Ed25519::PrivateKey& private_key,
td::uint32 wallet_id) noexcept {
td::uint32 seqno = 0;
td::uint32 valid_until = std::numeric_limits<td::uint32>::max();
auto signature = private_key
.sign(vm::CellBuilder()
.store_long(wallet_id, 32)
.store_long(valid_until, 32)
.store_long(seqno, 32)
.finalize()
->get_hash()
.as_slice())
.move_as_ok();
return vm::CellBuilder()
.store_bytes(signature)
.store_long(wallet_id, 32)
.store_long(valid_until, 32)
.store_long(seqno, 32)
.finalize();
}
td::Ref<vm::Cell> WalletV3::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id,
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(wallet_id, 32)
.store_long(valid_until, 32)
.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<vm::Cell> WalletV3::get_init_code() noexcept {
static auto res = [] {
auto serialized_code = td::base64_decode(
"te6ccgEBAQEAYgAAwP8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x/TH/gjE7vyY+1E0NMf0x/T/"
"9FRMrryoVFEuvKiBPkBVBBV+RDyo/gAkyDXSpbTB9QC+wDo0QGkyMsfyx/L/8ntVA==")
.move_as_ok();
return vm::std_boc_deserialize(serialized_code).move_as_ok();
}();
return res;
}
vm::CellHash WalletV3::get_init_code_hash() noexcept {
return get_init_code()->get_hash();
}
td::Ref<vm::Cell> WalletV3::get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept {
return vm::CellBuilder()
.store_long(0, 32)
.store_long(wallet_id, 32)
.store_bytes(public_key.as_octet_string())
.finalize();
}
td::Result<td::uint32> WalletV3::get_seqno() const {
return TRY_VM(get_seqno_or_throw());
}
td::Result<td::uint32> WalletV3::get_seqno_or_throw() const {
if (state_.data.is_null()) {
return 0;
}
//FIXME use get method
return static_cast<td::uint32>(vm::load_cell_slice(state_.data).fetch_ulong(32));
}
td::Result<td::uint32> WalletV3::get_wallet_id() const {
return TRY_VM(get_wallet_id_or_throw());
}
td::Result<td::uint32> WalletV3::get_wallet_id_or_throw() const {
if (state_.data.is_null()) {
return 0;
}
//FIXME use get method
auto cs = vm::load_cell_slice(state_.data);
cs.skip_first(32);
return static_cast<td::uint32>(cs.fetch_ulong(32));
}
} // namespace ton

View File

@ -18,23 +18,33 @@
*/
#pragma once
#include "smc-envelope/SmartContract.h"
#include "vm/cells.h"
#include "Ed25519.h"
#include "block/block.h"
#include "CellString.h"
#include "vm/cells/CellString.h"
namespace tonlib {
class TestWallet {
namespace ton {
class WalletV3 : ton::SmartContract {
public:
explicit WalletV3(State state) : ton::SmartContract(std::move(state)) {
}
static constexpr unsigned max_message_size = vm::CellString::max_bytes;
static td::Ref<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key) noexcept;
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept;
static td::Ref<vm::Cell> 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<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id) noexcept;
static td::Ref<vm::Cell> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id,
td::uint32 seqno, td::uint32 valid_until, td::int64 gramms,
td::Slice message, const block::StdAddress& dest_address) noexcept;
static td::Ref<vm::Cell> get_init_code() noexcept;
static vm::CellHash get_init_code_hash() noexcept;
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key) noexcept;
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
td::Result<td::uint32> get_seqno() const;
td::Result<td::uint32> get_wallet_id() const;
private:
td::Result<td::uint32> get_seqno_or_throw() const;
td::Result<td::uint32> get_wallet_id_or_throw() const;
};
} // namespace tonlib
} // namespace ton

View File

@ -208,7 +208,7 @@ TEST(Crypto, almost_zero) {
td::SecureString sig(64);
td::SecureString msg(1);
pub.as_mutable_slice()[31] = (char)128;
pub.as_mutable_slice().ubegin()[31] = static_cast<unsigned 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()) {

View File

@ -34,6 +34,7 @@
#include "smc-envelope/TestGiver.h"
#include "smc-envelope/TestWallet.h"
#include "smc-envelope/Wallet.h"
#include "smc-envelope/WalletV3.h"
#include "td/utils/base64.h"
#include "td/utils/crypto.h"
@ -114,6 +115,33 @@ SETCP0 DUP IFNOTRET // return if recv_internal
)ABCD";
return fift::compile_asm(code).move_as_ok();
}
td::Ref<vm::Cell> get_wallet_v3_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 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
NOW s1 s3 XCHG LEQ 35 THROWIF // signature in_msg subwallet_id cs msg_seqno
c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key
s3 s2 XCPU EQUAL 33 THROWIFNOT // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet
s4 s4 XCPU EQUAL 34 THROWIFNOT // signature in_msg stored_subwallet cs public_key stored_seqno
s0 s4 XCHG HASHSU // signature stored_seqno stored_subwallet cs public_key msg_hash
s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs msg_hash signature public_key
CHKSIGNU 35 THROWIFNOT // public_key stored_seqno stored_subwallet cs
ACCEPT
WHILE:<{
DUP SREFS // public_key stored_seqno stored_subwallet cs _51
}>DO<{ // public_key stored_seqno stored_subwallet cs
8 LDU LDREF s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode
SENDRAWMSG
}> // public_key stored_seqno stored_subwallet cs
ENDS SWAP INC // public_key stored_subwallet seqno'
NEWC 32 STU 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());
@ -209,6 +237,55 @@ TEST(Tonlib, Wallet) {
CHECK(vm::std_boc_deserialize(wallet_query).move_as_ok()->get_hash() == gift_message->get_hash());
}
TEST(Tonlib, WalletV3) {
LOG(ERROR) << td::base64_encode(std_boc_serialize(get_wallet_v3_source()).move_as_ok());
CHECK(get_wallet_v3_source()->get_hash() == ton::WalletV3::get_init_code()->get_hash());
auto fift_output = fift::mem_run_fift(load_source("smartcont/new-wallet-v3.fif"), {"aba", "0", "239"}).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::WalletV3::get_init_state(pub_key, 239);
auto init_message = ton::WalletV3::get_init_message(priv_key, 239);
auto address = ton::GenericAccount::get_address(0, init_state);
CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32));
td::Ref<vm::Cell> 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-v3.fif")).ensure();
class ZeroOsTime : public fift::OsTime {
public:
td::uint32 now() override {
return 0;
}
};
fift_output.source_lookup.set_os_time(std::make_unique<ZeroOsTime>());
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", "239", "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::WalletV3::make_a_gift_message(priv_key, 239, 123, 60, 321000000000ll, "TESTv3", 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();

View File

@ -288,7 +288,7 @@ std::string wycheproof_ed25519() {
"sig" : "7c38e026f29e14aabd059a0f2db8b0cd783040609a8be684db12f82a27774ab07a9155711ecfaf7f99f277bad0c6ae7e39d4eef676573336a5c51eb6f946b30d2020",
"result" : "invalid",
"flags" : []
},
},)abcd" R"abcd(
{
"tcId" : 34,
"comment" : "include pk in signature",
@ -570,7 +570,7 @@ std::string wycheproof_ed25519() {
"flags" : [
"SignatureMalleability"
]
},
},)abcd" R"abcd(
{
"tcId" : 68,
"comment" : "checking malleability ",
@ -858,7 +858,7 @@ std::string wycheproof_ed25519() {
"flags" : []
}
]
},
},)abcd" R"abcd(
{
"key" : {
"curve" : "edwards25519",

View File

@ -1021,9 +1021,9 @@ void CppTypeCode::generate_tag_pfx_selector(std::ostream& os, std::string nl, co
}
os << "};" << nl << "return ctab[1 + ";
if (simple) {
os << "(long)cs.prefetch_ulong(" << d << ")];";
os << "(long long)cs.prefetch_ulong(" << d << ")];";
} else {
os << "(long)cs.bselect" << (d >= min_size ? "(" : "_ext(") << d << ", " << HexConstWriter{mask} << ")];";
os << "(long long)cs.bselect" << (d >= min_size ? "(" : "_ext(") << d << ", " << HexConstWriter{mask} << ")];";
}
}
@ -1153,7 +1153,7 @@ void CppTypeCode::generate_get_tag_body(std::ostream& os, std::string nl) {
os << ")) {";
for (int i = 0; i < l; i++) {
if (A[i] != 0) {
if ((long)A[i] > 0) {
if ((long long)A[i] > 0) {
int j;
for (j = 0; j < i; j++) {
if (A[j] == A[i]) {
@ -1165,7 +1165,7 @@ void CppTypeCode::generate_get_tag_body(std::ostream& os, std::string nl) {
}
}
os << nl << "case " << i << ":";
if ((long)A[i] > 0) {
if ((long long)A[i] > 0) {
int j;
for (j = i + 1; j < l; j++) {
if (A[j] == A[i]) {

View File

@ -687,7 +687,7 @@ unsigned long long BinTrie::build_submap(int depth, unsigned long long A[]) cons
} else {
std::memset(A + n, 0, n * 8);
}
if (A[n] != A[n - 1] || (long)A[n] < 0) {
if (A[n] != A[n - 1] || (long long)A[n] < 0) {
r2 |= 1;
} else {
r2 &= ~1;

View File

@ -33,6 +33,8 @@
#include "vm/cellslice.h"
#include "vm/excno.hpp"
#include "td/utils/Span.h"
namespace td {
extern template class td::Cnt<std::string>;
extern template class td::Ref<td::Cnt<std::string>>;
@ -156,7 +158,7 @@ class StackEntry {
private:
template <typename T, Type tag>
Ref<T> dynamic_as() const & {
Ref<T> dynamic_as() const& {
return tp == tag ? static_cast<Ref<T>>(ref) : td::Ref<T>{};
}
template <typename T, Type tag>
@ -168,7 +170,7 @@ class StackEntry {
return tp == tag ? static_cast<Ref<T>>(std::move(ref)) : td::Ref<T>{};
}
template <typename T, Type tag>
Ref<T> as() const & {
Ref<T> as() const& {
return tp == tag ? Ref<T>{td::static_cast_ref(), ref} : td::Ref<T>{};
}
template <typename T, Type tag>
@ -189,31 +191,31 @@ class StackEntry {
return ref;
}
}
td::RefInt256 as_int() const & {
td::RefInt256 as_int() const& {
return as<td::CntInt256, t_int>();
}
td::RefInt256 as_int() && {
return move_as<td::CntInt256, t_int>();
}
Ref<Cell> as_cell() const & {
Ref<Cell> as_cell() const& {
return as<Cell, t_cell>();
}
Ref<Cell> as_cell() && {
return move_as<Cell, t_cell>();
}
Ref<CellBuilder> as_builder() const & {
Ref<CellBuilder> as_builder() const& {
return as<CellBuilder, t_builder>();
}
Ref<CellBuilder> as_builder() && {
return move_as<CellBuilder, t_builder>();
}
Ref<CellSlice> as_slice() const & {
Ref<CellSlice> as_slice() const& {
return as<CellSlice, t_slice>();
}
Ref<CellSlice> as_slice() && {
return move_as<CellSlice, t_slice>();
}
Ref<Continuation> as_cont() const &;
Ref<Continuation> as_cont() const&;
Ref<Continuation> as_cont() &&;
Ref<Cnt<std::string>> as_string_ref() const {
return as<Cnt<std::string>, t_string>();
@ -228,16 +230,16 @@ class StackEntry {
std::string as_bytes() const {
return tp == t_bytes ? *as_bytes_ref() : "";
}
Ref<Box> as_box() const &;
Ref<Box> as_box() const&;
Ref<Box> as_box() &&;
Ref<Tuple> as_tuple() const &;
Ref<Tuple> as_tuple() const&;
Ref<Tuple> as_tuple() &&;
Ref<Tuple> as_tuple_range(unsigned max_len = 255, unsigned min_len = 0) const &;
Ref<Tuple> as_tuple_range(unsigned max_len = 255, unsigned min_len = 0) const&;
Ref<Tuple> as_tuple_range(unsigned max_len = 255, unsigned min_len = 0) &&;
Ref<Atom> as_atom() const &;
Ref<Atom> as_atom() const&;
Ref<Atom> as_atom() &&;
template <class T>
Ref<T> as_object() const & {
Ref<T> as_object() const& {
return dynamic_as<T, t_object>();
}
template <class T>
@ -361,6 +363,9 @@ class Stack : public td::CntObject {
std::vector<StackEntry>::const_iterator from_top(int offs) const {
return stack.cend() - offs;
}
td::Span<StackEntry> as_span() const {
return stack;
}
bool at_least(int req) const {
return depth() >= req;
}

View File

@ -1145,6 +1145,273 @@ void run_queue_bench(int n, int m) {
#endif
}
struct Sem {
public:
void post() {
if (++cnt_ == 0) {
{
std::unique_lock<std::mutex> lk(mutex_);
}
cnd_.notify_one();
}
}
void wait(int cnt = 1) {
auto was = cnt_.fetch_sub(cnt);
if (was >= cnt) {
return;
}
std::unique_lock<std::mutex> lk(mutex_);
cnd_.wait(lk, [&] { return cnt_ >= 0; });
}
private:
std::mutex mutex_;
std::condition_variable cnd_;
std::atomic<int> cnt_{0};
};
class ChainedSpawn : public td::Benchmark {
public:
ChainedSpawn(bool use_io) : use_io_(use_io) {
}
std::string get_description() const {
return PSTRING() << "Chained create_actor use_io(" << use_io_ << ")";
}
void run(int n) {
class Task : public td::actor::Actor {
public:
Task(int n, Sem *sem) : n_(n), sem_(sem) {
}
void start_up() override {
if (n_ == 0) {
sem_->post();
} else {
td::actor::create_actor<Task>("Task", n_ - 1, sem_).release();
}
stop();
};
private:
int n_;
Sem *sem_{nullptr};
};
td::actor::Scheduler scheduler{{8}};
auto sch = td::thread([&] { scheduler.run(); });
Sem sem;
scheduler.run_in_context_external([&] {
for (int i = 0; i < n; i++) {
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), 1000, &sem)
.release();
sem.wait();
}
td::actor::SchedulerContext::get()->stop();
});
sch.join();
}
private:
bool use_io_{false};
};
class ChainedSpawnInplace : public td::Benchmark {
public:
ChainedSpawnInplace(bool use_io) : use_io_(use_io) {
}
std::string get_description() const {
return PSTRING() << "Chained send_signal(self) use_io(" << use_io_ << ")";
}
void run(int n) {
class Task : public td::actor::Actor {
public:
Task(int n, Sem *sem) : n_(n), sem_(sem) {
}
void loop() override {
if (n_ == 0) {
sem_->post();
stop();
} else {
n_--;
send_signals(actor_id(this), td::actor::ActorSignals::wakeup());
}
};
private:
int n_;
Sem *sem_;
};
td::actor::Scheduler scheduler{{8}};
auto sch = td::thread([&] { scheduler.run(); });
Sem sem;
scheduler.run_in_context_external([&] {
for (int i = 0; i < n; i++) {
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), 1000, &sem)
.release();
sem.wait();
}
td::actor::SchedulerContext::get()->stop();
});
sch.join();
}
private:
bool use_io_{false};
};
class PingPong : public td::Benchmark {
public:
PingPong(bool use_io) : use_io_(use_io) {
}
std::string get_description() const {
return PSTRING() << "PingPong use_io(" << use_io_ << ")";
}
void run(int n) {
if (n < 3) {
n = 3;
}
class Task : public td::actor::Actor {
public:
explicit Task(Sem *sem) : sem_(sem) {
}
void set_peer(td::actor::ActorId<Task> peer) {
peer_ = peer;
}
void ping(int n) {
if (n < 0) {
sem_->post();
stop();
}
send_closure(peer_, &Task::ping, n - 1);
}
private:
td::actor::ActorId<Task> peer_;
Sem *sem_;
};
td::actor::Scheduler scheduler{{8}};
auto sch = td::thread([&] { scheduler.run(); });
Sem sem;
scheduler.run_in_context_external([&] {
for (int i = 0; i < n; i++) {
auto a = td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem)
.release();
auto b = td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem)
.release();
send_closure(a, &Task::set_peer, b);
send_closure(b, &Task::set_peer, a);
send_closure(a, &Task::ping, 1000);
sem.wait(2);
}
td::actor::SchedulerContext::get()->stop();
});
sch.join();
}
private:
bool use_io_{false};
};
class SpawnMany : public td::Benchmark {
public:
SpawnMany(bool use_io) : use_io_(use_io) {
}
std::string get_description() const {
return PSTRING() << "Spawn many use_io(" << use_io_ << ")";
}
void run(int n) {
class Task : public td::actor::Actor {
public:
Task(Sem *sem) : sem_(sem) {
}
void start_up() override {
sem_->post();
stop();
};
private:
Sem *sem_;
};
td::actor::Scheduler scheduler{{8}};
Sem sem;
auto sch = td::thread([&] { scheduler.run(); });
scheduler.run_in_context_external([&] {
for (int i = 0; i < n; i++) {
int spawn_cnt = 10000;
for (int j = 0; j < spawn_cnt; j++) {
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem).release();
}
sem.wait(spawn_cnt);
}
td::actor::SchedulerContext::get()->stop();
});
sch.join();
}
private:
bool use_io_{false};
};
class YieldMany : public td::Benchmark {
public:
YieldMany(bool use_io) : use_io_(use_io) {
}
std::string get_description() const {
return PSTRING() << "Yield many use_io(" << use_io_ << ")";
}
void run(int n) {
int num_yield = 1000;
unsigned tasks_per_cpu = 50;
unsigned cpu_n = td::thread::hardware_concurrency();
class Task : public td::actor::Actor {
public:
explicit Task(int n, Sem *sem) : n_(n), sem_(sem) {
}
void loop() override {
if (n_ == 0) {
sem_->post();
stop();
} else {
n_--;
yield();
}
};
private:
int n_;
Sem *sem_;
};
td::actor::Scheduler scheduler{{cpu_n}};
auto sch = td::thread([&] { scheduler.run(); });
unsigned tasks = tasks_per_cpu * cpu_n;
Sem sem;
scheduler.run_in_context_external([&] {
for (int i = 0; i < n; i++) {
for (unsigned j = 0; j < tasks; j++) {
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), num_yield, &sem)
.release();
}
sem.wait(tasks);
}
});
scheduler.run_in_context_external([&] { td::actor::SchedulerContext::get()->stop(); });
sch.join();
}
private:
bool use_io_{false};
};
int main(int argc, char **argv) {
if (argc > 1) {
if (argv[1][0] == 'a') {
@ -1159,6 +1426,18 @@ int main(int argc, char **argv) {
return 0;
}
bench(YieldMany(false));
bench(YieldMany(true));
bench(SpawnMany(false));
bench(SpawnMany(true));
bench(PingPong(false));
bench(PingPong(true));
bench(ChainedSpawnInplace(false));
bench(ChainedSpawnInplace(true));
bench(ChainedSpawn(false));
bench(ChainedSpawn(true));
return 0;
bench(ActorDummyQuery());
bench(ActorExecutorBenchmark());
bench(ActorSignalQuery());

View File

@ -281,6 +281,8 @@ class Promise {
promise.do_wrap(std::move(res), std::move(func));
};
}
template <class... ArgsT>
auto send_closure(ArgsT &&... args);
private:
std::unique_ptr<PromiseInterface<T>> promise_;

View File

@ -162,4 +162,29 @@ void send_signals_later(ActorIdT &&actor_id, ActorSignals signals) {
detail::send_signals_later(id.as_actor_ref(), signals);
}
} // namespace actor
class SendClosure {
public:
template <class... ArgsT>
void operator()(ArgsT &&... args) const {
td::actor::send_closure(std::forward<ArgsT>(args)...);
}
};
template <class T>
template <class... ArgsT>
auto Promise<T>::send_closure(ArgsT &&... args) {
return [promise = std::move(*this), t = std::make_tuple(std::forward<ArgsT>(args)...)](auto &&r_res) mutable {
TRY_RESULT_PROMISE(promise, res, std::move(r_res));
td::call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::move(res), std::move(promise))));
};
}
template <class... ArgsT>
auto promise_send_closure(ArgsT &&... args) {
return [t = std::make_tuple(std::forward<ArgsT>(args)...)](auto &&res) mutable {
td::call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::move(res))));
};
}
} // namespace td

View File

@ -193,7 +193,7 @@ class JsonObjectScope;
class JsonBuilder {
public:
explicit JsonBuilder(StringBuilder &&sb, int32 offset = -1) : sb_(std::move(sb)), offset_(offset) {
explicit JsonBuilder(StringBuilder &&sb = {}, int32 offset = -1) : sb_(std::move(sb)), offset_(offset) {
}
StringBuilder &string_builder() {
return sb_;

View File

@ -31,6 +31,8 @@ namespace td {
class StringBuilder {
public:
explicit StringBuilder(MutableSlice slice, bool use_buffer = false);
StringBuilder() : StringBuilder({}, true) {
}
void clear() {
current_ptr_ = begin_ptr_;

View File

@ -128,7 +128,7 @@ auto invoke(F &&f,
}
template <class F, class... Args, std::size_t... S>
auto call_tuple_impl(F &func, std::tuple<Args...> &&tuple, IntSeq<S...>) {
auto call_tuple_impl(F &&func, std::tuple<Args...> &&tuple, IntSeq<S...>) {
return func(std::forward<Args>(std::get<S>(tuple))...);
}
@ -163,7 +163,7 @@ class LogicAnd {
};
template <class F, class... Args>
auto call_tuple(F &func, std::tuple<Args...> &&tuple) {
auto call_tuple(F &&func, std::tuple<Args...> &&tuple) {
return detail::call_tuple_impl(func, std::move(tuple), detail::IntRange<sizeof...(Args)>());
}

View File

@ -128,7 +128,7 @@ class JavadocTlDocumentationGenerator extends TlDocumentationGenerator
$this->addDocumentation('public class TdApi {', <<<EOT
$nullable_type_import/**
* This class contains as static nested classes all other TDLib interface
* This class contains as static nested classes all other tonlib interface
* type-classes and function-classes.
* <p>
* It has no inner classes, functions or public members.
@ -138,7 +138,7 @@ EOT
$this->addDocumentation(' public abstract static class Object {', <<<EOT
/**
* This class is a base class for all TDLib interface classes.
* This class is a base class for all tonlib interface classes.
*/
EOT
);
@ -159,7 +159,7 @@ EOT
$this->addDocumentation(' public abstract static class Function extends Object {', <<<EOT
/**
* This class is a base class for all TDLib interface function-classes.
* This class is a base class for all tonlib interface function-classes.
*/
EOT
);

View File

@ -202,21 +202,21 @@ void fees::store(td::TlStorerToString &s, const char *field_name) const {
}
}
inputKey::inputKey()
inputKeyRegular::inputKeyRegular()
: key_()
, local_password_()
{}
inputKey::inputKey(object_ptr<key> &&key_, td::SecureString &&local_password_)
inputKeyRegular::inputKeyRegular(object_ptr<key> &&key_, td::SecureString &&local_password_)
: key_(std::move(key_))
, local_password_(std::move(local_password_))
{}
const std::int32_t inputKey::ID;
const std::int32_t inputKeyRegular::ID;
void inputKey::store(td::TlStorerToString &s, const char *field_name) const {
void inputKeyRegular::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "inputKey");
s.store_class_begin(field_name, "inputKeyRegular");
if (key_ == nullptr) { s.store_field("key", "null"); } else { key_->store(s, "key"); }
s.store_bytes_field("local_password", local_password_);
s.store_class_end();
@ -577,6 +577,24 @@ void generic_accountStateWallet::store(td::TlStorerToString &s, const char *fiel
}
}
generic_accountStateWalletV3::generic_accountStateWalletV3()
: account_state_()
{}
generic_accountStateWalletV3::generic_accountStateWalletV3(object_ptr<wallet_v3_accountState> &&account_state_)
: account_state_(std::move(account_state_))
{}
const std::int32_t generic_accountStateWalletV3::ID;
void generic_accountStateWalletV3::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "generic_accountStateWalletV3");
if (account_state_ == nullptr) { s.store_field("account_state", "null"); } else { account_state_->store(s, "account_state"); }
s.store_class_end();
}
}
generic_accountStateTestGiver::generic_accountStateTestGiver()
: account_state_()
{}
@ -658,6 +676,24 @@ void liteServer_info::store(td::TlStorerToString &s, const char *field_name) con
}
}
options_configInfo::options_configInfo()
: default_wallet_id_()
{}
options_configInfo::options_configInfo(std::int64_t default_wallet_id_)
: default_wallet_id_(default_wallet_id_)
{}
const std::int32_t options_configInfo::ID;
void options_configInfo::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "options_configInfo");
s.store_field("default_wallet_id", default_wallet_id_);
s.store_class_end();
}
}
query_fees::query_fees()
: source_fees_()
, destination_fees_()
@ -856,6 +892,84 @@ void raw_transactions::store(td::TlStorerToString &s, const char *field_name) co
}
}
smc_info::smc_info()
: id_()
{}
smc_info::smc_info(std::int64_t id_)
: id_(id_)
{}
const std::int32_t smc_info::ID;
void smc_info::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_info");
s.store_field("id", id_);
s.store_class_end();
}
}
smc_methodIdNumber::smc_methodIdNumber()
: number_()
{}
smc_methodIdNumber::smc_methodIdNumber(std::int32_t number_)
: number_(number_)
{}
const std::int32_t smc_methodIdNumber::ID;
void smc_methodIdNumber::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_methodIdNumber");
s.store_field("number", number_);
s.store_class_end();
}
}
smc_methodIdName::smc_methodIdName()
: name_()
{}
smc_methodIdName::smc_methodIdName(std::string const &name_)
: name_(std::move(name_))
{}
const std::int32_t smc_methodIdName::ID;
void smc_methodIdName::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_methodIdName");
s.store_field("name", name_);
s.store_class_end();
}
}
smc_runResult::smc_runResult()
: gas_used_()
, stack_()
, exit_code_()
{}
smc_runResult::smc_runResult(std::int64_t gas_used_, std::vector<object_ptr<tvm_StackEntry>> &&stack_, std::int32_t exit_code_)
: gas_used_(gas_used_)
, stack_(std::move(stack_))
, exit_code_(exit_code_)
{}
const std::int32_t smc_runResult::ID;
void smc_runResult::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_runResult");
s.store_field("gas_used", gas_used_);
{ const std::vector<object_ptr<tvm_StackEntry>> &v = stack_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("stack", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
s.store_field("exit_code", exit_code_);
s.store_class_end();
}
}
testGiver_accountState::testGiver_accountState()
: balance_()
, seqno_()
@ -928,6 +1042,126 @@ void testWallet_initialAccountState::store(td::TlStorerToString &s, const char *
}
}
tvm_cell::tvm_cell()
: bytes_()
{}
tvm_cell::tvm_cell(std::string const &bytes_)
: bytes_(std::move(bytes_))
{}
const std::int32_t tvm_cell::ID;
void tvm_cell::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "tvm_cell");
s.store_field("bytes", bytes_);
s.store_class_end();
}
}
tvm_numberDecimal::tvm_numberDecimal()
: number_()
{}
tvm_numberDecimal::tvm_numberDecimal(std::string const &number_)
: number_(std::move(number_))
{}
const std::int32_t tvm_numberDecimal::ID;
void tvm_numberDecimal::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "tvm_numberDecimal");
s.store_field("number", number_);
s.store_class_end();
}
}
tvm_slice::tvm_slice()
: bytes_()
{}
tvm_slice::tvm_slice(std::string const &bytes_)
: bytes_(std::move(bytes_))
{}
const std::int32_t tvm_slice::ID;
void tvm_slice::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "tvm_slice");
s.store_field("bytes", bytes_);
s.store_class_end();
}
}
tvm_stackEntrySlice::tvm_stackEntrySlice()
: slice_()
{}
tvm_stackEntrySlice::tvm_stackEntrySlice(object_ptr<tvm_slice> &&slice_)
: slice_(std::move(slice_))
{}
const std::int32_t tvm_stackEntrySlice::ID;
void tvm_stackEntrySlice::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "tvm_stackEntrySlice");
if (slice_ == nullptr) { s.store_field("slice", "null"); } else { slice_->store(s, "slice"); }
s.store_class_end();
}
}
tvm_stackEntryCell::tvm_stackEntryCell()
: cell_()
{}
tvm_stackEntryCell::tvm_stackEntryCell(object_ptr<tvm_cell> &&cell_)
: cell_(std::move(cell_))
{}
const std::int32_t tvm_stackEntryCell::ID;
void tvm_stackEntryCell::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "tvm_stackEntryCell");
if (cell_ == nullptr) { s.store_field("cell", "null"); } else { cell_->store(s, "cell"); }
s.store_class_end();
}
}
tvm_stackEntryNumber::tvm_stackEntryNumber()
: number_()
{}
tvm_stackEntryNumber::tvm_stackEntryNumber(object_ptr<tvm_numberDecimal> &&number_)
: number_(std::move(number_))
{}
const std::int32_t tvm_stackEntryNumber::ID;
void tvm_stackEntryNumber::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "tvm_stackEntryNumber");
if (number_ == nullptr) { s.store_field("number", "null"); } else { number_->store(s, "number"); }
s.store_class_end();
}
}
tvm_stackEntryUnsupported::tvm_stackEntryUnsupported() {
}
const std::int32_t tvm_stackEntryUnsupported::ID;
void tvm_stackEntryUnsupported::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "tvm_stackEntryUnsupported");
s.store_class_end();
}
}
uninited_accountState::uninited_accountState()
: balance_()
, last_transaction_id_()
@ -1000,6 +1234,57 @@ void wallet_initialAccountState::store(td::TlStorerToString &s, const char *fiel
}
}
wallet_v3_accountState::wallet_v3_accountState()
: balance_()
, wallet_id_()
, seqno_()
, last_transaction_id_()
, sync_utime_()
{}
wallet_v3_accountState::wallet_v3_accountState(std::int64_t balance_, std::int64_t wallet_id_, std::int32_t seqno_, object_ptr<internal_transactionId> &&last_transaction_id_, std::int64_t sync_utime_)
: balance_(balance_)
, wallet_id_(wallet_id_)
, seqno_(seqno_)
, last_transaction_id_(std::move(last_transaction_id_))
, sync_utime_(sync_utime_)
{}
const std::int32_t wallet_v3_accountState::ID;
void wallet_v3_accountState::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "wallet_v3_accountState");
s.store_field("balance", balance_);
s.store_field("wallet_id", wallet_id_);
s.store_field("seqno", seqno_);
if (last_transaction_id_ == nullptr) { s.store_field("last_transaction_id", "null"); } else { last_transaction_id_->store(s, "last_transaction_id"); }
s.store_field("sync_utime", sync_utime_);
s.store_class_end();
}
}
wallet_v3_initialAccountState::wallet_v3_initialAccountState()
: public_key_()
, wallet_id_()
{}
wallet_v3_initialAccountState::wallet_v3_initialAccountState(std::string const &public_key_, std::int64_t wallet_id_)
: public_key_(std::move(public_key_))
, wallet_id_(wallet_id_)
{}
const std::int32_t wallet_v3_initialAccountState::ID;
void wallet_v3_initialAccountState::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "wallet_v3_initialAccountState");
s.store_field("public_key", public_key_);
s.store_field("wallet_id", wallet_id_);
s.store_class_end();
}
}
addLogMessage::addLogMessage()
: verbosity_level_()
, text_()
@ -1558,6 +1843,24 @@ void options_setConfig::store(td::TlStorerToString &s, const char *field_name) c
}
}
options_validateConfig::options_validateConfig()
: config_()
{}
options_validateConfig::options_validateConfig(object_ptr<config> &&config_)
: config_(std::move(config_))
{}
const std::int32_t options_validateConfig::ID;
void options_validateConfig::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "options_validateConfig");
if (config_ == nullptr) { s.store_field("config", "null"); } else { config_->store(s, "config"); }
s.store_class_end();
}
}
packAccountAddress::packAccountAddress()
: account_address_()
{}
@ -1852,6 +2155,102 @@ void setLogVerbosityLevel::store(td::TlStorerToString &s, const char *field_name
}
}
smc_getCode::smc_getCode()
: id_()
{}
smc_getCode::smc_getCode(std::int64_t id_)
: id_(id_)
{}
const std::int32_t smc_getCode::ID;
void smc_getCode::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_getCode");
s.store_field("id", id_);
s.store_class_end();
}
}
smc_getData::smc_getData()
: id_()
{}
smc_getData::smc_getData(std::int64_t id_)
: id_(id_)
{}
const std::int32_t smc_getData::ID;
void smc_getData::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_getData");
s.store_field("id", id_);
s.store_class_end();
}
}
smc_getState::smc_getState()
: id_()
{}
smc_getState::smc_getState(std::int64_t id_)
: id_(id_)
{}
const std::int32_t smc_getState::ID;
void smc_getState::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_getState");
s.store_field("id", id_);
s.store_class_end();
}
}
smc_load::smc_load()
: account_address_()
{}
smc_load::smc_load(object_ptr<accountAddress> &&account_address_)
: account_address_(std::move(account_address_))
{}
const std::int32_t smc_load::ID;
void smc_load::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_load");
if (account_address_ == nullptr) { s.store_field("account_address", "null"); } else { account_address_->store(s, "account_address"); }
s.store_class_end();
}
}
smc_runGetMethod::smc_runGetMethod()
: id_()
, method_()
, stack_()
{}
smc_runGetMethod::smc_runGetMethod(std::int64_t id_, object_ptr<smc_MethodId> &&method_, std::vector<object_ptr<tvm_StackEntry>> &&stack_)
: id_(id_)
, method_(std::move(method_))
, stack_(std::move(stack_))
{}
const std::int32_t smc_runGetMethod::ID;
void smc_runGetMethod::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "smc_runGetMethod");
s.store_field("id", id_);
if (method_ == nullptr) { s.store_field("method", "null"); } else { method_->store(s, "method"); }
{ const std::vector<object_ptr<tvm_StackEntry>> &v = stack_; const std::uint32_t multiplicity = static_cast<std::uint32_t>(v.size()); const auto vector_name = "vector[" + td::to_string(multiplicity)+ "]"; s.store_class_begin("stack", vector_name.c_str()); for (std::uint32_t i = 0; i < multiplicity; i++) { if (v[i] == nullptr) { s.store_field("", "null"); } else { v[i]->store(s, ""); } } s.store_class_end(); }
s.store_class_end();
}
}
sync::sync() {
}
@ -2103,5 +2502,23 @@ void wallet_sendGrams::store(td::TlStorerToString &s, const char *field_name) co
s.store_class_end();
}
}
wallet_v3_getAccountAddress::wallet_v3_getAccountAddress()
: initital_account_state_()
{}
wallet_v3_getAccountAddress::wallet_v3_getAccountAddress(object_ptr<wallet_v3_initialAccountState> &&initital_account_state_)
: initital_account_state_(std::move(initital_account_state_))
{}
const std::int32_t wallet_v3_getAccountAddress::ID;
void wallet_v3_getAccountAddress::store(td::TlStorerToString &s, const char *field_name) const {
if (!LOG_IS_STRIPPED(ERROR)) {
s.store_class_begin(field_name, "wallet_v3_getAccountAddress");
if (initital_account_state_ == nullptr) { s.store_field("initital_account_state", "null"); } else { initital_account_state_->store(s, "initital_account_state"); }
s.store_class_end();
}
}
} // namespace tonlib_api
} // namespace ton

View File

@ -92,6 +92,8 @@ class internal_transactionId;
class liteServer_info;
class options_configInfo;
class query_fees;
class query_info;
@ -106,18 +108,36 @@ class raw_transaction;
class raw_transactions;
class smc_info;
class smc_MethodId;
class smc_runResult;
class testGiver_accountState;
class testWallet_accountState;
class testWallet_initialAccountState;
class tvm_cell;
class tvm_numberDecimal;
class tvm_slice;
class tvm_StackEntry;
class uninited_accountState;
class wallet_accountState;
class wallet_initialAccountState;
class wallet_v3_accountState;
class wallet_v3_initialAccountState;
class Object;
class Object: public TlObject {
@ -283,16 +303,16 @@ class InputKey: public Object {
public:
};
class inputKey final : public InputKey {
class inputKeyRegular final : public InputKey {
public:
object_ptr<key> key_;
td::SecureString local_password_;
inputKey();
inputKeyRegular();
inputKey(object_ptr<key> &&key_, td::SecureString &&local_password_);
inputKeyRegular(object_ptr<key> &&key_, td::SecureString &&local_password_);
static const std::int32_t ID = 869287093;
static const std::int32_t ID = -555399522;
std::int32_t get_id() const final {
return ID;
}
@ -632,6 +652,22 @@ class generic_accountStateWallet final : public generic_AccountState {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class generic_accountStateWalletV3 final : public generic_AccountState {
public:
object_ptr<wallet_v3_accountState> account_state_;
generic_accountStateWalletV3();
explicit generic_accountStateWalletV3(object_ptr<wallet_v3_accountState> &&account_state_);
static const std::int32_t ID = -281349583;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class generic_accountStateTestGiver final : public generic_AccountState {
public:
object_ptr<testGiver_accountState> account_state_;
@ -699,6 +735,22 @@ class liteServer_info final : public Object {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class options_configInfo final : public Object {
public:
std::int64_t default_wallet_id_;
options_configInfo();
explicit options_configInfo(std::int64_t default_wallet_id_);
static const std::int32_t ID = 165216422;
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<fees> source_fees_;
@ -835,6 +887,76 @@ class raw_transactions final : public Object {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_info final : public Object {
public:
std::int64_t id_;
smc_info();
explicit smc_info(std::int64_t id_);
static const std::int32_t ID = 1134270012;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_MethodId: public Object {
public:
};
class smc_methodIdNumber final : public smc_MethodId {
public:
std::int32_t number_;
smc_methodIdNumber();
explicit smc_methodIdNumber(std::int32_t number_);
static const std::int32_t ID = -1541162500;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_methodIdName final : public smc_MethodId {
public:
std::string name_;
smc_methodIdName();
explicit smc_methodIdName(std::string const &name_);
static const std::int32_t ID = -249036908;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_runResult final : public Object {
public:
std::int64_t gas_used_;
std::vector<object_ptr<tvm_StackEntry>> stack_;
std::int32_t exit_code_;
smc_runResult();
smc_runResult(std::int64_t gas_used_, std::vector<object_ptr<tvm_StackEntry>> &&stack_, std::int32_t exit_code_);
static const std::int32_t ID = 1413805043;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class testGiver_accountState final : public Object {
public:
std::int64_t balance_;
@ -889,6 +1011,119 @@ class testWallet_initialAccountState final : public Object {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class tvm_cell final : public Object {
public:
std::string bytes_;
tvm_cell();
explicit tvm_cell(std::string const &bytes_);
static const std::int32_t ID = -859530316;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class tvm_numberDecimal final : public Object {
public:
std::string number_;
tvm_numberDecimal();
explicit tvm_numberDecimal(std::string const &number_);
static const std::int32_t ID = 1172477619;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class tvm_slice final : public Object {
public:
std::string bytes_;
tvm_slice();
explicit tvm_slice(std::string const &bytes_);
static const std::int32_t ID = -1069968387;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class tvm_StackEntry: public Object {
public:
};
class tvm_stackEntrySlice final : public tvm_StackEntry {
public:
object_ptr<tvm_slice> slice_;
tvm_stackEntrySlice();
explicit tvm_stackEntrySlice(object_ptr<tvm_slice> &&slice_);
static const std::int32_t ID = 1395485477;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class tvm_stackEntryCell final : public tvm_StackEntry {
public:
object_ptr<tvm_cell> cell_;
tvm_stackEntryCell();
explicit tvm_stackEntryCell(object_ptr<tvm_cell> &&cell_);
static const std::int32_t ID = 1303473952;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class tvm_stackEntryNumber final : public tvm_StackEntry {
public:
object_ptr<tvm_numberDecimal> number_;
tvm_stackEntryNumber();
explicit tvm_stackEntryNumber(object_ptr<tvm_numberDecimal> &&number_);
static const std::int32_t ID = 1358642622;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class tvm_stackEntryUnsupported final : public tvm_StackEntry {
public:
tvm_stackEntryUnsupported();
static const std::int32_t ID = 378880498;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class uninited_accountState final : public Object {
public:
std::int64_t balance_;
@ -943,6 +1178,43 @@ class wallet_initialAccountState final : public Object {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class wallet_v3_accountState final : public Object {
public:
std::int64_t balance_;
std::int64_t wallet_id_;
std::int32_t seqno_;
object_ptr<internal_transactionId> last_transaction_id_;
std::int64_t sync_utime_;
wallet_v3_accountState();
wallet_v3_accountState(std::int64_t balance_, std::int64_t wallet_id_, std::int32_t seqno_, object_ptr<internal_transactionId> &&last_transaction_id_, std::int64_t sync_utime_);
static const std::int32_t ID = 1977698154;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class wallet_v3_initialAccountState final : public Object {
public:
std::string public_key_;
std::int64_t wallet_id_;
wallet_v3_initialAccountState();
wallet_v3_initialAccountState(std::string const &public_key_, std::int64_t wallet_id_);
static const std::int32_t ID = 283460879;
std::int32_t get_id() const final {
return ID;
}
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class addLogMessage final : public Function {
public:
std::int32_t verbosity_level_;
@ -1459,6 +1731,24 @@ class options_setConfig final : public Function {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class options_validateConfig final : public Function {
public:
object_ptr<config> config_;
options_validateConfig();
explicit options_validateConfig(object_ptr<config> &&config_);
static const std::int32_t ID = -346965447;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<options_configInfo>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class packAccountAddress final : public Function {
public:
object_ptr<unpackedAccountAddress> account_address_;
@ -1737,6 +2027,98 @@ class setLogVerbosityLevel final : public Function {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_getCode final : public Function {
public:
std::int64_t id_;
smc_getCode();
explicit smc_getCode(std::int64_t id_);
static const std::int32_t ID = -2115626088;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tvm_cell>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_getData final : public Function {
public:
std::int64_t id_;
smc_getData();
explicit smc_getData(std::int64_t id_);
static const std::int32_t ID = -427601079;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tvm_cell>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_getState final : public Function {
public:
std::int64_t id_;
smc_getState();
explicit smc_getState(std::int64_t id_);
static const std::int32_t ID = -214390293;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<tvm_cell>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_load final : public Function {
public:
object_ptr<accountAddress> account_address_;
smc_load();
explicit smc_load(object_ptr<accountAddress> &&account_address_);
static const std::int32_t ID = -903491521;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<smc_info>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class smc_runGetMethod final : public Function {
public:
std::int64_t id_;
object_ptr<smc_MethodId> method_;
std::vector<object_ptr<tvm_StackEntry>> stack_;
smc_runGetMethod();
smc_runGetMethod(std::int64_t id_, object_ptr<smc_MethodId> &&method_, std::vector<object_ptr<tvm_StackEntry>> &&stack_);
static const std::int32_t ID = -255261270;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<smc_runResult>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class sync final : public Function {
public:
@ -1974,5 +2356,23 @@ class wallet_sendGrams final : public Function {
void store(td::TlStorerToString &s, const char *field_name) const final;
};
class wallet_v3_getAccountAddress final : public Function {
public:
object_ptr<wallet_v3_initialAccountState> initital_account_state_;
wallet_v3_getAccountAddress();
explicit wallet_v3_getAccountAddress(object_ptr<wallet_v3_initialAccountState> &&initital_account_state_);
static const std::int32_t ID = 1011655671;
std::int32_t get_id() const final {
return ID;
}
using ReturnType = object_ptr<accountAddress>;
void store(td::TlStorerToString &s, const char *field_name) const final;
};
} // namespace tonlib_api
} // namespace ton

View File

@ -41,8 +41,8 @@ bool downcast_call(Object &obj, const T &func) {
case fees::ID:
func(static_cast<fees &>(obj));
return true;
case inputKey::ID:
func(static_cast<inputKey &>(obj));
case inputKeyRegular::ID:
func(static_cast<inputKeyRegular &>(obj));
return true;
case inputKeyFake::ID:
func(static_cast<inputKeyFake &>(obj));
@ -104,6 +104,9 @@ bool downcast_call(Object &obj, const T &func) {
case generic_accountStateWallet::ID:
func(static_cast<generic_accountStateWallet &>(obj));
return true;
case generic_accountStateWalletV3::ID:
func(static_cast<generic_accountStateWalletV3 &>(obj));
return true;
case generic_accountStateTestGiver::ID:
func(static_cast<generic_accountStateTestGiver &>(obj));
return true;
@ -116,6 +119,9 @@ bool downcast_call(Object &obj, const T &func) {
case liteServer_info::ID:
func(static_cast<liteServer_info &>(obj));
return true;
case options_configInfo::ID:
func(static_cast<options_configInfo &>(obj));
return true;
case query_fees::ID:
func(static_cast<query_fees &>(obj));
return true;
@ -137,6 +143,18 @@ bool downcast_call(Object &obj, const T &func) {
case raw_transactions::ID:
func(static_cast<raw_transactions &>(obj));
return true;
case smc_info::ID:
func(static_cast<smc_info &>(obj));
return true;
case smc_methodIdNumber::ID:
func(static_cast<smc_methodIdNumber &>(obj));
return true;
case smc_methodIdName::ID:
func(static_cast<smc_methodIdName &>(obj));
return true;
case smc_runResult::ID:
func(static_cast<smc_runResult &>(obj));
return true;
case testGiver_accountState::ID:
func(static_cast<testGiver_accountState &>(obj));
return true;
@ -146,6 +164,27 @@ bool downcast_call(Object &obj, const T &func) {
case testWallet_initialAccountState::ID:
func(static_cast<testWallet_initialAccountState &>(obj));
return true;
case tvm_cell::ID:
func(static_cast<tvm_cell &>(obj));
return true;
case tvm_numberDecimal::ID:
func(static_cast<tvm_numberDecimal &>(obj));
return true;
case tvm_slice::ID:
func(static_cast<tvm_slice &>(obj));
return true;
case tvm_stackEntrySlice::ID:
func(static_cast<tvm_stackEntrySlice &>(obj));
return true;
case tvm_stackEntryCell::ID:
func(static_cast<tvm_stackEntryCell &>(obj));
return true;
case tvm_stackEntryNumber::ID:
func(static_cast<tvm_stackEntryNumber &>(obj));
return true;
case tvm_stackEntryUnsupported::ID:
func(static_cast<tvm_stackEntryUnsupported &>(obj));
return true;
case uninited_accountState::ID:
func(static_cast<uninited_accountState &>(obj));
return true;
@ -155,6 +194,12 @@ bool downcast_call(Object &obj, const T &func) {
case wallet_initialAccountState::ID:
func(static_cast<wallet_initialAccountState &>(obj));
return true;
case wallet_v3_accountState::ID:
func(static_cast<wallet_v3_accountState &>(obj));
return true;
case wallet_v3_initialAccountState::ID:
func(static_cast<wallet_v3_initialAccountState &>(obj));
return true;
default:
return false;
}
@ -253,6 +298,9 @@ bool downcast_call(Function &obj, const T &func) {
case options_setConfig::ID:
func(static_cast<options_setConfig &>(obj));
return true;
case options_validateConfig::ID:
func(static_cast<options_validateConfig &>(obj));
return true;
case packAccountAddress::ID:
func(static_cast<packAccountAddress &>(obj));
return true;
@ -298,6 +346,21 @@ bool downcast_call(Function &obj, const T &func) {
case setLogVerbosityLevel::ID:
func(static_cast<setLogVerbosityLevel &>(obj));
return true;
case smc_getCode::ID:
func(static_cast<smc_getCode &>(obj));
return true;
case smc_getData::ID:
func(static_cast<smc_getData &>(obj));
return true;
case smc_getState::ID:
func(static_cast<smc_getState &>(obj));
return true;
case smc_load::ID:
func(static_cast<smc_load &>(obj));
return true;
case smc_runGetMethod::ID:
func(static_cast<smc_runGetMethod &>(obj));
return true;
case sync::ID:
func(static_cast<sync &>(obj));
return true;
@ -337,6 +400,9 @@ bool downcast_call(Function &obj, const T &func) {
case wallet_sendGrams::ID:
func(static_cast<wallet_sendGrams &>(obj));
return true;
case wallet_v3_getAccountAddress::ID:
func(static_cast<wallet_v3_getAccountAddress &>(obj));
return true;
default:
return false;
}
@ -351,8 +417,8 @@ bool downcast_call(Function &obj, const T &func) {
template <class T>
bool downcast_call(InputKey &obj, const T &func) {
switch (obj.get_id()) {
case inputKey::ID:
func(static_cast<inputKey &>(obj));
case inputKeyRegular::ID:
func(static_cast<inputKeyRegular &>(obj));
return true;
case inputKeyFake::ID:
func(static_cast<inputKeyFake &>(obj));
@ -463,6 +529,9 @@ bool downcast_call(generic_AccountState &obj, const T &func) {
case generic_accountStateWallet::ID:
func(static_cast<generic_accountStateWallet &>(obj));
return true;
case generic_accountStateWalletV3::ID:
func(static_cast<generic_accountStateWalletV3 &>(obj));
return true;
case generic_accountStateTestGiver::ID:
func(static_cast<generic_accountStateTestGiver &>(obj));
return true;
@ -474,5 +543,51 @@ bool downcast_call(generic_AccountState &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 <class T>
bool downcast_call(smc_MethodId &obj, const T &func) {
switch (obj.get_id()) {
case smc_methodIdNumber::ID:
func(static_cast<smc_methodIdNumber &>(obj));
return true;
case smc_methodIdName::ID:
func(static_cast<smc_methodIdName &>(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 <class T>
bool downcast_call(tvm_StackEntry &obj, const T &func) {
switch (obj.get_id()) {
case tvm_stackEntrySlice::ID:
func(static_cast<tvm_stackEntrySlice &>(obj));
return true;
case tvm_stackEntryCell::ID:
func(static_cast<tvm_stackEntryCell &>(obj));
return true;
case tvm_stackEntryNumber::ID:
func(static_cast<tvm_stackEntryNumber &>(obj));
return true;
case tvm_stackEntryUnsupported::ID:
func(static_cast<tvm_stackEntryUnsupported &>(obj));
return true;
default:
return false;
}
}
} // namespace tonlib_api
} // namespace ton

View File

@ -16,7 +16,7 @@ namespace tonlib_api{
using namespace td;
Result<int32> tl_constructor_from_string(tonlib_api::InputKey *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> m = {
{"inputKey", 869287093},
{"inputKeyRegular", -555399522},
{"inputKeyFake", -1074054722}
};
auto it = m.find(str);
@ -75,6 +75,7 @@ Result<int32> tl_constructor_from_string(tonlib_api::generic_AccountState *objec
{"generic.accountStateRaw", -1387096685},
{"generic.accountStateTestWallet", -1041955397},
{"generic.accountStateWallet", 942582925},
{"generic.accountStateWalletV3", -281349583},
{"generic.accountStateTestGiver", 1134654598},
{"generic.accountStateUninited", -908702008}
};
@ -84,6 +85,30 @@ Result<int32> tl_constructor_from_string(tonlib_api::generic_AccountState *objec
}
return it->second;
}
Result<int32> tl_constructor_from_string(tonlib_api::smc_MethodId *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> m = {
{"smc.methodIdNumber", -1541162500},
{"smc.methodIdName", -249036908}
};
auto it = m.find(str);
if (it == m.end()) {
return Status::Error(str + "Unknown class");
}
return it->second;
}
Result<int32> tl_constructor_from_string(tonlib_api::tvm_StackEntry *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> m = {
{"tvm.stackEntrySlice", 1395485477},
{"tvm.stackEntryCell", 1303473952},
{"tvm.stackEntryNumber", 1358642622},
{"tvm.stackEntryUnsupported", 378880498}
};
auto it = m.find(str);
if (it == m.end()) {
return Status::Error(str + "Unknown class");
}
return it->second;
}
Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::string &str) {
static const std::unordered_map<Slice, int32, SliceHash> m = {
{"accountAddress", 755613099},
@ -95,7 +120,7 @@ Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::
{"exportedKey", -1449248297},
{"exportedPemKey", 1425473725},
{"fees", 1676273340},
{"inputKey", 869287093},
{"inputKeyRegular", -555399522},
{"inputKeyFake", -1074054722},
{"key", -1978362923},
{"keyStoreTypeDirectory", -378990038},
@ -116,10 +141,12 @@ Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::
{"generic.accountStateRaw", -1387096685},
{"generic.accountStateTestWallet", -1041955397},
{"generic.accountStateWallet", 942582925},
{"generic.accountStateWalletV3", -281349583},
{"generic.accountStateTestGiver", 1134654598},
{"generic.accountStateUninited", -908702008},
{"internal.transactionId", -989527262},
{"liteServer.info", -1250165133},
{"options.configInfo", 165216422},
{"query.fees", 725267759},
{"query.info", 1588635915},
{"raw.accountState", 1205935434},
@ -127,12 +154,25 @@ Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::
{"raw.message", -906281442},
{"raw.transaction", 1887601793},
{"raw.transactions", -2063931155},
{"smc.info", 1134270012},
{"smc.methodIdNumber", -1541162500},
{"smc.methodIdName", -249036908},
{"smc.runResult", 1413805043},
{"testGiver.accountState", 860930426},
{"testWallet.accountState", 305698744},
{"testWallet.initialAccountState", -1231516227},
{"tvm.cell", -859530316},
{"tvm.numberDecimal", 1172477619},
{"tvm.slice", -1069968387},
{"tvm.stackEntrySlice", 1395485477},
{"tvm.stackEntryCell", 1303473952},
{"tvm.stackEntryNumber", 1358642622},
{"tvm.stackEntryUnsupported", 378880498},
{"uninited.accountState", -918880075},
{"wallet.accountState", -1919815977},
{"wallet.initialAccountState", -1079249978}
{"wallet.initialAccountState", -1079249978},
{"wallet.v3.accountState", 1977698154},
{"wallet.v3.initialAccountState", 283460879}
};
auto it = m.find(str);
if (it == m.end()) {
@ -170,6 +210,7 @@ Result<int32> tl_constructor_from_string(tonlib_api::Function *object, const std
{"onLiteServerQueryError", -677427533},
{"onLiteServerQueryResult", 2056444510},
{"options.setConfig", 646497241},
{"options.validateConfig", -346965447},
{"packAccountAddress", -1388561940},
{"query.estimateFees", -957002175},
{"query.forget", -1211985313},
@ -185,6 +226,11 @@ Result<int32> tl_constructor_from_string(tonlib_api::Function *object, const std
{"setLogStream", -1364199535},
{"setLogTagVerbosityLevel", -2095589738},
{"setLogVerbosityLevel", -303429678},
{"smc.getCode", -2115626088},
{"smc.getData", -427601079},
{"smc.getState", -214390293},
{"smc.load", -903491521},
{"smc.runGetMethod", -255261270},
{"sync", -1617065525},
{"testGiver.getAccountAddress", -540100768},
{"testGiver.getAccountState", 267738275},
@ -197,7 +243,8 @@ Result<int32> tl_constructor_from_string(tonlib_api::Function *object, const std
{"wallet.getAccountAddress", -1004103180},
{"wallet.getAccountState", 462294850},
{"wallet.init", -395706309},
{"wallet.sendGrams", 297317621}
{"wallet.sendGrams", 297317621},
{"wallet.v3.getAccountAddress", 1011655671}
};
auto it = m.find(str);
if (it == m.end()) {
@ -328,7 +375,7 @@ Status from_json(tonlib_api::fees &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::inputKey &to, JsonObject &from) {
Status from_json(tonlib_api::inputKeyRegular &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "key", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
@ -547,6 +594,15 @@ Status from_json(tonlib_api::generic_accountStateWallet &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::generic_accountStateWalletV3 &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "account_state", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.account_state_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::generic_accountStateTestGiver &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "account_state", JsonValue::Type::Null, true));
@ -601,6 +657,15 @@ Status from_json(tonlib_api::liteServer_info &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::options_configInfo &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "default_wallet_id", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.default_wallet_id_, 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));
@ -808,6 +873,54 @@ Status from_json(tonlib_api::raw_transactions &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::smc_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));
}
}
return Status::OK();
}
Status from_json(tonlib_api::smc_methodIdNumber &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "number", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.number_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::smc_methodIdName &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "name", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.name_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::smc_runResult &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "gas_used", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.gas_used_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "stack", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.stack_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "exit_code", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.exit_code_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::testGiver_accountState &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "balance", JsonValue::Type::Null, true));
@ -871,6 +984,63 @@ Status from_json(tonlib_api::testWallet_initialAccountState &to, JsonObject &fro
}
return Status::OK();
}
Status from_json(tonlib_api::tvm_cell &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "bytes", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.bytes_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::tvm_numberDecimal &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "number", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.number_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::tvm_slice &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "bytes", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.bytes_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::tvm_stackEntrySlice &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "slice", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.slice_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::tvm_stackEntryCell &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "cell", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.cell_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::tvm_stackEntryNumber &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "number", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.number_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::tvm_stackEntryUnsupported &to, JsonObject &from) {
return Status::OK();
}
Status from_json(tonlib_api::uninited_accountState &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "balance", JsonValue::Type::Null, true));
@ -934,6 +1104,54 @@ Status from_json(tonlib_api::wallet_initialAccountState &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::wallet_v3_accountState &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "balance", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.balance_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "wallet_id", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.wallet_id_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "seqno", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.seqno_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "last_transaction_id", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.last_transaction_id_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "sync_utime", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.sync_utime_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::wallet_v3_initialAccountState &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "public_key", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.public_key_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "wallet_id", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.wallet_id_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::addLogMessage &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "verbosity_level", JsonValue::Type::Null, true));
@ -1330,6 +1548,15 @@ Status from_json(tonlib_api::options_setConfig &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::options_validateConfig &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "config", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.config_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::packAccountAddress &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "account_address", JsonValue::Type::Null, true));
@ -1513,6 +1740,63 @@ Status from_json(tonlib_api::setLogVerbosityLevel &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::smc_getCode &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::smc_getData &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::smc_getState &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::smc_load &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "account_address", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.account_address_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::smc_runGetMethod &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, "method", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.method_, value));
}
}
{
TRY_RESULT(value, get_json_object_field(from, "stack", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.stack_, value));
}
}
return Status::OK();
}
Status from_json(tonlib_api::sync &to, JsonObject &from) {
return Status::OK();
}
@ -1684,6 +1968,15 @@ Status from_json(tonlib_api::wallet_sendGrams &to, JsonObject &from) {
}
return Status::OK();
}
Status from_json(tonlib_api::wallet_v3_getAccountAddress &to, JsonObject &from) {
{
TRY_RESULT(value, get_json_object_field(from, "initital_account_state", JsonValue::Type::Null, true));
if (value.type() != JsonValue::Type::Null) {
TRY_STATUS(from_json(to.initital_account_state_, value));
}
}
return Status::OK();
}
void to_json(JsonValueScope &jv, const tonlib_api::accountAddress &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "accountAddress");
@ -1739,9 +2032,9 @@ void to_json(JsonValueScope &jv, const tonlib_api::fees &object) {
void to_json(JsonValueScope &jv, const tonlib_api::InputKey &object) {
tonlib_api::downcast_call(const_cast<tonlib_api::InputKey &>(object), [&jv](const auto &object) { to_json(jv, object); });
}
void to_json(JsonValueScope &jv, const tonlib_api::inputKey &object) {
void to_json(JsonValueScope &jv, const tonlib_api::inputKeyRegular &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "inputKey");
jo << ctie("@type", "inputKeyRegular");
if (object.key_) {
jo << ctie("key", ToJson(object.key_));
}
@ -1878,6 +2171,13 @@ void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateWallet &o
jo << ctie("account_state", ToJson(object.account_state_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateWalletV3 &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "generic.accountStateWalletV3");
if (object.account_state_) {
jo << ctie("account_state", ToJson(object.account_state_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateTestGiver &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "generic.accountStateTestGiver");
@ -1905,6 +2205,11 @@ void to_json(JsonValueScope &jv, const tonlib_api::liteServer_info &object) {
jo << ctie("version", ToJson(object.version_));
jo << ctie("capabilities", ToJson(JsonInt64{object.capabilities_}));
}
void to_json(JsonValueScope &jv, const tonlib_api::options_configInfo &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "options.configInfo");
jo << ctie("default_wallet_id", ToJson(object.default_wallet_id_));
}
void to_json(JsonValueScope &jv, const tonlib_api::query_fees &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "query.fees");
@ -1976,6 +2281,31 @@ void to_json(JsonValueScope &jv, const tonlib_api::raw_transactions &object) {
jo << ctie("previous_transaction_id", ToJson(object.previous_transaction_id_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_info &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.info");
jo << ctie("id", ToJson(object.id_));
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_MethodId &object) {
tonlib_api::downcast_call(const_cast<tonlib_api::smc_MethodId &>(object), [&jv](const auto &object) { to_json(jv, object); });
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_methodIdNumber &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.methodIdNumber");
jo << ctie("number", ToJson(object.number_));
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_methodIdName &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.methodIdName");
jo << ctie("name", ToJson(object.name_));
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_runResult &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.runResult");
jo << ctie("gas_used", ToJson(object.gas_used_));
jo << ctie("stack", ToJson(object.stack_));
jo << ctie("exit_code", ToJson(object.exit_code_));
}
void to_json(JsonValueScope &jv, const tonlib_api::testGiver_accountState &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "testGiver.accountState");
@ -2001,6 +2331,49 @@ void to_json(JsonValueScope &jv, const tonlib_api::testWallet_initialAccountStat
jo << ctie("@type", "testWallet.initialAccountState");
jo << ctie("public_key", ToJson(object.public_key_));
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_cell &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "tvm.cell");
jo << ctie("bytes", ToJson(object.bytes_));
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_numberDecimal &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "tvm.numberDecimal");
jo << ctie("number", ToJson(object.number_));
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_slice &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "tvm.slice");
jo << ctie("bytes", ToJson(object.bytes_));
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_StackEntry &object) {
tonlib_api::downcast_call(const_cast<tonlib_api::tvm_StackEntry &>(object), [&jv](const auto &object) { to_json(jv, object); });
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntrySlice &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "tvm.stackEntrySlice");
if (object.slice_) {
jo << ctie("slice", ToJson(object.slice_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntryCell &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "tvm.stackEntryCell");
if (object.cell_) {
jo << ctie("cell", ToJson(object.cell_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntryNumber &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "tvm.stackEntryNumber");
if (object.number_) {
jo << ctie("number", ToJson(object.number_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntryUnsupported &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "tvm.stackEntryUnsupported");
}
void to_json(JsonValueScope &jv, const tonlib_api::uninited_accountState &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "uninited.accountState");
@ -2026,6 +2399,23 @@ void to_json(JsonValueScope &jv, const tonlib_api::wallet_initialAccountState &o
jo << ctie("@type", "wallet.initialAccountState");
jo << ctie("public_key", ToJson(object.public_key_));
}
void to_json(JsonValueScope &jv, const tonlib_api::wallet_v3_accountState &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "wallet.v3.accountState");
jo << ctie("balance", ToJson(JsonInt64{object.balance_}));
jo << ctie("wallet_id", ToJson(object.wallet_id_));
jo << ctie("seqno", ToJson(object.seqno_));
if (object.last_transaction_id_) {
jo << ctie("last_transaction_id", ToJson(object.last_transaction_id_));
}
jo << ctie("sync_utime", ToJson(object.sync_utime_));
}
void to_json(JsonValueScope &jv, const tonlib_api::wallet_v3_initialAccountState &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "wallet.v3.initialAccountState");
jo << ctie("public_key", ToJson(object.public_key_));
jo << ctie("wallet_id", ToJson(object.wallet_id_));
}
void to_json(JsonValueScope &jv, const tonlib_api::addLogMessage &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "addLogMessage");
@ -2226,6 +2616,13 @@ void to_json(JsonValueScope &jv, const tonlib_api::options_setConfig &object) {
jo << ctie("config", ToJson(object.config_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::options_validateConfig &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "options.validateConfig");
if (object.config_) {
jo << ctie("config", ToJson(object.config_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::packAccountAddress &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "packAccountAddress");
@ -2325,6 +2722,37 @@ 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::smc_getCode &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.getCode");
jo << ctie("id", ToJson(object.id_));
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_getData &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.getData");
jo << ctie("id", ToJson(object.id_));
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_getState &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.getState");
jo << ctie("id", ToJson(object.id_));
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_load &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.load");
if (object.account_address_) {
jo << ctie("account_address", ToJson(object.account_address_));
}
}
void to_json(JsonValueScope &jv, const tonlib_api::smc_runGetMethod &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "smc.runGetMethod");
jo << ctie("id", ToJson(object.id_));
if (object.method_) {
jo << ctie("method", ToJson(object.method_));
}
jo << ctie("stack", ToJson(object.stack_));
}
void to_json(JsonValueScope &jv, const tonlib_api::sync &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "sync");
@ -2421,5 +2849,12 @@ void to_json(JsonValueScope &jv, const tonlib_api::wallet_sendGrams &object) {
jo << ctie("amount", ToJson(JsonInt64{object.amount_}));
jo << ctie("message", ToJson(JsonBytes{object.message_}));
}
void to_json(JsonValueScope &jv, const tonlib_api::wallet_v3_getAccountAddress &object) {
auto jo = jv.enter_object();
jo << ctie("@type", "wallet.v3.getAccountAddress");
if (object.initital_account_state_) {
jo << ctie("initital_account_state", ToJson(object.initital_account_state_));
}
}
} // namespace tonlib_api
} // namespace ton

View File

@ -17,6 +17,8 @@ Result<int32> tl_constructor_from_string(tonlib_api::LogStream *object, const st
Result<int32> tl_constructor_from_string(tonlib_api::SyncState *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::Update *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::generic_AccountState *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::smc_MethodId *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::tvm_StackEntry *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::string &str);
Result<int32> tl_constructor_from_string(tonlib_api::Function *object, const std::string &str);
Status from_json(tonlib_api::accountAddress &to, JsonObject &from);
@ -28,7 +30,7 @@ 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::inputKeyRegular &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);
@ -49,10 +51,12 @@ 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_accountStateWalletV3 &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::options_configInfo &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);
@ -60,12 +64,25 @@ Status from_json(tonlib_api::raw_initialAccountState &to, JsonObject &from);
Status from_json(tonlib_api::raw_message &to, JsonObject &from);
Status from_json(tonlib_api::raw_transaction &to, JsonObject &from);
Status from_json(tonlib_api::raw_transactions &to, JsonObject &from);
Status from_json(tonlib_api::smc_info &to, JsonObject &from);
Status from_json(tonlib_api::smc_methodIdNumber &to, JsonObject &from);
Status from_json(tonlib_api::smc_methodIdName &to, JsonObject &from);
Status from_json(tonlib_api::smc_runResult &to, JsonObject &from);
Status from_json(tonlib_api::testGiver_accountState &to, JsonObject &from);
Status from_json(tonlib_api::testWallet_accountState &to, JsonObject &from);
Status from_json(tonlib_api::testWallet_initialAccountState &to, JsonObject &from);
Status from_json(tonlib_api::tvm_cell &to, JsonObject &from);
Status from_json(tonlib_api::tvm_numberDecimal &to, JsonObject &from);
Status from_json(tonlib_api::tvm_slice &to, JsonObject &from);
Status from_json(tonlib_api::tvm_stackEntrySlice &to, JsonObject &from);
Status from_json(tonlib_api::tvm_stackEntryCell &to, JsonObject &from);
Status from_json(tonlib_api::tvm_stackEntryNumber &to, JsonObject &from);
Status from_json(tonlib_api::tvm_stackEntryUnsupported &to, JsonObject &from);
Status from_json(tonlib_api::uninited_accountState &to, JsonObject &from);
Status from_json(tonlib_api::wallet_accountState &to, JsonObject &from);
Status from_json(tonlib_api::wallet_initialAccountState &to, JsonObject &from);
Status from_json(tonlib_api::wallet_v3_accountState &to, JsonObject &from);
Status from_json(tonlib_api::wallet_v3_initialAccountState &to, JsonObject &from);
Status from_json(tonlib_api::addLogMessage &to, JsonObject &from);
Status from_json(tonlib_api::changeLocalPassword &to, JsonObject &from);
Status from_json(tonlib_api::close &to, JsonObject &from);
@ -94,6 +111,7 @@ 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::options_validateConfig &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);
@ -109,6 +127,11 @@ 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::smc_getCode &to, JsonObject &from);
Status from_json(tonlib_api::smc_getData &to, JsonObject &from);
Status from_json(tonlib_api::smc_getState &to, JsonObject &from);
Status from_json(tonlib_api::smc_load &to, JsonObject &from);
Status from_json(tonlib_api::smc_runGetMethod &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);
@ -122,6 +145,7 @@ Status from_json(tonlib_api::wallet_getAccountAddress &to, JsonObject &from);
Status from_json(tonlib_api::wallet_getAccountState &to, JsonObject &from);
Status from_json(tonlib_api::wallet_init &to, JsonObject &from);
Status from_json(tonlib_api::wallet_sendGrams &to, JsonObject &from);
Status from_json(tonlib_api::wallet_v3_getAccountAddress &to, JsonObject &from);
void to_json(JsonValueScope &jv, const tonlib_api::accountAddress &object);
void to_json(JsonValueScope &jv, const tonlib_api::bip39Hints &object);
void to_json(JsonValueScope &jv, const tonlib_api::config &object);
@ -132,7 +156,7 @@ 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::inputKeyRegular &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);
@ -158,10 +182,12 @@ 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);
void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateWallet &object);
void to_json(JsonValueScope &jv, const tonlib_api::generic_accountStateWalletV3 &object);
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::options_configInfo &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);
@ -169,12 +195,27 @@ void to_json(JsonValueScope &jv, const tonlib_api::raw_initialAccountState &obje
void to_json(JsonValueScope &jv, const tonlib_api::raw_message &object);
void to_json(JsonValueScope &jv, const tonlib_api::raw_transaction &object);
void to_json(JsonValueScope &jv, const tonlib_api::raw_transactions &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_info &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_MethodId &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_methodIdNumber &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_methodIdName &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_runResult &object);
void to_json(JsonValueScope &jv, const tonlib_api::testGiver_accountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::testWallet_accountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::testWallet_initialAccountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_cell &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_numberDecimal &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_slice &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_StackEntry &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntrySlice &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntryCell &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntryNumber &object);
void to_json(JsonValueScope &jv, const tonlib_api::tvm_stackEntryUnsupported &object);
void to_json(JsonValueScope &jv, const tonlib_api::uninited_accountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::wallet_accountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::wallet_initialAccountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::wallet_v3_accountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::wallet_v3_initialAccountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::addLogMessage &object);
void to_json(JsonValueScope &jv, const tonlib_api::changeLocalPassword &object);
void to_json(JsonValueScope &jv, const tonlib_api::close &object);
@ -203,6 +244,7 @@ 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::options_validateConfig &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);
@ -218,6 +260,11 @@ 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::smc_getCode &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_getData &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_getState &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_load &object);
void to_json(JsonValueScope &jv, const tonlib_api::smc_runGetMethod &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);
@ -231,6 +278,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::wallet_getAccountAddress &obj
void to_json(JsonValueScope &jv, const tonlib_api::wallet_getAccountState &object);
void to_json(JsonValueScope &jv, const tonlib_api::wallet_init &object);
void to_json(JsonValueScope &jv, const tonlib_api::wallet_sendGrams &object);
void to_json(JsonValueScope &jv, const tonlib_api::wallet_v3_getAccountAddress &object);
inline void to_json(JsonValueScope &jv, const ton::tonlib_api::Object &object) {
ton::tonlib_api::downcast_call(const_cast<ton::tonlib_api::Object &>(object),[&jv](const auto &object) { to_json(jv, object); });
}

View File

@ -22,9 +22,10 @@ keyStoreTypeInMemory = KeyStoreType;
config config:string blockchain_name:string use_callbacks_for_network:Bool ignore_cache:Bool = Config;
options config:config keystore_type:KeyStoreType = Options;
options.configInfo default_wallet_id:int53 = options.ConfigInfo;
key public_key:string secret:secureBytes = Key;
inputKey key:key local_password:secureBytes = InputKey;
inputKeyRegular key:key local_password:secureBytes = InputKey;
inputKeyFake = InputKey;
exportedKey word_list:vector<secureString> = ExportedKey;
exportedPemKey pem:secureString = ExportedPemKey;
@ -50,6 +51,9 @@ testWallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.t
wallet.initialAccountState public_key:string = wallet.InitialAccountState;
wallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53 = wallet.AccountState;
wallet.v3.initialAccountState public_key:string wallet_id:int53 = wallet.v3.InitialAccountState;
wallet.v3.accountState balance:int64 wallet_id:int53 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53 = wallet.v3.AccountState;
testGiver.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53= testGiver.AccountState;
uninited.accountState balance:int64 last_transaction_id:internal.transactionId frozen_hash:bytes sync_utime:int53 = uninited.AccountState;
@ -61,6 +65,7 @@ uninited.accountState balance:int64 last_transaction_id:internal.transactionId f
generic.accountStateRaw account_state:raw.accountState = generic.AccountState;
generic.accountStateTestWallet account_state:testWallet.accountState = generic.AccountState;
generic.accountStateWallet account_state:wallet.accountState = generic.AccountState;
generic.accountStateWalletV3 account_state:wallet.v3.accountState = generic.AccountState;
generic.accountStateTestGiver account_state:testGiver.accountState = generic.AccountState;
generic.accountStateUninited account_state:uninited.accountState = generic.AccountState;
@ -73,25 +78,41 @@ 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;
tvm.slice bytes:string = tvm.Slice;
tvm.cell bytes:string = tvm.Cell;
tvm.numberDecimal number:string = tvm.Number;
tvm.stackEntrySlice slice:tvm.slice = tvm.StackEntry;
tvm.stackEntryCell cell:tvm.cell = tvm.StackEntry;
tvm.stackEntryNumber number:tvm.Number = tvm.StackEntry;
tvm.stackEntryUnsupported = tvm.StackEntry;
smc.info id:int53 = smc.Info;
smc.methodIdNumber number:int32 = smc.MethodId;
smc.methodIdName name:string = smc.MethodId;
smc.runResult gas_used:int53 stack:vector<tvm.StackEntry> exit_code:int32 = smc.RunResult;
updateSendLiteServerQuery id:int64 data:bytes = Update;
updateSyncState sync_state:SyncState = Update;
//@class LogStream @description Describes a stream to which TDLib internal log is written
//@class LogStream @description Describes a stream to which tonlib internal log is written
//@description The log is written to stderr or an OS specific log
logStreamDefault = LogStream;
//@description The log is written to a file @path Path to the file to where the internal TDLib log will be written @max_file_size Maximum size of the file to where the internal TDLib log is written before the file will be auto-rotated
//@description The log is written to a file @path Path to the file to where the internal tonlib log will be written @max_file_size Maximum size of the file to where the internal tonlib log is written before the file will be auto-rotated
logStreamFile path:string max_file_size:int53 = LogStream;
//@description The log is written nowhere
logStreamEmpty = LogStream;
//@description Contains a TDLib internal log verbosity level @verbosity_level Log verbosity level
//@description Contains a tonlib internal log verbosity level @verbosity_level Log verbosity level
logVerbosityLevel verbosity_level:int32 = LogVerbosityLevel;
//@description Contains a list of available TDLib internal log tags @tags List of log tags
//@description Contains a list of available tonlib internal log tags @tags List of log tags
logTags tags:vector<string> = LogTags;
data bytes:secureBytes = Data;
@ -104,6 +125,7 @@ init options:options = Ok;
close = Ok;
options.setConfig config:config = Ok;
options.validateConfig config:config = options.ConfigInfo;
createNewKey local_password:secureBytes mnemonic_password:secureBytes random_extra_seed:secureBytes = Key;
deleteKey key:key = Ok;
@ -122,7 +144,6 @@ kdf password:secureBytes salt:secureBytes iterations:int32 = Data;
unpackAccountAddress account_address:string = UnpackedAccountAddress;
packAccountAddress account_address:unpackedAccountAddress = AccountAddress;
getBip39Hints prefix:string = Bip39Hints;
//raw.init initial_account_state:raw.initialAccountState = Ok;
@ -143,6 +164,8 @@ wallet.getAccountAddress initital_account_state:wallet.initialAccountState = Acc
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.v3.getAccountAddress initital_account_state:wallet.v3.initialAccountState = AccountAddress;
testGiver.getAccountState = testGiver.AccountState;
testGiver.getAccountAddress = AccountAddress;
testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 message:bytes = SendGramsResult;
@ -160,6 +183,12 @@ query.forget id:int53 = Ok;
query.estimateFees id:int53 ignore_chksig:Bool = query.Fees;
query.getInfo id:int53 = query.Info;
smc.load account_address:accountAddress = smc.Info;
smc.getCode id:int53 = tvm.Cell;
smc.getData id:int53 = tvm.Cell;
smc.getState id:int53 = tvm.Cell;
smc.runGetMethod id:int53 method:smc.MethodId stack:vector<tvm.StackEntry> = smc.RunResult;
onLiteServerQueryResult id:int64 bytes:bytes = Ok;
onLiteServerQueryError id:int64 error:error = Ok;
@ -167,29 +196,29 @@ 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
//@description Sets new log stream for internal logging of tonlib. This is an offline method. Can be called before authorization. Can be called synchronously @log_stream New log stream
setLogStream log_stream:LogStream = Ok;
//@description Returns information about currently used log stream for internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously
//@description Returns information about currently used log stream for internal logging of tonlib. This is an offline method. Can be called before authorization. Can be called synchronously
getLogStream = LogStream;
//@description Sets the verbosity level of the internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously
//@description Sets the verbosity level of the internal logging of tonlib. This is an offline method. Can be called before authorization. Can be called synchronously
//@new_verbosity_level New value of the verbosity level for logging. Value 0 corresponds to fatal errors, value 1 corresponds to errors, value 2 corresponds to warnings and debug warnings, value 3 corresponds to informational, value 4 corresponds to debug, value 5 corresponds to verbose debug, value greater than 5 and up to 1023 can be used to enable even more logging
setLogVerbosityLevel new_verbosity_level:int32 = Ok;
//@description Returns current verbosity level of the internal logging of TDLib. This is an offline method. Can be called before authorization. Can be called synchronously
//@description Returns current verbosity level of the internal logging of tonlib. This is an offline method. Can be called before authorization. Can be called synchronously
getLogVerbosityLevel = LogVerbosityLevel;
//@description Returns list of available TDLib internal log tags, for example, ["actor", "binlog", "connections", "notifications", "proxy"]. This is an offline method. Can be called before authorization. Can be called synchronously
//@description Returns list of available tonlib internal log tags, for example, ["actor", "binlog", "connections", "notifications", "proxy"]. This is an offline method. Can be called before authorization. Can be called synchronously
getLogTags = LogTags;
//@description Sets the verbosity level for a specified TDLib internal log tag. This is an offline method. Can be called before authorization. Can be called synchronously
//@description Sets the verbosity level for a specified tonlib internal log tag. This is an offline method. Can be called before authorization. Can be called synchronously
//@tag Logging tag to change verbosity level @new_verbosity_level New verbosity level; 1-1024
setLogTagVerbosityLevel tag:string new_verbosity_level:int32 = Ok;
//@description Returns current verbosity level for a specified TDLib internal log tag. This is an offline method. Can be called before authorization. Can be called synchronously @tag Logging tag to change verbosity level
//@description Returns current verbosity level for a specified tonlib internal log tag. This is an offline method. Can be called before authorization. Can be called synchronously @tag Logging tag to change verbosity level
getLogTagVerbosityLevel tag:string = LogVerbosityLevel;
//@description Adds a message to TDLib internal log. This is an offline method. Can be called before authorization. Can be called synchronously
//@description Adds a message to tonlib internal log. This is an offline method. Can be called before authorization. Can be called synchronously
//@verbosity_level Minimum verbosity level needed for the message to be logged, 0-1023 @text Text of a message to log
addLogMessage verbosity_level:int32 text:string = Ok;

View File

@ -19,6 +19,7 @@
#include "block/block.h"
#include "block/block-auto.h"
#include "block/mc-config.h"
#include "vm/cells.h"
#include "vm/boc.h"
@ -246,6 +247,17 @@ TEST(Tonlib, ParseAddres) {
ASSERT_EQ("Uf9Tj6fMJP-OqhAdhKXxq36DL-HYSzCc3-9O6UNzqsgPfdyS", addr_str2->account_address_);
}
TEST(Tonlib, ConfigParseBug) {
td::Slice literal =
"D1000000000000006400000000000186A0DE0000000003E8000000000000000F424000000000000F42400000000000002710000000000098"
"96800000000005F5E100000000003B9ACA00";
unsigned char buff[128];
int bits = (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), literal.begin(), literal.end());
CHECK(bits >= 0);
auto slice = vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize();
block::Config::do_get_gas_limits_prices(std::move(slice), 21).ensure();
}
TEST(Tonlib, EncryptionApi) {
using tonlib_api::make_object;
Client client;
@ -296,15 +308,15 @@ TEST(Tonlib, KeysApi) {
td::SecureString{}))
.move_as_ok();
sync_send(client, make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKey>(
sync_send(client, make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(key->public_key_, key->secret_.copy()),
td::SecureString("wrong password"))))
.ensure_error();
//exportKey input_key:inputKey = ExportedKey;
//exportKey input_key:inputKeyRegular = ExportedKey;
auto exported_key =
sync_send(client,
make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKey>(
make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(key->public_key_, key->secret_.copy()), local_password.copy())))
.move_as_ok();
LOG(ERROR) << to_string(exported_key);
@ -316,20 +328,20 @@ TEST(Tonlib, KeysApi) {
return word_list_copy;
};
//changeLocalPassword input_key:inputKey new_local_password:bytes = Key;
//changeLocalPassword input_key:inputKeyRegular new_local_password:bytes = Key;
auto new_key =
sync_send(client,
make_object<tonlib_api::changeLocalPassword>(
make_object<tonlib_api::inputKey>(
make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(key->public_key_, key->secret_.copy()), local_password.copy()),
td::SecureString("tmp local password")))
.move_as_ok();
sync_send(client,
make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKey>(
make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(key->public_key_, new_key->secret_.copy()), local_password.copy())))
.ensure_error();
auto exported_key2 = sync_send(client, make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKey>(
auto exported_key2 = sync_send(client, make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(key->public_key_, new_key->secret_.copy()),
td::SecureString("tmp local password"))))
.move_as_ok();
@ -347,7 +359,7 @@ TEST(Tonlib, KeysApi) {
auto wrong_export_password = td::SecureString("wrong_export password");
auto exported_encrypted_key =
sync_send(client, make_object<tonlib_api::exportEncryptedKey>(
make_object<tonlib_api::inputKey>(
make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(key->public_key_, new_key->secret_.copy()),
td::SecureString("tmp local password")),
export_password.copy()))
@ -392,12 +404,12 @@ TEST(Tonlib, KeysApi) {
CHECK(imported_key->public_key_ == key->public_key_);
CHECK(imported_key->secret_ != key->secret_);
//exportPemKey input_key:inputKey key_password:bytes = ExportedPemKey;
//exportPemKey input_key:inputKeyRegular key_password:bytes = ExportedPemKey;
auto pem_password = td::SecureString("pem password");
auto r_exported_pem_key = sync_send(
client,
make_object<tonlib_api::exportPemKey>(
make_object<tonlib_api::inputKey>(
make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(key->public_key_, imported_key->secret_.copy()), new_local_password.copy()),
pem_password.copy()));
if (r_exported_pem_key.is_error() && r_exported_pem_key.error().message() == "INTERNAL Not supported") {

View File

@ -98,7 +98,7 @@ struct Key {
std::string public_key;
td::SecureString secret;
tonlib_api::object_ptr<tonlib_api::InputKey> get_input_key() const {
return tonlib_api::make_object<tonlib_api::inputKey>(
return tonlib_api::make_object<tonlib_api::inputKeyRegular>(
tonlib_api::make_object<tonlib_api::key>(public_key, secret.copy()), td::SecureString("local"));
}
tonlib_api::object_ptr<tonlib_api::InputKey> get_fake_input_key() const {
@ -133,9 +133,11 @@ void sync(Client& client) {
sync_send(client, make_object<tonlib_api::sync>()).ensure();
}
static td::uint32 default_wallet_id{0};
std::string wallet_address(Client& client, const Key& key) {
return sync_send(client, make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(key.public_key)))
return sync_send(client,
make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(key.public_key, default_wallet_id)))
.move_as_ok()
->account_address_;
}
@ -171,6 +173,7 @@ AccountState get_account_state(Client& client, std::string address) {
case tonlib_api::generic_accountStateUninited::ID:
res.type = AccountState::Empty;
break;
case tonlib_api::generic_accountStateWalletV3::ID:
case tonlib_api::generic_accountStateWallet::ID:
res.type = AccountState::Wallet;
break;
@ -358,8 +361,9 @@ Wallet create_empty_wallet(Client& client) {
Wallet wallet{"", {key->public_key_, std::move(key->secret_)}};
auto account_address =
sync_send(client, make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(wallet.key.public_key)))
sync_send(client,
make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(wallet.key.public_key, default_wallet_id)))
.move_as_ok();
wallet.address = account_address->account_address_;
@ -462,29 +466,31 @@ void test_multisig(Client& client, const Wallet& giver_wallet) {
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]);
for (int i = 0; i < 2; i++) {
// 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(), 1);
icb.store_bytes("\0\0\0\0", 4);
vm::CellString::store(icb, "Greatings from multisig", 35 * 8).ensure();
ton::MultisigWallet::QueryBuilder qb(-1 - i, icb.finalize());
for (int i = 0; i < k - 1; i++) {
qb.sign(i, private_keys[i]);
}
auto query_id =
create_raw_query(client, address,
i == 0 ? vm::std_boc_serialize(ms->get_state().code).move_as_ok().as_slice().str() : "",
i == 0 ? 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();
}
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[]) {
@ -515,8 +521,8 @@ int main(int argc, char* argv[]) {
if (reset_keystore_dir) {
td::rmrf(keystore_dir).ignore();
td::mkdir(keystore_dir).ensure();
}
td::mkdir(keystore_dir).ensure();
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(INFO));
static_send(make_object<tonlib_api::setLogTagVerbosityLevel>("tonlib_query", 4)).ensure();
@ -527,6 +533,10 @@ int main(int argc, char* argv[]) {
Client client;
{
auto info = sync_send(client, make_object<tonlib_api::options_validateConfig>(
make_object<tonlib_api::config>(global_config_str, "", false, false)))
.move_as_ok();
default_wallet_id = static_cast<td::uint32>(info->default_wallet_id_);
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
make_object<tonlib_api::config>(global_config_str, "", false, false),
make_object<tonlib_api::keyStoreTypeDirectory>(keystore_dir))))

View File

@ -1,64 +0,0 @@
#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<td::uint32>(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 <class F>
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<td::string> 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

View File

@ -1,22 +0,0 @@
#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<td::string> load(CellSlice &cs, unsigned int top_bits = Cell::max_bits);
private:
template <class F>
static void for_each(F &&f, CellSlice &cs, unsigned int top_bits = Cell::max_bits);
};
} // namespace vm

View File

@ -134,7 +134,7 @@ class Client::Impl final {
};
Client::Client() : impl_(std::make_unique<Impl>()) {
// At least it should be enough for everybody who uses TDLib
// At least it should be enough for everybody who uses tonlib
// FIXME
//td::init_openssl_threads();
}

View File

@ -42,6 +42,7 @@ class ExtClientOutboundImp : public ExtClientOutbound {
auto it = queries_.find(id);
if (it == queries_.end()) {
promise.set_error(TonlibError::Internal("Unknown query id"));
return;
}
it->second.set_result(std::move(r_data));
queries_.erase(it);

View File

@ -1,80 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tonlib/GenericAccount.h"
#include "tonlib/utils.h"
#include "block/block-auto.h"
namespace tonlib {
td::Ref<vm::Cell> GenericAccount::get_init_state(td::Ref<vm::Cell> code, td::Ref<vm::Cell> data) noexcept {
return vm::CellBuilder()
.append_cellslice(binary_bitstring_to_cellslice("b{00110}").move_as_ok())
.store_ref(std::move(code))
.store_ref(std::move(data))
.finalize();
}
block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id,
const td::Ref<vm::Cell>& init_state) noexcept {
return block::StdAddress(workchain_id, init_state->get_hash().bits(), true /*bounce*/);
}
td::Ref<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
td::Ref<vm::Cell> 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<vm::Cell> res;
tlb::type_pack_cell(res, block::gen::t_Message_Any, message);
CHECK(res.not_null());
return res;
}
} // namespace tonlib

View File

@ -1,30 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "vm/cells.h"
#include "block/block.h"
namespace tonlib {
class GenericAccount {
public:
static td::Ref<vm::Cell> get_init_state(td::Ref<vm::Cell> code, td::Ref<vm::Cell> data) noexcept;
static block::StdAddress get_address(ton::WorkchainId workchain_id, const td::Ref<vm::Cell>& init_state) noexcept;
static td::Ref<vm::Cell> create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
td::Ref<vm::Cell> body) noexcept;
};
} // namespace tonlib

View File

@ -169,18 +169,20 @@ td::Result<KeyStorage::Key> KeyStorage::import_pem_key(td::Slice local_password,
return save_key(DecryptedKey({}, std::move(key)), local_password);
}
static std::string dummy_secret = "dummy secret of 32 bytes length!";
td::SecureString get_dummy_secret() {
return td::SecureString("dummy secret of 32 bytes length!");
}
td::Result<KeyStorage::ExportedEncryptedKey> KeyStorage::export_encrypted_key(InputKey input_key,
td::Slice key_password) {
TRY_RESULT(decrypted_key, export_decrypted_key(std::move(input_key)));
auto res = decrypted_key.encrypt(key_password, dummy_secret);
auto res = decrypted_key.encrypt(key_password, get_dummy_secret());
return ExportedEncryptedKey{std::move(res.encrypted_data)};
}
td::Result<KeyStorage::Key> KeyStorage::import_encrypted_key(td::Slice local_password, td::Slice key_password,
ExportedEncryptedKey exported_key) {
EncryptedKey encrypted_key{std::move(exported_key.data), td::Ed25519::PublicKey(td::SecureString()),
td::SecureString(dummy_secret)};
get_dummy_secret()};
TRY_RESULT_PREFIX(decrypted_key, encrypted_key.decrypt(key_password, false), TonlibError::KeyDecrypt());
return save_key(std::move(decrypted_key), local_password);
}

View File

@ -25,6 +25,8 @@
#include "lite-client/lite-client-common.h"
#include "td/utils/JsonBuilder.h"
namespace tonlib {
// init_state <-> last_key_block
@ -313,6 +315,18 @@ 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;
VLOG(last_block) << "Update masterchain key block id: " << state_.last_key_block_id.to_str();
if (true) {
td::JsonBuilder jb;
auto jo = jb.enter_object();
jo("workchain", state_.last_key_block_id.id.workchain);
jo("shard", static_cast<td::int64>(state_.last_key_block_id.id.shard));
jo("seqno", static_cast<td::int32>(state_.last_key_block_id.id.seqno));
jo("root_hash", td::base64_encode(as_slice(state_.last_key_block_id.root_hash)));
jo("file_hash", td::base64_encode(as_slice(state_.last_key_block_id.file_hash)));
jo.leave();
LOG(INFO) << jb.string_builder().as_cslice();
}
//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());

View File

@ -32,10 +32,17 @@
namespace tonlib {
static std::mutex logging_mutex;
static td::FileLog file_log;
static td::TsLog ts_log(&file_log);
static td::NullLog null_log;
struct LogData {
std::mutex logging_mutex;
td::FileLog file_log;
td::TsLog ts_log{&file_log};
td::NullLog null_log;
};
auto &log_data() {
static LogData data;
return data;
}
#define ADD_TAG(tag) \
{ #tag, &VERBOSITY_NAME(tag) }
@ -48,7 +55,7 @@ td::Status Logging::set_current_stream(tonlib_api::object_ptr<tonlib_api::LogStr
return td::Status::Error("Log stream must not be empty");
}
std::lock_guard<std::mutex> lock(logging_mutex);
std::lock_guard<std::mutex> lock(log_data().logging_mutex);
switch (stream->get_id()) {
case tonlib_api::logStreamDefault::ID:
td::log_interface = td::default_log_interface;
@ -60,13 +67,13 @@ td::Status Logging::set_current_stream(tonlib_api::object_ptr<tonlib_api::LogStr
return td::Status::Error("Max log file size should be positive");
}
TRY_STATUS(file_log.init(file_stream->path_, max_log_file_size));
TRY_STATUS(log_data().file_log.init(file_stream->path_, max_log_file_size));
std::atomic_thread_fence(std::memory_order_release); // better than nothing
td::log_interface = &ts_log;
td::log_interface = &log_data().ts_log;
return td::Status::OK();
}
case tonlib_api::logStreamEmpty::ID:
td::log_interface = &null_log;
td::log_interface = &log_data().null_log;
return td::Status::OK();
default:
UNREACHABLE();
@ -75,22 +82,22 @@ td::Status Logging::set_current_stream(tonlib_api::object_ptr<tonlib_api::LogStr
}
td::Result<tonlib_api::object_ptr<tonlib_api::LogStream>> Logging::get_current_stream() {
std::lock_guard<std::mutex> lock(logging_mutex);
std::lock_guard<std::mutex> lock(log_data().logging_mutex);
if (td::log_interface == td::default_log_interface) {
return tonlib_api::make_object<tonlib_api::logStreamDefault>();
}
if (td::log_interface == &null_log) {
if (td::log_interface == &log_data().null_log) {
return tonlib_api::make_object<tonlib_api::logStreamEmpty>();
}
if (td::log_interface == &ts_log) {
return tonlib_api::make_object<tonlib_api::logStreamFile>(file_log.get_path().str(),
file_log.get_rotate_threshold());
if (td::log_interface == &log_data().ts_log) {
return tonlib_api::make_object<tonlib_api::logStreamFile>(log_data().file_log.get_path().str(),
log_data().file_log.get_rotate_threshold());
}
return td::Status::Error("Log stream is unrecognized");
}
td::Status Logging::set_verbosity_level(int new_verbosity_level) {
std::lock_guard<std::mutex> lock(logging_mutex);
std::lock_guard<std::mutex> lock(log_data().logging_mutex);
if (0 <= new_verbosity_level && new_verbosity_level <= VERBOSITY_NAME(NEVER)) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(FATAL) + new_verbosity_level);
return td::Status::OK();
@ -100,7 +107,7 @@ td::Status Logging::set_verbosity_level(int new_verbosity_level) {
}
int Logging::get_verbosity_level() {
std::lock_guard<std::mutex> lock(logging_mutex);
std::lock_guard<std::mutex> lock(log_data().logging_mutex);
return GET_VERBOSITY_LEVEL();
}
@ -114,7 +121,7 @@ td::Status Logging::set_tag_verbosity_level(td::Slice tag, int new_verbosity_lev
return td::Status::Error("Log tag is not found");
}
std::lock_guard<std::mutex> lock(logging_mutex);
std::lock_guard<std::mutex> lock(log_data().logging_mutex);
*it->second = td::clamp(new_verbosity_level, 1, VERBOSITY_NAME(NEVER));
return td::Status::OK();
}
@ -125,7 +132,7 @@ td::Result<int> Logging::get_tag_verbosity_level(td::Slice tag) {
return td::Status::Error("Log tag is not found");
}
std::lock_guard<std::mutex> lock(logging_mutex);
std::lock_guard<std::mutex> lock(log_data().logging_mutex);
return *it->second;
}

View File

@ -1,52 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tonlib/TestGiver.h"
#include "tonlib/utils.h"
#include "td/utils/base64.h"
namespace tonlib {
const block::StdAddress& TestGiver::address() noexcept {
static block::StdAddress res =
block::StdAddress::parse("kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny").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());
}
td::Ref<vm::Cell> TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message,
const block::StdAddress& dest_address) noexcept {
td::BigInt256 dest_addr;
dest_addr.import_bits(dest_address.addr.as_bitslice());
vm::CellBuilder cb;
cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok())
.store_long(dest_address.bounceable, 1)
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
.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).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();
}
} // namespace tonlib

View File

@ -1,31 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "block/block.h"
#include "CellString.h"
namespace tonlib {
class TestGiver {
public:
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<vm::Cell> make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message,
const block::StdAddress& dest_address) noexcept;
};
} // namespace tonlib

View File

@ -1,84 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tonlib/TestWallet.h"
#include "tonlib/GenericAccount.h"
#include "tonlib/utils.h"
#include "vm/boc.h"
#include "td/utils/base64.h"
namespace tonlib {
td::Ref<vm::Cell> 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<vm::Cell> 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<vm::Cell> 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::BigInt256 dest_addr;
dest_addr.import_bits(dest_address.addr.as_bitslice());
vm::CellBuilder cb;
cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok())
.store_long(dest_address.bounceable, 1)
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
.store_long(dest_address.workchain, 8)
.store_int256(dest_addr, 256);
td::int32 send_mode = 3;
if (gramms == -1) {
gramms = 0;
send_mode += 128;
}
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
cb.store_zeroes(9 + 64 + 32 + 1 + 1).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<vm::Cell> 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<vm::Cell> 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();
}
} // namespace tonlib

View File

@ -31,6 +31,7 @@
#include "smc-envelope/GenericAccount.h"
#include "smc-envelope/TestWallet.h"
#include "smc-envelope/Wallet.h"
#include "smc-envelope/WalletV3.h"
#include "smc-envelope/TestGiver.h"
#include "auto/tl/tonlib_api.hpp"
@ -41,6 +42,7 @@
#include "vm/boc.h"
#include "td/utils/as.h"
#include "td/utils/Random.h"
#include "td/utils/optional.h"
#include "td/utils/overloaded.h"
@ -101,6 +103,7 @@ struct RawAccountState {
td::Ref<vm::Cell> code;
td::Ref<vm::Cell> data;
td::Ref<vm::Cell> state;
std::string frozen_hash;
block::AccountState::Info info;
};
@ -114,9 +117,14 @@ tonlib_api::object_ptr<tonlib_api::internal_transactionId> to_transaction_id(con
info.last_trans_hash.as_slice().str());
}
std::string to_bytes(td::Ref<vm::Cell> cell) {
return vm::std_boc_serialize(cell, vm::BagOfCells::Mode::WithCRC32C).move_as_ok().as_slice().str();
}
class AccountState {
public:
AccountState(block::StdAddress address, RawAccountState&& raw) : address_(std::move(address)), raw_(std::move(raw)) {
AccountState(block::StdAddress address, RawAccountState&& raw, td::uint32 wallet_id)
: address_(std::move(address)), raw_(std::move(raw)), wallet_id_(wallet_id) {
wallet_type_ = guess_type();
}
@ -129,11 +137,11 @@ class AccountState {
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();
code = to_bytes(state.code);
}
std::string data;
if (state.data.not_null()) {
data = vm::std_boc_serialize(state.data).move_as_ok().as_slice().str();
data = to_bytes(state.data);
}
return tonlib_api::make_object<tonlib_api::raw_accountState>(get_balance(), std::move(code), std::move(data),
to_transaction_id(raw().info), raw().frozen_hash,
@ -157,6 +165,17 @@ class AccountState {
return tonlib_api::make_object<tonlib_api::wallet_accountState>(get_balance(), static_cast<td::uint32>(seqno),
to_transaction_id(raw().info), get_sync_time());
}
td::Result<tonlib_api::object_ptr<tonlib_api::wallet_v3_accountState>> to_wallet_v3_accountState() const {
if (wallet_type_ != WalletV3) {
return TonlibError::AccountTypeUnexpected("WalletV3");
}
auto wallet = ton::WalletV3(get_smc_state());
TRY_RESULT(seqno, wallet.get_seqno());
TRY_RESULT(wallet_id, wallet.get_wallet_id());
return tonlib_api::make_object<tonlib_api::wallet_v3_accountState>(
get_balance(), static_cast<td::uint32>(wallet_id), static_cast<td::uint32>(seqno),
to_transaction_id(raw().info), get_sync_time());
}
td::Result<tonlib_api::object_ptr<tonlib_api::testGiver_accountState>> to_testGiver_accountState() const {
if (wallet_type_ != Giver) {
@ -186,11 +205,15 @@ class AccountState {
TRY_RESULT(res, to_wallet_accountState());
return tonlib_api::make_object<tonlib_api::generic_accountStateWallet>(std::move(res));
}
case WalletV3: {
TRY_RESULT(res, to_wallet_v3_accountState());
return tonlib_api::make_object<tonlib_api::generic_accountStateWalletV3>(std::move(res));
}
}
UNREACHABLE();
}
enum WalletType { Empty, Unknown, Giver, SimpleWallet, Wallet };
enum WalletType { Empty, Unknown, Giver, SimpleWallet, Wallet, WalletV3 };
WalletType get_wallet_type() const {
return wallet_type_;
}
@ -230,6 +253,10 @@ class AccountState {
address_.addr) {
set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)});
wallet_type_ = WalletType::Wallet;
} else if (ton::GenericAccount::get_address(address_.workchain, ton::WalletV3::get_init_state(key, wallet_id_))
.addr == address_.addr) {
set_new_state({ton::WalletV3::get_init_code(), ton::WalletV3::get_init_data(key, wallet_id_)});
wallet_type_ = WalletType::WalletV3;
}
return wallet_type_;
}
@ -238,8 +265,8 @@ class AccountState {
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;
set_new_state({ton::WalletV3::get_init_code(), ton::WalletV3::get_init_data(key, wallet_id_)});
wallet_type_ = WalletType::WalletV3;
return wallet_type_;
}
@ -247,9 +274,14 @@ class AccountState {
return {raw_.code, raw_.data};
}
td::Ref<vm::Cell> get_raw_state() {
return raw_.state;
}
void set_new_state(ton::SmartContract::State state) {
raw_.code = std::move(state.code);
raw_.data = std::move(state.data);
raw_.state = ton::GenericAccount::get_init_state(raw_.code, raw_.data);
has_new_state_ = true;
}
@ -257,13 +289,14 @@ class AccountState {
if (!has_new_state_) {
return {};
}
return ton::GenericAccount::get_init_state(raw_.code, raw_.data);
return raw_.state;
}
private:
block::StdAddress address_;
RawAccountState raw_;
WalletType wallet_type_{Unknown};
td::uint32 wallet_id_{0};
bool has_new_state_{false};
WalletType guess_type() const {
@ -280,6 +313,9 @@ class AccountState {
if (code_hash == ton::Wallet::get_init_code_hash()) {
return WalletType::Wallet;
}
if (code_hash == ton::WalletV3::get_init_code_hash()) {
return WalletType::WalletV3;
}
LOG(WARNING) << "Unknown code hash: " << td::base64_encode(code_hash.as_slice());
return WalletType::Unknown;
}
@ -717,12 +753,12 @@ class GetRawAccountState : public td::actor::Actor {
return td::Status::Error("Failed to parse AccountState");
}
block::gen::StateInit::Record state_init;
res.state = vm::CellBuilder().append_cellslice(state.x).finalize();
if (!tlb::csr_unpack(state.x, state_init)) {
return td::Status::Error("Failed to parse StateInit");
}
state_init.code->prefetch_maybe_ref(res.code);
state_init.data->prefetch_maybe_ref(res.data);
return res;
}
@ -788,18 +824,22 @@ void TonlibClient::init_ext_client() {
if (use_callbacks_for_network_) {
class Callback : public ExtClientOutbound::Callback {
public:
explicit Callback(td::actor::ActorShared<TonlibClient> parent) : parent_(std::move(parent)) {
explicit Callback(td::actor::ActorShared<TonlibClient> parent, td::uint32 config_generation)
: parent_(std::move(parent)), config_generation_(config_generation) {
}
void request(td::int64 id, std::string data) override {
send_closure(parent_, &TonlibClient::proxy_request, id, std::move(data));
send_closure(parent_, &TonlibClient::proxy_request, (id << 16) | (config_generation_ & 0xffff),
std::move(data));
}
private:
td::actor::ActorShared<TonlibClient> parent_;
td::uint32 config_generation_;
};
ref_cnt_++;
auto client = ExtClientOutbound::create(td::make_unique<Callback>(td::actor::actor_shared(this)));
auto client =
ExtClientOutbound::create(td::make_unique<Callback>(td::actor::actor_shared(this), config_generation_));
ext_client_outbound_ = client.get();
raw_client_ = std::move(client);
} else {
@ -826,6 +866,7 @@ void TonlibClient::update_last_block_state(LastBlockState state, td::uint32 conf
if (config_generation != config_generation_) {
return;
}
last_block_storage_.save_state(blockchain_name_, state);
}
@ -848,7 +889,7 @@ void TonlibClient::update_sync_state(LastBlockSyncState state, td::uint32 config
}
}
void TonlibClient::init_last_block() {
void TonlibClient::init_last_block(td::optional<Config> o_master_config) {
ref_cnt_++;
class Callback : public LastBlock::Callback {
public:
@ -883,6 +924,15 @@ void TonlibClient::init_last_block() {
state = r_state.move_as_ok();
}
if (o_master_config) {
auto master_config = o_master_config.unwrap();
if (master_config.init_block_id.is_valid() &&
state.last_key_block_id.id.seqno < master_config.init_block_id.id.seqno) {
state.last_key_block_id = master_config.init_block_id;
LOG(INFO) << "Use init block from MASTER config: " << master_config.init_block_id.to_str();
}
}
raw_last_block_ = td::actor::create_actor<LastBlock>(
td::actor::ActorOptions().with_name("LastBlock").with_poll(false), get_client_ref(), std::move(state), config_,
source_.get_cancellation_token(), td::make_unique<Callback>(td::actor::actor_shared(this), config_generation_));
@ -975,9 +1025,11 @@ bool TonlibClient::is_static_request(td::int32 id) {
case tonlib_api::raw_getAccountAddress::ID:
case tonlib_api::testWallet_getAccountAddress::ID:
case tonlib_api::wallet_getAccountAddress::ID:
case tonlib_api::wallet_v3_getAccountAddress::ID:
case tonlib_api::testGiver_getAccountAddress::ID:
case tonlib_api::packAccountAddress::ID:
case tonlib_api::unpackAccountAddress::ID:
case tonlib_api::options_validateConfig::ID:
case tonlib_api::getBip39Hints::ID:
case tonlib_api::setLogStream::ID:
case tonlib_api::getLogStream::ID:
@ -1037,6 +1089,12 @@ td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_initi
auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key));
return ton::GenericAccount::get_address(0 /*zerochain*/, ton::Wallet::get_init_state(key));
}
td::Result<block::StdAddress> get_account_address(const tonlib_api::wallet_v3_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 ton::GenericAccount::get_address(
0 /*zerochain*/, ton::WalletV3::get_init_state(key, static_cast<td::uint32>(test_wallet_state.wallet_id_)));
}
td::Result<block::StdAddress> get_account_address(td::Slice account_address) {
TRY_RESULT_PREFIX(address, block::StdAddress::parse(account_address), TonlibError::InvalidAccountAddress());
@ -1045,6 +1103,9 @@ td::Result<block::StdAddress> get_account_address(td::Slice account_address) {
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::raw_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
@ -1054,6 +1115,12 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::testWallet_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
@ -1063,6 +1130,20 @@ tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::wallet_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
}
return tonlib_api::make_object<tonlib_api::accountAddress>(r_account_address.ok().rserialize(true));
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
const tonlib_api::wallet_v3_getAccountAddress& request) {
if (!request.initital_account_state_) {
return status_to_tonlib_api(TonlibError::EmptyField("initial_account_state"));
}
auto r_account_address = get_account_address(*request.initital_account_state_);
if (r_account_address.is_error()) {
return status_to_tonlib_api(r_account_address.error());
@ -1132,37 +1213,114 @@ td::Status TonlibClient::do_request(const tonlib_api::init& request,
key_storage_.set_key_value(kv_);
last_block_storage_.set_key_value(kv_);
if (request.options_->config_) {
TRY_STATUS(set_config(std::move(request.options_->config_)));
TRY_RESULT(full_config, validate_config(std::move(request.options_->config_)));
set_config(std::move(full_config));
}
state_ = State::Running;
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
return td::Status::OK();
}
td::Status TonlibClient::set_config(object_ptr<tonlib_api::config> config) {
CHECK(config);
class MasterConfig {
public:
void add_config(std::string name, std::string json) {
auto config = std::make_shared<Config>(Config::parse(json).move_as_ok());
if (!name.empty()) {
by_name_[name] = config;
}
by_root_hash_[config->zero_state_id.root_hash] = config;
}
td::optional<Config> by_name(std::string name) const {
auto it = by_name_.find(name);
if (it == by_name_.end()) {
return {};
}
return *it->second;
}
td::optional<Config> by_root_hash(const ton::RootHash& root_hash) const {
auto it = by_root_hash_.find(root_hash);
if (it == by_root_hash_.end()) {
return {};
}
return *it->second;
}
private:
size_t next_id_{0};
std::map<std::string, std::shared_ptr<const Config>> by_name_;
std::map<ton::RootHash, std::shared_ptr<const Config>> by_root_hash_;
};
const MasterConfig& get_default_master_config() {
static MasterConfig config = [] {
MasterConfig res;
res.add_config("testnet", R"abc({
"liteservers": [
],
"validator": {
"@type": "validator.config.global",
"zero_state": {
"workchain": -1,
"shard": -9223372036854775808,
"seqno": 0,
"root_hash": "VCSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=",
"file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo="
},
"init_block":
{"workchain":-1,"shard":-9223372036854775808,"seqno":870721,"root_hash":"jYKhSQ1xeSPprzgjqiUOnAWwc2yqs7nCVAU21k922s4=","file_hash":"kHidF02CZpaz2ia9jtXUJLp0AiWMWwfzprTUIsddHSo="}
}
})abc");
return res;
}();
return config;
}
td::Result<TonlibClient::FullConfig> TonlibClient::validate_config(tonlib_api::object_ptr<tonlib_api::config> config) {
if (!config) {
return TonlibError::EmptyField("config");
}
if (config->config_.empty()) {
return TonlibError::InvalidConfig("config is empty");
}
TRY_RESULT_PREFIX(new_config, Config::parse(std::move(config->config_)),
TonlibError::InvalidConfig("can't parse config"));
if (new_config.lite_clients.empty() && !config->use_callbacks_for_network_) {
return TonlibError::InvalidConfig("no lite clients");
}
config_ = std::move(new_config);
config_generation_++;
td::optional<Config> o_master_config;
if (config->blockchain_name_.empty()) {
blockchain_name_ = td::sha256(config_.zero_state_id.to_str()).substr(0, 16);
o_master_config = get_default_master_config().by_root_hash(new_config.zero_state_id.root_hash);
} else {
blockchain_name_ = config->blockchain_name_;
o_master_config = get_default_master_config().by_name(config->blockchain_name_);
}
use_callbacks_for_network_ = config->use_callbacks_for_network_;
ignore_cache_ = config->ignore_cache_;
if (o_master_config && o_master_config.value().zero_state_id != new_config.zero_state_id) {
return TonlibError::InvalidConfig("zero_state differs from embedded zero_state");
}
FullConfig res;
res.config = std::move(new_config);
res.o_master_config = std::move(o_master_config);
res.ignore_cache = config->ignore_cache_;
res.use_callbacks_for_network = config->use_callbacks_for_network_;
res.wallet_id = td::as<td::uint32>(res.config.zero_state_id.root_hash.as_slice().data());
return std::move(res);
}
void TonlibClient::set_config(FullConfig full_config) {
config_ = std::move(full_config.config);
config_generation_++;
wallet_id_ = full_config.wallet_id;
blockchain_name_ = config_.zero_state_id.root_hash.as_slice().str();
use_callbacks_for_network_ = full_config.use_callbacks_for_network;
ignore_cache_ = full_config.ignore_cache;
init_ext_client();
init_last_block();
init_last_block(std::move(full_config.o_master_config));
init_last_config();
client_.set_client(get_client_ref());
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::close& request,
@ -1174,12 +1332,22 @@ td::Status TonlibClient::do_request(const tonlib_api::close& request,
return td::Status::OK();
}
tonlib_api::object_ptr<tonlib_api::Object> TonlibClient::do_static_request(
tonlib_api::options_validateConfig& request) {
auto r_config = validate_config(std::move(request.config_));
if (r_config.is_error()) {
return status_to_tonlib_api(r_config.move_as_error());
}
return tonlib_api::make_object<tonlib_api::options_configInfo>(r_config.ok().wallet_id);
}
td::Status TonlibClient::do_request(tonlib_api::options_setConfig& request,
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
if (!request.config_) {
return TonlibError::EmptyField("config");
}
TRY_STATUS(set_config(std::move(request.config_)));
TRY_RESULT(config, validate_config(std::move(request.config_)));
set_config(std::move(config));
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
return td::Status::OK();
}
@ -1290,8 +1458,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_transaction>> to_raw_transacti
td::int64 fees = 0;
td::int64 storage_fee = 0;
if (info.transaction.not_null()) {
TRY_RESULT(copy_data, vm::std_boc_serialize(info.transaction));
data = copy_data.as_slice().str();
data = to_bytes(info.transaction);
block::gen::Transaction::Record trans;
if (!tlb::unpack_cell(info.transaction, trans)) {
return td::Status::Error("Failed to unpack Transaction");
@ -1425,7 +1592,7 @@ td::Status TonlibClient::do_request(tonlib_api::raw_getTransactions& request,
promise.wrap(to_raw_transactions));
return td::Status::OK();
}
td::Result<KeyStorage::InputKey> from_tonlib(tonlib_api::inputKey& input_key) {
td::Result<KeyStorage::InputKey> from_tonlib(tonlib_api::inputKeyRegular& input_key) {
if (!input_key.key_) {
return TonlibError::EmptyField("key");
}
@ -1437,9 +1604,9 @@ td::Result<KeyStorage::InputKey> from_tonlib(tonlib_api::inputKey& input_key) {
td::Result<KeyStorage::InputKey> from_tonlib(tonlib_api::InputKey& input_key) {
td::Result<KeyStorage::InputKey> 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(); }));
tonlib_api::downcast_call(
input_key, td::overloaded([&](tonlib_api::inputKeyRegular& input_key) { r_key = from_tonlib(input_key); },
[&](tonlib_api::inputKeyFake&) { r_key = KeyStorage::fake_input_key(); }));
return r_key;
}
@ -1666,18 +1833,15 @@ class GenericCreateSendGrams : public TonlibQueryActor {
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::GetPrivateKey{std::move(input_key)},
promise_send_closure(actor_id(this), &GenericCreateSendGrams::on_private_key));
}
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{source_address},
promise_send_closure(actor_id(this), &GenericCreateSendGrams::on_source_state));
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));
});
send_query(int_api::GetAccountState{destination_address},
promise_send_closure(actor_id(this), &GenericCreateSendGrams::on_destination_state));
return do_loop();
}
@ -1787,6 +1951,23 @@ class GenericCreateSendGrams : public TonlibQueryActor {
destination_->get_address());
break;
}
case AccountState::WalletV3: {
if (!private_key_) {
return TonlibError::EmptyField("private_key");
}
if (message.size() > ton::WalletV3::max_message_size) {
return TonlibError::MessageTooLong();
}
auto wallet = ton::WalletV3(source_->get_smc_state());
TRY_RESULT(seqno, wallet.get_seqno());
TRY_RESULT(wallet_id, wallet.get_wallet_id());
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::WalletV3::make_a_gift_message(private_key_.unwrap(), wallet_id, seqno, valid_until,
amount, message, destination_->get_address());
break;
}
}
raw.new_state = source_->get_new_state();
@ -1835,9 +2016,7 @@ td::Status TonlibClient::do_request(tonlib_api::generic_createSendGramsQuery& re
auto id = actor_id_++;
actors_[id] = td::actor::create_actor<GenericCreateSendGrams>(
"GenericSendGrams", actor_shared(this, id), std::move(request),
[promise = std::move(promise), self = actor_id(this)](td::Result<td::unique_ptr<Query>> r_query) mutable {
send_closure(self, &TonlibClient::finish_create_query, std::move(r_query), std::move(promise));
});
promise.send_closure(actor_id(this), &TonlibClient::finish_create_query));
return td::Status::OK();
}
@ -1857,9 +2036,7 @@ td::Status TonlibClient::do_request(const tonlib_api::raw_createQuery& request,
TRY_RESULT_PREFIX(body, vm::std_boc_deserialize(request.body_), TonlibError::InvalidBagOfCells("body"));
td::Promise<td::unique_ptr<Query>> new_promise =
[promise = std::move(promise), self = actor_id(this)](td::Result<td::unique_ptr<Query>> r_query) mutable {
send_closure(self, &TonlibClient::finish_create_query, std::move(r_query), std::move(promise));
};
promise.send_closure(actor_id(this), &TonlibClient::finish_create_query);
make_request(int_api::GetAccountState{account_address},
new_promise.wrap([smc_state = std::move(smc_state), body = std::move(body)](auto&& source) mutable {
@ -1886,9 +2063,7 @@ td::Status TonlibClient::do_request(tonlib_api::generic_sendGrams& request,
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<td::unique_ptr<Query>> r_query) mutable {
send_closure(self, &TonlibClient::finish_send_query, std::move(r_query), std::move(promise));
});
promise.send_closure(actor_id(this), &TonlibClient::finish_send_query));
return td::Status::OK();
}
@ -1953,6 +2128,151 @@ td::Status TonlibClient::do_request(tonlib_api::query_forget& request,
return td::Status::OK();
}
td::int64 TonlibClient::register_smc(td::unique_ptr<AccountState> smc) {
auto smc_id = ++next_smc_id_;
smcs_[smc_id] = std::move(smc);
return smc_id;
}
td::Result<tonlib_api::object_ptr<tonlib_api::smc_info>> TonlibClient::get_smc_info(td::int64 id) {
auto it = smcs_.find(id);
if (it == smcs_.end()) {
return TonlibError::InvalidSmcId();
}
return tonlib_api::make_object<tonlib_api::smc_info>(id);
}
void TonlibClient::finish_load_smc(td::unique_ptr<AccountState> smc,
td::Promise<object_ptr<tonlib_api::smc_info>>&& promise) {
auto id = register_smc(std::move(smc));
promise.set_result(get_smc_info(id));
}
td::Status TonlibClient::do_request(const tonlib_api::smc_load& request,
td::Promise<object_ptr<tonlib_api::smc_info>>&& promise) {
if (!request.account_address_) {
return TonlibError::EmptyField("account_address");
}
TRY_RESULT(account_address, get_account_address(request.account_address_->account_address_));
make_request(int_api::GetAccountState{std::move(account_address)},
promise.send_closure(actor_id(this), &TonlibClient::finish_load_smc));
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::smc_getCode& request,
td::Promise<object_ptr<tonlib_api::tvm_cell>>&& promise) {
auto it = smcs_.find(request.id_);
if (it == smcs_.end()) {
return TonlibError::InvalidSmcId();
}
auto& acc = it->second;
auto code = acc->get_smc_state().code;
promise.set_value(tonlib_api::make_object<tonlib_api::tvm_cell>(to_bytes(code)));
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::smc_getData& request,
td::Promise<object_ptr<tonlib_api::tvm_cell>>&& promise) {
auto it = smcs_.find(request.id_);
if (it == smcs_.end()) {
return TonlibError::InvalidSmcId();
}
auto& acc = it->second;
auto data = acc->get_smc_state().data;
promise.set_value(tonlib_api::make_object<tonlib_api::tvm_cell>(to_bytes(data)));
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::smc_getState& request,
td::Promise<object_ptr<tonlib_api::tvm_cell>>&& promise) {
auto it = smcs_.find(request.id_);
if (it == smcs_.end()) {
return TonlibError::InvalidSmcId();
}
auto& acc = it->second;
auto data = acc->get_raw_state();
promise.set_value(tonlib_api::make_object<tonlib_api::tvm_cell>(to_bytes(data)));
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::smc_runGetMethod& request,
td::Promise<object_ptr<tonlib_api::smc_runResult>>&& promise) {
auto it = smcs_.find(request.id_);
if (it == smcs_.end()) {
return TonlibError::InvalidSmcId();
}
td::Ref<ton::SmartContract> smc(true, it->second->get_smc_state());
ton::SmartContract::Args args;
downcast_call(*request.method_,
td::overloaded([&](tonlib_api::smc_methodIdNumber& number) { args.set_method_id(number.number_); },
[&](tonlib_api::smc_methodIdName& name) { args.set_method_id(name.name_); }));
td::Ref<vm::Stack> stack(true);
td::Status status;
// TODO: error codes
// downcast_call
for (auto& entry : request.stack_) {
downcast_call(*entry, td::overloaded(
[&](tonlib_api::tvm_stackEntryUnsupported& cell) {
status = td::Status::Error("Unsuppored stack entry");
},
[&](tonlib_api::tvm_stackEntrySlice& cell) {
auto r_cell = vm::std_boc_deserialize(cell.slice_->bytes_);
if (r_cell.is_error()) {
status = r_cell.move_as_error();
return;
}
stack.write().push_cell(r_cell.move_as_ok());
},
[&](tonlib_api::tvm_stackEntryCell& cell) {
auto r_cell = vm::std_boc_deserialize(cell.cell_->bytes_);
if (r_cell.is_error()) {
status = r_cell.move_as_error();
return;
}
stack.write().push_cell(r_cell.move_as_ok());
},
[&](tonlib_api::tvm_stackEntryNumber& number) {
[&](tonlib_api::tvm_numberDecimal& dec) {
auto num = td::dec_string_to_int256(dec.number_);
if (num.is_null()) {
status = td::Status::Error("Failed to parse dec string to int256");
return;
}
stack.write().push_int(std::move(num));
}(*number.number_);
}));
}
TRY_STATUS(std::move(status));
args.set_stack(std::move(stack));
auto res = smc->run_get_method(std::move(args));
// smc.runResult gas_used:int53 stack:vector<tvm.StackEntry> exit_code:int32 = smc.RunResult;
std::vector<object_ptr<tonlib_api::tvm_StackEntry>> res_stack;
for (auto& entry : res.stack->as_span()) {
switch (entry.type()) {
case vm::StackEntry::Type::t_int:
res_stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryNumber>(
tonlib_api::make_object<tonlib_api::tvm_numberDecimal>(dec_string(entry.as_int()))));
break;
case vm::StackEntry::Type::t_slice:
res_stack.push_back(
tonlib_api::make_object<tonlib_api::tvm_stackEntryCell>(tonlib_api::make_object<tonlib_api::tvm_cell>(
to_bytes(vm::CellBuilder().append_cellslice(entry.as_slice()).finalize()))));
break;
case vm::StackEntry::Type::t_cell:
res_stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryCell>(
tonlib_api::make_object<tonlib_api::tvm_cell>(to_bytes(entry.as_cell()))));
break;
default:
res_stack.push_back(tonlib_api::make_object<tonlib_api::tvm_stackEntryUnsupported>());
break;
}
}
promise.set_value(tonlib_api::make_object<tonlib_api::smc_runResult>(res.gas_used, std::move(res_stack), res.code));
return td::Status::OK();
}
td::Status TonlibClient::do_request(tonlib_api::sync& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
client_.with_last_block(to_any_promise(std::move(promise)));
return td::Status::OK();
@ -2079,13 +2399,25 @@ td::Status TonlibClient::do_request(const tonlib_api::changeLocalPassword& reque
td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryResult& request,
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_, td::BufferSlice(request.bytes_),
to_any_promise(std::move(promise)));
if (ext_client_outbound_.empty()) {
return TonlibError::InvalidQueryId();
}
if (((request.id_ ^ config_generation_) & 0xffff) != 0) {
return TonlibError::InvalidQueryId();
}
send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_ >> 16,
td::BufferSlice(request.bytes_), to_any_promise(std::move(promise)));
return td::Status::OK();
}
td::Status TonlibClient::do_request(const tonlib_api::onLiteServerQueryError& request,
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_,
if (ext_client_outbound_.empty()) {
return TonlibError::InvalidQueryId();
}
if (((request.id_ ^ config_generation_) & 0xffff) != 0) {
return TonlibError::InvalidQueryId();
}
send_closure(ext_client_outbound_, &ExtClientOutbound::on_query_result, request.id_ >> 16,
td::Status::Error(request.error_->code_, request.error_->message_)
.move_as_error_prefix(TonlibError::LiteServerNetwork()),
to_any_promise(std::move(promise)));
@ -2176,8 +2508,8 @@ td::Status TonlibClient::do_request(int_api::GetAccountState request,
auto actor_id = actor_id_++;
actors_[actor_id] = td::actor::create_actor<GetRawAccountState>(
"GetAccountState", client_.get_client(), request.address, actor_shared(this, actor_id),
promise.wrap([address = request.address](auto&& state) mutable {
return td::make_unique<AccountState>(std::move(address), std::move(state));
promise.wrap([address = request.address, wallet_id = wallet_id_](auto&& state) mutable {
return td::make_unique<AccountState>(std::move(address), std::move(state), wallet_id);
}));
return td::Status::OK();
}
@ -2224,6 +2556,11 @@ td::Status TonlibClient::do_request(const tonlib_api::wallet_getAccountAddress&
return TonlibError::Internal();
}
template <class P>
td::Status TonlibClient::do_request(const tonlib_api::wallet_v3_getAccountAddress& request, P&&) {
UNREACHABLE();
return TonlibError::Internal();
}
template <class P>
td::Status TonlibClient::do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&) {
UNREACHABLE();
return TonlibError::Internal();
@ -2239,6 +2576,11 @@ td::Status TonlibClient::do_request(const tonlib_api::unpackAccountAddress& requ
return TonlibError::Internal();
}
template <class P>
td::Status TonlibClient::do_request(const tonlib_api::options_validateConfig& request, P&&) {
UNREACHABLE();
return TonlibError::Internal();
}
template <class P>
td::Status TonlibClient::do_request(tonlib_api::getBip39Hints& request, P&&) {
UNREACHABLE();
return TonlibError::Internal();

View File

@ -30,6 +30,7 @@
#include "td/actor/actor.h"
#include "td/utils/CancellationToken.h"
#include "td/utils/optional.h"
#include <map>
@ -64,6 +65,7 @@ class TonlibClient : public td::actor::Actor {
// Config
Config config_;
td::uint32 config_generation_{0};
td::uint32 wallet_id_;
std::string blockchain_name_;
bool ignore_cache_{false};
bool use_callbacks_for_network_{false};
@ -87,7 +89,7 @@ class TonlibClient : public td::actor::Actor {
ExtClientRef get_client_ref();
void init_ext_client();
void init_last_block();
void init_last_block(td::optional<Config> o_master_config);
void init_last_config();
bool is_closing_{false};
@ -122,9 +124,11 @@ class TonlibClient : public td::actor::Actor {
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::raw_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testWallet_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::wallet_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::wallet_v3_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::testGiver_getAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::packAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(const tonlib_api::unpackAccountAddress& request);
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::options_validateConfig& request);
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::getBip39Hints& request);
static object_ptr<tonlib_api::Object> do_static_request(tonlib_api::setLogStream& request);
@ -149,12 +153,16 @@ class TonlibClient : public td::actor::Actor {
template <class P>
td::Status do_request(const tonlib_api::wallet_getAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::wallet_v3_getAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::testGiver_getAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::packAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::unpackAccountAddress& request, P&&);
template <class P>
td::Status do_request(const tonlib_api::options_validateConfig& request, P&&);
template <class P>
td::Status do_request(tonlib_api::getBip39Hints& request, P&&);
template <class P>
@ -189,7 +197,15 @@ class TonlibClient : public td::actor::Actor {
}
}
td::Status set_config(object_ptr<tonlib_api::config> config);
struct FullConfig {
Config config;
td::optional<Config> o_master_config;
bool use_callbacks_for_network;
bool ignore_cache;
td::uint32 wallet_id;
};
static td::Result<FullConfig> validate_config(tonlib_api::object_ptr<tonlib_api::config> config);
void set_config(FullConfig config);
td::Status do_request(const tonlib_api::init& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
td::Status do_request(const tonlib_api::close& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
td::Status do_request(tonlib_api::options_setConfig& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
@ -274,6 +290,23 @@ class TonlibClient : public td::actor::Actor {
td::Status do_request(tonlib_api::generic_createSendGramsQuery& request,
td::Promise<object_ptr<tonlib_api::query_info>>&& promise);
td::int64 next_smc_id_{0};
std::map<td::int64, td::unique_ptr<AccountState>> smcs_;
td::int64 register_smc(td::unique_ptr<AccountState> smc);
td::Result<tonlib_api::object_ptr<tonlib_api::smc_info>> get_smc_info(td::int64 id);
void finish_load_smc(td::unique_ptr<AccountState> query, td::Promise<object_ptr<tonlib_api::smc_info>>&& promise);
td::Status do_request(const tonlib_api::smc_load& request, td::Promise<object_ptr<tonlib_api::smc_info>>&& promise);
td::Status do_request(const tonlib_api::smc_getCode& request,
td::Promise<object_ptr<tonlib_api::tvm_cell>>&& promise);
td::Status do_request(const tonlib_api::smc_getData& request,
td::Promise<object_ptr<tonlib_api::tvm_cell>>&& promise);
td::Status do_request(const tonlib_api::smc_getState& request,
td::Promise<object_ptr<tonlib_api::tvm_cell>>&& promise);
td::Status do_request(const tonlib_api::smc_runGetMethod& request,
td::Promise<object_ptr<tonlib_api::smc_runResult>>&& promise);
td::Status do_request(int_api::GetAccountState request, td::Promise<td::unique_ptr<AccountState>>&&);
td::Status do_request(int_api::GetPrivateKey request, td::Promise<KeyStorage::PrivateKey>&&);
td::Status do_request(int_api::SendMessage request, td::Promise<td::Unit>&& promise);

View File

@ -28,6 +28,7 @@
// INVALID_BAG_OF_CELLS
// INVALID_PUBLIC_KEY
// INVALID_QUERY_ID
// INVALID_SMC_ID
// INVALID_ACCOUNT_ADDRESS
// INVALID_CONFIG
// INVALID_PEM_KEY
@ -69,12 +70,18 @@ struct TonlibError {
static td::Status InvalidQueryId() {
return td::Status::Error(400, "INVALID_QUERY_ID");
}
static td::Status InvalidSmcId() {
return td::Status::Error(400, "INVALID_SMC_ID");
}
static td::Status InvalidConfig(td::Slice reason) {
return td::Status::Error(400, PSLICE() << "INVALID_CONFIG: " << reason);
}
static td::Status InvalidPemKey() {
return td::Status::Error(400, "INVALID_PEM_KEY");
}
static td::Status NeedConfig() {
return td::Status::Error(400, "NeedConfig");
}
static td::Status MessageTooLong() {
return td::Status::Error(400, "MESSAGE_TOO_LONG");
}

View File

@ -1,95 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "tonlib/Wallet.h"
#include "tonlib/CellString.h"
#include "tonlib/GenericAccount.h"
#include "tonlib/utils.h"
#include "vm/boc.h"
#include "td/utils/base64.h"
#include <limits>
namespace tonlib {
td::Ref<vm::Cell> 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<vm::Cell> Wallet::get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept {
td::uint32 seqno = 0;
td::uint32 valid_until = std::numeric_limits<td::uint32>::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<vm::Cell> 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::BigInt256 dest_addr;
dest_addr.import_bits(dest_address.addr.as_bitslice());
vm::CellBuilder cb;
cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok())
.store_long(dest_address.bounceable, 1)
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
.store_long(dest_address.workchain, 8)
.store_int256(dest_addr, 256);
td::int32 send_mode = 3;
if (gramms == -1) {
gramms = 0;
send_mode += 128;
}
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
cb.store_zeroes(9 + 64 + 32 + 1 + 1).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();
std::string seq_no(4, 0);
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<vm::Cell> 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<vm::Cell> 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();
}
} // namespace tonlib

View File

@ -1,40 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include "vm/cells.h"
#include "Ed25519.h"
#include "block/block.h"
#include "CellString.h"
namespace tonlib {
class Wallet {
public:
static constexpr unsigned max_message_size = vm::CellString::max_bytes;
static td::Ref<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key) noexcept;
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept;
static td::Ref<vm::Cell> 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<vm::Cell> get_init_code() noexcept;
static vm::CellHash get_init_code_hash() noexcept;
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key) noexcept;
};
} // namespace tonlib

View File

@ -29,20 +29,21 @@
// "help [<command>]\tThis help\n" // TODO: support [<command>]
// "quit\tExit\n";
// "sendfile <filename>\tLoad a serialized message from <filename> and send it to server\n"
//
// "saveaccount[code|data] <filename> <addr> [<block-id-ext>]\tSaves into specified file the most recent state "
// "(StateInit) or just the code or data of specified account; <addr> is in "
// "[<workchain>:]<hex-or-base64-addr> format\n"
//
// "runmethod <addr> <method-id> <params>...\tRuns GET method <method-id> of account <addr> "
// "with specified parameters\n"
//
// "getaccount <addr> [<block-id-ext>]\tLoads the most recent state of specified account; <addr> is in "
// "[<workchain>:]<hex-or-base64-addr> format\n"
//
// WONTSUPPORT
//
// UNSUPPORTED
//"last\tGet last block and state info from server\n"
//"status\tShow connection and local database status\n"
//"getaccount <addr> [<block-id-ext>]\tLoads the most recent state of specified account; <addr> is in "
//"[<workchain>:]<hex-or-base64-addr> format\n"
//"(StateInit) or just the code or data of specified account; <addr> is in "
//"[<workchain>:]<hex-or-base64-addr> format\n"
//"allshards [<block-id-ext>]\tShows shard configuration from the most recent masterchain "
//"state or from masterchain state corresponding to <block-id-ext>\n"
//"getconfig [<param>...]\tShows specified or all configuration parameters from the latest masterchain state\n"
@ -80,7 +81,7 @@ class TonlibCli : public td::actor::Actor {
std::string key_dir{"."};
bool in_memory{false};
bool use_callbacks_for_network{false};
bool use_simple_wallet{false};
td::int32 wallet_version = 2;
bool ignore_cache{false};
bool one_shot{false};
@ -95,6 +96,7 @@ class TonlibCli : public td::actor::Actor {
td::actor::ActorOwn<tonlib::TonlibClient> client_;
std::uint64_t next_query_id_{1};
td::Promise<td::Slice> cont_;
td::uint32 wallet_id_;
struct KeyInfo {
std::string public_key;
@ -175,6 +177,10 @@ class TonlibCli : public td::actor::Actor {
? make_object<tonlib_api::config>(options_.config, options_.name,
options_.use_callbacks_for_network, options_.ignore_cache)
: nullptr;
auto config2 = !options_.config.empty()
? make_object<tonlib_api::config>(options_.config, options_.name,
options_.use_callbacks_for_network, options_.ignore_cache)
: nullptr;
tonlib_api::object_ptr<tonlib_api::KeyStoreType> ks_type;
if (options_.in_memory) {
@ -182,6 +188,14 @@ class TonlibCli : public td::actor::Actor {
} else {
ks_type = make_object<tonlib_api::keyStoreTypeDirectory>(options_.key_dir);
}
auto obj =
tonlib::TonlibClient::static_request(make_object<tonlib_api::options_validateConfig>(std::move(config2)));
if (obj->get_id() != tonlib_api::error::ID) {
auto info = ton::move_tl_object_as<tonlib_api::options_configInfo>(obj);
wallet_id_ = static_cast<td::uint32>(info->default_wallet_id_);
} else {
LOG(ERROR) << "Invalid config";
}
send_query(make_object<tonlib_api::init>(make_object<tonlib_api::options>(std::move(config), std::move(ks_type))),
[](auto r_ok) {
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
@ -266,8 +280,12 @@ class TonlibCli : public td::actor::Actor {
td::TerminalIO::out() << "time\tGet server time\n";
td::TerminalIO::out() << "remote-version\tShows server time, version and capabilities\n";
td::TerminalIO::out() << "sendfile <filename>\tLoad a serialized message from <filename> and send it to server\n";
td::TerminalIO::out() << "setconfig|validateconfig <path> [<name>] [<use_callback>] [<force>] - set or validate "
"lite server config\n";
td::TerminalIO::out() << "exit\tExit\n";
td::TerminalIO::out() << "quit\tExit\n";
td::TerminalIO::out()
<< "saveaccount[code|data] <filename> <addr>\tSaves into specified file the most recent state\n";
td::TerminalIO::out() << "genkey - generate new secret key\n";
td::TerminalIO::out() << "keys - show all stored keys\n";
@ -277,7 +295,6 @@ class TonlibCli : public td::actor::Actor {
td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n";
td::TerminalIO::out() << "exportkey [<key_id>] - export key\n";
td::TerminalIO::out() << "exportkeypem [<key_id>] - export key\n";
td::TerminalIO::out() << "setconfig <path> [<name>] [<use_callback>] [<force>] - set lite server config\n";
td::TerminalIO::out() << "getstate <key_id> - get state of simple wallet with requested key\n";
td::TerminalIO::out()
<< "gethistory <key_id> - get history fo simple wallet with requested key (last 10 transactions)\n";
@ -303,12 +320,6 @@ class TonlibCli : public td::actor::Actor {
export_key(cmd.str(), parser.read_word());
} else if (cmd == "importkey") {
import_key(parser.read_all());
} else if (cmd == "setconfig") {
auto config = parser.read_word();
auto name = parser.read_word();
auto use_callback = parser.read_word();
auto force = parser.read_word();
set_config(config, name, to_bool(use_callback), to_bool(force));
} else if (cmd == "getstate") {
get_state(parser.read_word());
} else if (cmd == "gethistory") {
@ -340,6 +351,18 @@ class TonlibCli : public td::actor::Actor {
remote_version(std::move(cmd_promise));
} else if (cmd == "sendfile") {
send_file(parser.read_word(), std::move(cmd_promise));
} else if (cmd == "saveaccount" || cmd == "saveaccountdata" || cmd == "saveaccountcode") {
auto path = parser.read_word();
auto address = parser.read_word();
save_account(cmd, path, address, std::move(cmd_promise));
} else if (cmd == "runmethod") {
run_method(parser, std::move(cmd_promise));
} else if (cmd == "setconfig" || cmd == "validateconfig") {
auto config = parser.read_word();
auto name = parser.read_word();
auto use_callback = parser.read_word();
auto force = parser.read_word();
set_validate_config(cmd, config, name, to_bool(use_callback), to_bool(force), std::move(cmd_promise));
} else {
cmd_promise.set_error(td::Status::Error(PSLICE() << "Unkwnown query `" << cmd << "`"));
}
@ -372,6 +395,40 @@ class TonlibCli : public td::actor::Actor {
}));
}
void save_account(td::Slice cmd, td::Slice path, td::Slice address, td::Promise<td::Unit> promise) {
TRY_RESULT_PROMISE(promise, addr, to_account_address(address, false));
send_query(tonlib_api::make_object<tonlib_api::smc_load>(std::move(addr.address)),
promise.send_closure(actor_id(this), &TonlibCli::save_account_2, cmd.str(), path.str(), address.str()));
}
void save_account_2(std::string cmd, std::string path, std::string address,
tonlib_api::object_ptr<tonlib_api::smc_info> info, td::Promise<td::Unit> promise) {
auto with_query = [&, self = this](auto query, auto log) {
send_query(std::move(query),
promise.send_closure(actor_id(self), &TonlibCli::save_account_3, std::move(path), std::move(log)));
};
if (cmd == "saveaccount") {
with_query(tonlib_api::make_object<tonlib_api::smc_getState>(info->id_),
PSTRING() << "StateInit of account " << address);
} else if (cmd == "saveaccountcode") {
with_query(tonlib_api::make_object<tonlib_api::smc_getCode>(info->id_), PSTRING()
<< "Code of account " << address);
} else if (cmd == "saveaccountdata") {
with_query(tonlib_api::make_object<tonlib_api::smc_getData>(info->id_), PSTRING()
<< "Data of account " << address);
} else {
promise.set_error(td::Status::Error("Unknown query"));
}
}
void save_account_3(std::string path, std::string log, tonlib_api::object_ptr<tonlib_api::tvm_cell> cell,
td::Promise<td::Unit> promise) {
TRY_STATUS_PROMISE(promise, td::write_file(path, cell->bytes_));
td::TerminalIO::out() << log << " was successfully written to the disk(" << td::format::as_size(cell->bytes_.size())
<< ")\n";
promise.set_value(td::Unit());
}
void sync(td::Promise<td::Unit> promise) {
using tonlib_api::make_object;
send_query(make_object<tonlib_api::sync>(), promise.wrap([](auto&&) {
@ -379,6 +436,107 @@ class TonlibCli : public td::actor::Actor {
return td::Unit();
}));
}
td::Result<tonlib_api::object_ptr<tonlib_api::tvm_StackEntry>> parse_stack_entry(td::Slice str) {
if (str.empty() || str.size() > 65535) {
return td::Status::Error("String is or empty or too big");
}
int l = (int)str.size();
if (str[0] == '"') {
vm::CellBuilder cb;
if (l == 1 || str.back() != '"' || l >= 127 + 2 || !cb.store_bytes_bool(str.data() + 1, l - 2)) {
return td::Status::Error("Failed to parse slice");
}
return tonlib_api::make_object<tonlib_api::tvm_stackEntrySlice>(
tonlib_api::make_object<tonlib_api::tvm_slice>(vm::std_boc_serialize(cb.finalize()).ok().as_slice().str()));
}
if (l >= 3 && (str[0] == 'x' || str[0] == 'b') && str[1] == '{' && str.back() == '}') {
unsigned char buff[128];
int bits =
(str[0] == 'x')
? (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1)
: (int)td::bitstring::parse_bitstring_binary_literal(buff, sizeof(buff), str.begin() + 2, str.end() - 1);
if (bits < 0) {
return td::Status::Error("Failed to parse slice");
}
return tonlib_api::make_object<tonlib_api::tvm_stackEntrySlice>(tonlib_api::make_object<tonlib_api::tvm_slice>(
vm::std_boc_serialize(vm::CellBuilder().store_bits(td::ConstBitPtr{buff}, bits).finalize())
.ok()
.as_slice()
.str()));
}
auto num = td::RefInt256{true};
auto& x = num.unique_write();
if (l >= 3 && str[0] == '0' && str[1] == 'x') {
if (x.parse_hex(str.data() + 2, l - 2) != l - 2) {
return td::Status::Error("Failed to parse a number");
}
} else if (l >= 4 && str[0] == '-' && str[1] == '0' && str[2] == 'x') {
if (x.parse_hex(str.data() + 3, l - 3) != l - 3) {
return td::Status::Error("Failed to parse a number");
}
x.negate().normalize();
} else if (!l || x.parse_dec(str.data(), l) != l) {
return td::Status::Error("Failed to parse a number");
}
return tonlib_api::make_object<tonlib_api::tvm_stackEntryNumber>(
tonlib_api::make_object<tonlib_api::tvm_numberDecimal>(dec_string(num)));
}
void run_method(td::ConstParser& parser, td::Promise<td::Unit> promise) {
TRY_RESULT_PROMISE(promise, addr, to_account_address(parser.read_word(), false));
auto method_str = parser.read_word();
tonlib_api::object_ptr<tonlib_api::smc_MethodId> method;
if (std::all_of(method_str.begin(), method_str.end(), [](auto c) { return c >= '0' && c <= '9'; })) {
method = tonlib_api::make_object<tonlib_api::smc_methodIdNumber>(td::to_integer<td::int32>(method_str.str()));
} else {
method = tonlib_api::make_object<tonlib_api::smc_methodIdName>(method_str.str());
}
std::vector<tonlib_api::object_ptr<tonlib_api::tvm_StackEntry>> stack;
while (true) {
auto word = parser.read_word();
if (word.empty()) {
break;
}
TRY_RESULT_PROMISE(promise, stack_entry, parse_stack_entry(word));
stack.push_back(std::move(stack_entry));
}
auto to_run =
tonlib_api::make_object<tonlib_api::smc_runGetMethod>(0 /*fixme*/, std::move(method), std::move(stack));
send_query(tonlib_api::make_object<tonlib_api::smc_load>(std::move(addr.address)),
promise.send_closure(actor_id(this), &TonlibCli::run_method_2, std::move(to_run)));
}
void run_method_2(tonlib_api::object_ptr<tonlib_api::smc_runGetMethod> to_run,
tonlib_api::object_ptr<tonlib_api::smc_info> info, td::Promise<td::Unit> promise) {
to_run->id_ = info->id_;
send_query(std::move(to_run), promise.send_closure(actor_id(this), &TonlibCli::run_method_3));
}
void run_method_3(tonlib_api::object_ptr<tonlib_api::smc_runResult> info, td::Promise<td::Unit> promise) {
td::TerminalIO::out() << "Got smc result " << to_string(info);
promise.set_value({});
}
void set_validate_config(td::Slice cmd, td::Slice path, td::Slice name, bool use_callback, bool ignore_cache,
td::Promise<td::Unit> promise) {
TRY_RESULT_PROMISE(promise, data, td::read_file_str(path.str()));
using tonlib_api::make_object;
auto config = make_object<tonlib_api::config>(std::move(data), name.str(), use_callback, ignore_cache);
if (cmd == "setconfig") {
send_query(make_object<tonlib_api::options_setConfig>(std::move(config)), promise.wrap([](auto&& info) {
td::TerminalIO::out() << "Config is set\n";
return td::Unit();
}));
} else {
send_query(make_object<tonlib_api::options_validateConfig>(std::move(config)), promise.wrap([](auto&& info) {
td::TerminalIO::out() << "Config is valid: " << to_string(info) << "\n";
return td::Unit();
}));
}
}
void dump_netstats() {
td::TerminalIO::out() << td::tag("snd", td::format::as_size(snd_bytes_)) << "\n";
@ -397,6 +555,8 @@ class TonlibCli : public td::actor::Actor {
}
}
td::Timestamp sync_started_;
void on_tonlib_result(std::uint64_t id, tonlib_api::object_ptr<tonlib_api::Object> result) {
if (id == 0) {
switch (result->get_id()) {
@ -415,10 +575,15 @@ class TonlibCli : public td::actor::Actor {
auto update = tonlib_api::move_object_as<tonlib_api::updateSyncState>(std::move(result));
switch (update->sync_state_->get_id()) {
case tonlib_api::syncStateDone::ID: {
td::TerminalIO::out() << "synchronization: DONE\n";
td::TerminalIO::out() << "synchronization: DONE in "
<< td::format::as_time(td::Time::now() - sync_started_.at()) << "\n";
sync_started_ = {};
break;
}
case tonlib_api::syncStateInProgress::ID: {
if (!sync_started_) {
sync_started_ = td::Timestamp::now();
}
auto progress = tonlib_api::move_object_as<tonlib_api::syncStateInProgress>(update->sync_state_);
auto from = progress->from_seqno_;
auto to = progress->to_seqno_;
@ -672,11 +837,19 @@ class TonlibCli : public td::actor::Actor {
auto r_key_i = to_key_i(key);
using tonlib_api::make_object;
if (r_key_i.is_ok()) {
auto obj = options_.use_simple_wallet
? tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)))
: tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
auto obj = [&](td::int32 version) {
if (version == 1) {
return tonlib::TonlibClient::static_request(make_object<tonlib_api::testWallet_getAccountAddress>(
make_object<tonlib_api::testWallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
}
if (version == 2) {
return tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_getAccountAddress>(
make_object<tonlib_api::wallet_initialAccountState>(keys_[r_key_i.ok()].public_key)));
}
return tonlib::TonlibClient::static_request(make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(keys_[r_key_i.ok()].public_key, wallet_id_)));
UNREACHABLE();
}(options_.wallet_version);
if (obj->get_id() != tonlib_api::error::ID) {
Address res;
res.address = ton::move_tl_object_as<tonlib_api::accountAddress>(obj);
@ -747,7 +920,7 @@ class TonlibCli : public td::actor::Actor {
void export_key(std::string cmd, std::string key, size_t key_i, td::Slice password) {
using tonlib_api::make_object;
if (cmd == "exportkey") {
send_query(make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKey>(
send_query(make_object<tonlib_api::exportKey>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy()),
td::SecureString(password))),
[this, key = std::move(key), key_i](auto r_res) {
@ -762,7 +935,7 @@ class TonlibCli : public td::actor::Actor {
});
} else {
send_query(make_object<tonlib_api::exportPemKey>(
make_object<tonlib_api::inputKey>(
make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy()),
td::SecureString(password)),
td::SecureString("cucumber")),
@ -817,26 +990,6 @@ class TonlibCli : public td::actor::Actor {
});
}
void set_config(td::Slice path, td::Slice name, bool use_callback, bool ignore_cache) {
auto r_data = td::read_file_str(path.str());
if (r_data.is_error()) {
td::TerminalIO::out() << "Can't read file [" << path << "] : " << r_data.error() << "\n";
return;
}
auto data = r_data.move_as_ok();
using tonlib_api::make_object;
send_query(make_object<tonlib_api::options_setConfig>(
make_object<tonlib_api::config>(std::move(data), name.str(), use_callback, ignore_cache)),
[](auto r_res) {
if (r_res.is_error()) {
td::TerminalIO::out() << "Can't set config: " << r_res.error() << "\n";
return;
}
td::TerminalIO::out() << to_string(r_res.ok());
});
}
void get_state(td::Slice key) {
if (key.empty()) {
dump_keys();
@ -973,7 +1126,7 @@ class TonlibCli : public td::actor::Actor {
}
using tonlib_api::make_object;
auto key = !from.secret.empty()
? make_object<tonlib_api::inputKey>(
? make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(from.public_key, from.secret.copy()), td::SecureString(password))
: nullptr;
send_query(make_object<tonlib_api::generic_createSendGramsQuery>(std::move(key), std::move(from.address),
@ -1034,8 +1187,8 @@ class TonlibCli : public td::actor::Actor {
void init_simple_wallet(std::string key, size_t key_i, td::Slice password) {
using tonlib_api::make_object;
if (options_.use_simple_wallet) {
send_query(make_object<tonlib_api::testWallet_init>(make_object<tonlib_api::inputKey>(
if (options_.wallet_version == 1) {
send_query(make_object<tonlib_api::testWallet_init>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy()),
td::SecureString(password))),
[key = std::move(key)](auto r_res) {
@ -1046,7 +1199,7 @@ class TonlibCli : public td::actor::Actor {
td::TerminalIO::out() << to_string(r_res.ok());
});
} else {
send_query(make_object<tonlib_api::wallet_init>(make_object<tonlib_api::inputKey>(
send_query(make_object<tonlib_api::wallet_init>(make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy()),
td::SecureString(password))),
[key = std::move(key)](auto r_res) {
@ -1127,8 +1280,8 @@ int main(int argc, char* argv[]) {
options.use_callbacks_for_network = true;
return td::Status::OK();
});
p.add_option('S', "use-simple-wallet", "do not use this", [&]() {
options.use_simple_wallet = true;
p.add_option('W', "wallet-version", "do not use this", [&](td::Slice arg) {
options.wallet_version = td::to_integer<td::int32>(arg);
return td::Status::OK();
});