mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit 'cdb9c21de06d3398874351b5ffc492ad8cd8ffc6' into background-task
This commit is contained in:
commit
b9fa37c984
2
BUCK
2
BUCK
@ -50,6 +50,8 @@ resource_dependencies = [
|
||||
"//submodules/TelegramUI:TelegramUIResources",
|
||||
"//submodules/WalletUI:WalletUIAssets",
|
||||
"//submodules/WalletUI:WalletUIResources",
|
||||
"//submodules/PasswordSetupUI:PasswordSetupUIResources",
|
||||
"//submodules/PasswordSetupUI:PasswordSetupUIAssets",
|
||||
"//submodules/OverlayStatusController:OverlayStatusControllerResources",
|
||||
"//:AppResources",
|
||||
"//:AppStringResources",
|
||||
|
@ -4820,7 +4820,7 @@ Any member of this group will be able to see messages in the channel.";
|
||||
"Wallet.Send.Balance" = "Balance: %@";
|
||||
"Wallet.Send.AmountText" = "Grams to send";
|
||||
"Wallet.Send.Confirmation" = "Confirmation";
|
||||
"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?";
|
||||
"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?\n\nFees: ~%3$@ grams";
|
||||
"Wallet.Send.ConfirmationConfirm" = "Confirm";
|
||||
"Wallet.Send.Send" = "Send";
|
||||
"Wallet.Settings.Title" = "Wallet Settings";
|
||||
@ -4991,3 +4991,38 @@ Any member of this group will be able to see messages in the channel.";
|
||||
|
||||
"Conversation.SwipeToReplyHintTitle" = "Swipe To Reply";
|
||||
"Conversation.SwipeToReplyHintText" = "Swipe left on any message to reply to it.";
|
||||
|
||||
"TwoFactorSetup.Intro.Title" = "Additional Password";
|
||||
"TwoFactorSetup.Intro.Text" = "You can set a password that will be\nrequired when you log in on a new device in addition to the code you get via SMS.";
|
||||
"TwoFactorSetup.Intro.Action" = "Set Additional Password";
|
||||
|
||||
"TwoFactorSetup.Password.Title" = "Create Password";
|
||||
"TwoFactorSetup.Password.PlaceholderPassword" = "Password";
|
||||
"TwoFactorSetup.Password.PlaceholderConfirmPassword" = "Re-enter Password";
|
||||
"TwoFactorSetup.Password.Action" = "Create Password";
|
||||
|
||||
"TwoFactorSetup.Email.Title" = "Recovery Email";
|
||||
"TwoFactorSetup.Email.Text" = "You can set a recovery email to be able to reset password and restore access\nto your Telegram account.";
|
||||
"TwoFactorSetup.Email.Placeholder" = "Your email address";
|
||||
"TwoFactorSetup.Email.Action" = "Continue";
|
||||
"TwoFactorSetup.Email.SkipAction" = "Skip setting email";
|
||||
"TwoFactorSetup.Email.SkipConfirmationTitle" = "No, seriously.";
|
||||
"TwoFactorSetup.Email.SkipConfirmationText" = "If you forget your password, you will lose access to your Telegram account. There will be no way to restore it.";
|
||||
"TwoFactorSetup.Email.SkipConfirmationSkip" = "Skip";
|
||||
|
||||
"TwoFactorSetup.EmailVerification.Title" = "Recovery Email";
|
||||
"TwoFactorSetup.EmailVerification.Text" = "Please enter code we've just emailed at %@";
|
||||
"TwoFactorSetup.EmailVerification.Placeholder" = "Code";
|
||||
"TwoFactorSetup.EmailVerification.Action" = "Continue";
|
||||
"TwoFactorSetup.EmailVerification.ChangeAction" = "Change Email";
|
||||
"TwoFactorSetup.EmailVerification.ResendAction" = "Resend Code";
|
||||
|
||||
"TwoFactorSetup.Hint.Title" = "Hint";
|
||||
"TwoFactorSetup.Hint.Text" = "You can create an optional hint for\nyour password.";
|
||||
"TwoFactorSetup.Hint.Placeholder" = "Hint (optional)";
|
||||
"TwoFactorSetup.Hint.Action" = "Continue";
|
||||
"TwoFactorSetup.Hint.SkipAction" = "Skip setting hint";
|
||||
|
||||
"TwoFactorSetup.Done.Title" = "Password Set!";
|
||||
"TwoFactorSetup.Done.Text" = "Now password will be required when you log in on a new device in addition to the code you get via SMS.";
|
||||
"TwoFactorSetup.Done.Action" = "Return to Settings";
|
||||
|
@ -54,7 +54,7 @@
|
||||
"Wallet.Send.Balance" = "Balance: %@";
|
||||
"Wallet.Send.AmountText" = "Grams to send";
|
||||
"Wallet.Send.Confirmation" = "Confirmation";
|
||||
"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?";
|
||||
"Wallet.Send.ConfirmationText" = "Do you want to send **%1$@** Grams to\n%2$@?\n\nFees: ~%3$@ grams";
|
||||
"Wallet.Send.ConfirmationConfirm" = "Confirm";
|
||||
"Wallet.Send.Send" = "Send";
|
||||
"Wallet.Settings.Title" = "Wallet Settings";
|
||||
@ -106,11 +106,11 @@
|
||||
"Wallet.TransactionInfo.SenderHeader" = "SENDER";
|
||||
"Wallet.TransactionInfo.CopyAddress" = "Copy Wallet Address";
|
||||
"Wallet.TransactionInfo.AddressCopied" = "Address copied to clipboard.";
|
||||
"Wallet.TransactionInfo.SendGrams" = "Send Grams";
|
||||
"Wallet.TransactionInfo.SendGrams" = "Send Grams to This Address";
|
||||
"Wallet.TransactionInfo.CommentHeader" = "COMMENT";
|
||||
"Wallet.TransactionInfo.StorageFeeHeader" = "STORAGE FEE";
|
||||
"Wallet.TransactionInfo.OtherFeeHeader" = "TRANSACTION FEE";
|
||||
"Wallet.TransactionInfo.StorageFeeInfo" = "Blockchain validators collect a tiny fee for storing information about your decentralized wallet. [More info]()";
|
||||
"Wallet.TransactionInfo.StorageFeeInfo" = "Blockchain validators collect a tiny fee for storing information about your decentralized wallet and processing your transactions. [More info]()";
|
||||
"Wallet.TransactionInfo.OtherFeeInfo" = "Blockchain validators collect a tiny fee for processing your decentralized transactions. [More info]()";
|
||||
"Wallet.TransactionInfo.FeeInfoURL" = "https://telegram.org/wallet/fee";
|
||||
"Wallet.WordCheck.Title" = "Test Time!";
|
||||
|
@ -171,6 +171,7 @@ public final class TextAlertContentNode: AlertContentNode {
|
||||
self.textNode.isLayerBacked = false
|
||||
self.textNode.isAccessibilityElement = true
|
||||
self.textNode.accessibilityLabel = text.string
|
||||
self.textNode.insets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0)
|
||||
if text.length != 0 {
|
||||
if let paragraphStyle = text.attribute(.paragraphStyle, at: 0, effectiveRange: nil) as? NSParagraphStyle {
|
||||
self.textNode.textAlignment = paragraphStyle.alignment
|
||||
@ -292,7 +293,7 @@ public final class TextAlertContentNode: AlertContentNode {
|
||||
transition.updateFrame(node: titleNode, frame: titleFrame)
|
||||
|
||||
let textFrame = CGRect(origin: CGPoint(x: insets.left + floor((contentWidth - textSize.width) / 2.0), y: titleFrame.maxY + spacing), size: textSize)
|
||||
transition.updateFrame(node: self.textNode, frame: textFrame)
|
||||
transition.updateFrame(node: self.textNode, frame: textFrame.offsetBy(dx: -1.0, dy: -1.0))
|
||||
|
||||
resultSize = CGSize(width: contentWidth + insets.left + insets.right, height: titleSize.height + spacing + textSize.height + actionsHeight + insets.top + insets.bottom)
|
||||
} else {
|
||||
|
@ -1,5 +1,21 @@
|
||||
load("//Config:buck_rule_macros.bzl", "static_library")
|
||||
|
||||
apple_resource(
|
||||
name = "PasswordSetupUIResources",
|
||||
files = glob([
|
||||
"Resources/**/*",
|
||||
], exclude = ["Resources/**/.*"]),
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
apple_asset_catalog(
|
||||
name = "PasswordSetupUIAssets",
|
||||
dirs = [
|
||||
"PasswordSetupUIImages.xcassets",
|
||||
],
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
static_library(
|
||||
name = "PasswordSetupUI",
|
||||
srcs = glob([
|
||||
@ -19,6 +35,11 @@ static_library(
|
||||
"//submodules/AlertUI:AlertUI",
|
||||
"//submodules/PresentationDataUtils:PresentationDataUtils",
|
||||
"//submodules/ItemListUI:ItemListUI",
|
||||
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
|
||||
"//submodules/AppBundle:AppBundle",
|
||||
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
|
||||
"//submodules/OverlayStatusController:OverlayStatusController",
|
||||
"//submodules/rlottie:RLottieBinding",
|
||||
],
|
||||
frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"provides-namespace" : true
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "User.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/User.pdf
vendored
Normal file
BIN
submodules/PasswordSetupUI/PasswordSetupUIImages.xcassets/PasswordSetup/TextHidden.imageset/User.pdf
vendored
Normal file
Binary file not shown.
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupDone.tgs
Normal file
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupDone.tgs
Normal file
Binary file not shown.
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupHint.tgs
Normal file
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupHint.tgs
Normal file
Binary file not shown.
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupIntro.tgs
Normal file
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupIntro.tgs
Normal file
Binary file not shown.
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupMail.tgs
Normal file
BIN
submodules/PasswordSetupUI/Resources/TwoFactorSetupMail.tgs
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
256
submodules/PasswordSetupUI/Sources/ManagedAnimationNode.swift
Normal file
256
submodules/PasswordSetupUI/Sources/ManagedAnimationNode.swift
Normal file
@ -0,0 +1,256 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import RLottieBinding
|
||||
import AppBundle
|
||||
import GZip
|
||||
|
||||
enum ManagedAnimationTrackState {
|
||||
case intro
|
||||
case loop
|
||||
case outro
|
||||
}
|
||||
|
||||
private final class ManagedAnimationState {
|
||||
var item: ManagedAnimationItem
|
||||
|
||||
private let instance: LottieInstance
|
||||
|
||||
let frameCount: Int
|
||||
let fps: Double
|
||||
|
||||
var startTime: Double?
|
||||
var trackState: ManagedAnimationTrackState?
|
||||
var trackingFrameState: (Int, Int)?
|
||||
var frameIndex: Int?
|
||||
|
||||
private let renderContext: DrawingContext
|
||||
|
||||
init?(item: ManagedAnimationItem) {
|
||||
guard let path = getAppBundle().path(forResource: item.name, ofType: "tgs") else {
|
||||
return nil
|
||||
}
|
||||
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
|
||||
return nil
|
||||
}
|
||||
guard let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024) else {
|
||||
return nil
|
||||
}
|
||||
guard let instance = LottieInstance(data: unpackedData, cacheKey: item.name) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.item = item
|
||||
self.instance = instance
|
||||
|
||||
self.frameCount = Int(instance.frameCount)
|
||||
self.fps = Double(instance.frameRate)
|
||||
|
||||
self.renderContext = DrawingContext(size: instance.dimensions, scale: UIScreenScale, premultiplied: true, clear: true)
|
||||
}
|
||||
|
||||
func draw() -> UIImage? {
|
||||
self.instance.renderFrame(with: Int32(self.frameIndex ?? 0), into: self.renderContext.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(self.renderContext.size.width * self.renderContext.scale), height: Int32(self.renderContext.size.height * self.renderContext.scale), bytesPerRow: Int32(self.renderContext.bytesPerRow))
|
||||
return self.renderContext.generateImage()
|
||||
}
|
||||
}
|
||||
|
||||
enum ManagedAnimationActionAtEnd {
|
||||
case pause
|
||||
case advance
|
||||
case loop
|
||||
}
|
||||
|
||||
struct ManagedAnimationTrack: Equatable {
|
||||
let frameRange: Range<Int>
|
||||
}
|
||||
|
||||
struct ManagedAnimationItem: Equatable {
|
||||
let name: String
|
||||
var intro: ManagedAnimationTrack?
|
||||
var loop: ManagedAnimationTrack?
|
||||
var outro: ManagedAnimationTrack?
|
||||
}
|
||||
|
||||
final class ManagedAnimationNode: ASDisplayNode {
|
||||
let intrinsicSize: CGSize
|
||||
|
||||
private let imageNode: ASImageNode
|
||||
private let displayLink: CADisplayLink
|
||||
|
||||
private var items: [ManagedAnimationState] = []
|
||||
|
||||
var currentItemName: String? {
|
||||
return self.items.first?.item.name
|
||||
}
|
||||
|
||||
init(size: CGSize) {
|
||||
self.intrinsicSize = size
|
||||
|
||||
self.imageNode = ASImageNode()
|
||||
self.imageNode.displayWithoutProcessing = true
|
||||
self.imageNode.displaysAsynchronously = false
|
||||
self.imageNode.frame = CGRect(origin: CGPoint(), size: self.intrinsicSize)
|
||||
|
||||
final class DisplayLinkTarget: NSObject {
|
||||
private let f: () -> Void
|
||||
|
||||
init(_ f: @escaping () -> Void) {
|
||||
self.f = f
|
||||
}
|
||||
|
||||
@objc func event() {
|
||||
self.f()
|
||||
}
|
||||
}
|
||||
var displayLinkUpdate: (() -> Void)?
|
||||
self.displayLink = CADisplayLink(target: DisplayLinkTarget {
|
||||
displayLinkUpdate?()
|
||||
}, selector: #selector(DisplayLinkTarget.event))
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.imageNode)
|
||||
|
||||
self.displayLink.add(to: RunLoop.main, forMode: .common)
|
||||
|
||||
displayLinkUpdate = { [weak self] in
|
||||
self?.updateAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateAnimation() {
|
||||
guard let item = self.items.first else {
|
||||
return
|
||||
}
|
||||
let timestamp = CACurrentMediaTime()
|
||||
var startTime: Double
|
||||
let maybeTrackState: ManagedAnimationTrackState?
|
||||
if let current = item.startTime {
|
||||
startTime = current
|
||||
} else {
|
||||
startTime = timestamp
|
||||
item.startTime = startTime
|
||||
}
|
||||
if let current = item.trackState {
|
||||
maybeTrackState = current
|
||||
} else if let _ = item.item.intro {
|
||||
maybeTrackState = .intro
|
||||
} else if let _ = item.item.loop {
|
||||
maybeTrackState = .loop
|
||||
} else if let _ = item.item.outro {
|
||||
maybeTrackState = .outro
|
||||
} else {
|
||||
maybeTrackState = nil
|
||||
}
|
||||
if item.trackState != maybeTrackState {
|
||||
item.trackState = maybeTrackState
|
||||
item.startTime = timestamp
|
||||
startTime = timestamp
|
||||
}
|
||||
|
||||
guard let trackState = maybeTrackState else {
|
||||
self.items.removeFirst()
|
||||
return
|
||||
}
|
||||
|
||||
var fps = item.fps
|
||||
|
||||
let track: ManagedAnimationTrack
|
||||
switch trackState {
|
||||
case .intro:
|
||||
track = item.item.intro!
|
||||
case .loop:
|
||||
track = item.item.loop!
|
||||
if self.items.count > 1 {
|
||||
//fps *= 2.0
|
||||
}
|
||||
case .outro:
|
||||
track = item.item.outro!
|
||||
}
|
||||
|
||||
let frameIndex: Int
|
||||
if let (startFrame, endFrame) = item.trackingFrameState {
|
||||
let duration: Double = 0.3
|
||||
var t = (timestamp - startTime) / duration
|
||||
t = max(0.0, t)
|
||||
t = min(1.0, t)
|
||||
let frameOffset = Int(Double(startFrame) * (1.0 - t) + Double(endFrame) * t)
|
||||
let lowerBound = min(track.frameRange.lowerBound, item.frameCount - 1)
|
||||
let upperBound = min(track.frameRange.upperBound, item.frameCount)
|
||||
frameIndex = max(lowerBound, min(upperBound, frameOffset))
|
||||
} else {
|
||||
let frameOffset = Int((timestamp - startTime) * fps)
|
||||
let lowerBound = min(track.frameRange.lowerBound, item.frameCount - 1)
|
||||
let upperBound = min(track.frameRange.upperBound, item.frameCount)
|
||||
if frameOffset >= upperBound - lowerBound {
|
||||
switch trackState {
|
||||
case .intro:
|
||||
if let _ = item.item.loop {
|
||||
item.trackState = .loop
|
||||
item.startTime = timestamp
|
||||
return
|
||||
} else if let _ = item.item.outro {
|
||||
item.trackState = .outro
|
||||
item.startTime = timestamp
|
||||
return
|
||||
} else {
|
||||
self.items.removeFirst()
|
||||
return
|
||||
}
|
||||
case .loop:
|
||||
if self.items.count > 1 {
|
||||
if let _ = item.item.outro {
|
||||
item.trackState = .outro
|
||||
item.startTime = timestamp
|
||||
} else {
|
||||
self.items.removeFirst()
|
||||
}
|
||||
return
|
||||
} else {
|
||||
item.startTime = timestamp
|
||||
frameIndex = lowerBound
|
||||
}
|
||||
case .outro:
|
||||
self.items.removeFirst()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
frameIndex = lowerBound + frameOffset % (upperBound - lowerBound)
|
||||
}
|
||||
}
|
||||
|
||||
if item.frameIndex != frameIndex {
|
||||
item.frameIndex = frameIndex
|
||||
if let image = item.draw() {
|
||||
self.imageNode.image = image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func switchTo(_ item: ManagedAnimationItem, noOutro: Bool = false) {
|
||||
if let state = ManagedAnimationState(item: item) {
|
||||
if let last = self.items.last {
|
||||
if last.item.name == item.name {
|
||||
return
|
||||
}
|
||||
}
|
||||
if let first = self.items.first {
|
||||
if noOutro {
|
||||
first.item.outro = nil
|
||||
}
|
||||
}
|
||||
self.items.append(state)
|
||||
self.updateAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
func trackTo(frameIndex: Int) {
|
||||
if let first = self.items.first {
|
||||
first.startTime = CACurrentMediaTime()
|
||||
first.trackingFrameState = (first.frameIndex ?? 0, frameIndex)
|
||||
self.updateAnimation()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// PasswordSetupUI.h
|
||||
// PasswordSetupUI
|
||||
//
|
||||
// Created by Peter on 8/12/19.
|
||||
// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
//! Project version number for PasswordSetupUI.
|
||||
FOUNDATION_EXPORT double PasswordSetupUIVersionNumber;
|
||||
|
||||
//! Project version string for PasswordSetupUI.
|
||||
FOUNDATION_EXPORT const unsigned char PasswordSetupUIVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <PasswordSetupUI/PublicHeader.h>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,207 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AppBundle
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import SolidRoundedButtonNode
|
||||
import SwiftSignalKit
|
||||
import OverlayStatusController
|
||||
import AnimatedStickerNode
|
||||
import AccountContext
|
||||
import TelegramPresentationData
|
||||
import PresentationDataUtils
|
||||
|
||||
public enum TwoFactorAuthSplashMode {
|
||||
case intro
|
||||
case done
|
||||
}
|
||||
|
||||
public final class TwoFactorAuthSplashScreen: ViewController {
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
private var mode: TwoFactorAuthSplashMode
|
||||
|
||||
public init(context: AccountContext, mode: TwoFactorAuthSplashMode) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
let defaultTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme)
|
||||
let navigationBarTheme = NavigationBarTheme(buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor)
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Wallet_Intro_NotNow, close: self.presentationData.strings.Wallet_Navigation_Close)))
|
||||
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
self.navigationPresentation = .modalInLargeLayout
|
||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
self.navigationBar?.intrinsicCanTransitionInline = false
|
||||
|
||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Wallet_Navigation_Back, style: .plain, target: nil, action: nil)
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = TwoFactorAuthSplashScreenNode(context: self.context, presentationData: self.presentationData, mode: self.mode, action: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
switch strongSelf.mode {
|
||||
case .intro:
|
||||
strongSelf.push(TwoFactorDataInputScreen(context: strongSelf.context, mode: .password))
|
||||
case .done:
|
||||
guard let navigationController = strongSelf.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
navigationController.filterController(strongSelf, animated: true)
|
||||
}
|
||||
})
|
||||
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
(self.displayNode as! TwoFactorAuthSplashScreenNode).containerLayoutUpdated(layout: layout, navigationHeight: self.navigationHeight, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private final class TwoFactorAuthSplashScreenNode: ViewControllerTracingNode {
|
||||
private var presentationData: PresentationData
|
||||
private let mode: TwoFactorAuthSplashMode
|
||||
|
||||
private var animationSize: CGSize = CGSize()
|
||||
private var animationOffset: CGPoint = CGPoint()
|
||||
private let animationNode: AnimatedStickerNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let textNode: ImmediateTextNode
|
||||
let buttonNode: SolidRoundedButtonNode
|
||||
|
||||
var inProgress: Bool = false {
|
||||
didSet {
|
||||
self.buttonNode.isUserInteractionEnabled = !self.inProgress
|
||||
self.buttonNode.alpha = self.inProgress ? 0.6 : 1.0
|
||||
}
|
||||
}
|
||||
|
||||
init(context: AccountContext, presentationData: PresentationData, mode: TwoFactorAuthSplashMode, action: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.mode = mode
|
||||
|
||||
self.animationNode = AnimatedStickerNode()
|
||||
|
||||
let title: String
|
||||
let text: NSAttributedString
|
||||
let buttonText: String
|
||||
|
||||
let textFont = Font.regular(16.0)
|
||||
let textColor = self.presentationData.theme.list.itemPrimaryTextColor
|
||||
|
||||
switch mode {
|
||||
case .intro:
|
||||
title = self.presentationData.strings.TwoFactorSetup_Intro_Title
|
||||
text = NSAttributedString(string: self.presentationData.strings.TwoFactorSetup_Intro_Text, font: textFont, textColor: textColor)
|
||||
buttonText = self.presentationData.strings.TwoFactorSetup_Intro_Action
|
||||
|
||||
if let path = getAppBundle().path(forResource: "TwoFactorSetupIntro", ofType: "tgs") {
|
||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, playbackMode: .once, mode: .direct)
|
||||
self.animationSize = CGSize(width: 124.0, height: 124.0)
|
||||
self.animationNode.visibility = true
|
||||
}
|
||||
case .done:
|
||||
title = self.presentationData.strings.TwoFactorSetup_Done_Title
|
||||
text = NSAttributedString(string: self.presentationData.strings.TwoFactorSetup_Done_Text, font: textFont, textColor: textColor)
|
||||
buttonText = self.presentationData.strings.TwoFactorSetup_Done_Action
|
||||
|
||||
if let path = getAppBundle().path(forResource: "TwoFactorSetupDone", ofType: "tgs") {
|
||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 248, height: 248, mode: .direct)
|
||||
self.animationSize = CGSize(width: 124.0, height: 124.0)
|
||||
self.animationNode.visibility = true
|
||||
}
|
||||
}
|
||||
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(32.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
|
||||
self.titleNode.maximumNumberOfLines = 0
|
||||
self.titleNode.textAlignment = .center
|
||||
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.displaysAsynchronously = false
|
||||
self.textNode.attributedText = text
|
||||
self.textNode.maximumNumberOfLines = 0
|
||||
self.textNode.lineSpacing = 0.1
|
||||
self.textNode.textAlignment = .center
|
||||
|
||||
self.buttonNode = SolidRoundedButtonNode(title: buttonText, theme: SolidRoundedButtonTheme(backgroundColor: self.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: self.presentationData.theme.list.itemCheckColors.foregroundColor), height: 50.0, cornerRadius: 10.0, gloss: false)
|
||||
self.buttonNode.isHidden = buttonText.isEmpty
|
||||
|
||||
super.init()
|
||||
|
||||
self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor
|
||||
|
||||
self.addSubnode(self.animationNode)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.textNode)
|
||||
self.addSubnode(self.buttonNode)
|
||||
|
||||
self.buttonNode.pressed = {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let sideInset: CGFloat = 32.0
|
||||
let buttonSideInset: CGFloat = 48.0
|
||||
let iconSpacing: CGFloat = 8.0
|
||||
let titleSpacing: CGFloat = 19.0
|
||||
let buttonHeight: CGFloat = 50.0
|
||||
|
||||
let iconSize: CGSize = self.animationSize
|
||||
var iconOffset = CGPoint()
|
||||
switch self.mode {
|
||||
case .done:
|
||||
iconOffset.x = 10.0
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
|
||||
|
||||
let contentHeight = iconSize.height + iconSpacing + titleSize.height + titleSpacing + textSize.height
|
||||
var contentVerticalOrigin = floor((layout.size.height - contentHeight - iconSize.height / 2.0) / 2.0)
|
||||
|
||||
let minimalBottomInset: CGFloat = 60.0
|
||||
let bottomInset = layout.intrinsicInsets.bottom + minimalBottomInset
|
||||
|
||||
let buttonWidth = layout.size.width - buttonSideInset * 2.0
|
||||
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonWidth) / 2.0), y: layout.size.height - bottomInset - buttonHeight), size: CGSize(width: buttonWidth, height: buttonHeight))
|
||||
transition.updateFrame(node: self.buttonNode, frame: buttonFrame)
|
||||
self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
|
||||
|
||||
var maxContentVerticalOrigin = buttonFrame.minY - 12.0 - contentHeight
|
||||
|
||||
contentVerticalOrigin = min(contentVerticalOrigin, maxContentVerticalOrigin)
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0) + self.animationOffset.x, y: contentVerticalOrigin + self.animationOffset.y), size: iconSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y)
|
||||
self.animationNode.updateLayout(size: iconFrame.size)
|
||||
transition.updateFrameAdditive(node: self.animationNode, frame: iconFrame)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
|
||||
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
|
||||
let textFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize)
|
||||
transition.updateFrameAdditive(node: self.textNode, frame: textFrame)
|
||||
}
|
||||
}
|
@ -80,9 +80,9 @@ static_library(
|
||||
"//submodules/ContextUI:ContextUI",
|
||||
"//submodules/WalletUI:WalletUI",
|
||||
"//submodules/Markdown:Markdown",
|
||||
"//submodules/PhoneNumberFormat:PhoneNumberFormat",
|
||||
"//submodules/UndoUI:UndoUI",
|
||||
"//submodules/DeleteChatPeerActionSheetItem:DeleteChatPeerActionSheetItem",
|
||||
"//submodules/PhoneNumberFormat:PhoneNumberFormat",
|
||||
],
|
||||
frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||
|
@ -14,6 +14,7 @@ import AccountContext
|
||||
import TelegramNotices
|
||||
import LocalAuth
|
||||
import AppBundle
|
||||
import PasswordSetupUI
|
||||
|
||||
private final class PrivacyAndSecurityControllerArguments {
|
||||
let account: Account
|
||||
@ -640,7 +641,14 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
||||
case .set:
|
||||
break
|
||||
case let .notSet(pendingEmail):
|
||||
intro = pendingEmail == nil
|
||||
if pendingEmail == nil {
|
||||
let controller = TwoFactorAuthSplashScreen(context: context, mode: .intro)
|
||||
pushControllerImpl?(controller, true)
|
||||
} else {
|
||||
|
||||
}
|
||||
//intro = pendingEmail == nil
|
||||
return
|
||||
}
|
||||
}
|
||||
if intro {
|
||||
|
@ -339,9 +339,9 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
|
||||
inputBackgroundColor: UIColor(rgb: 0xe9e9e9),
|
||||
inputHollowBackgroundColor: .white,
|
||||
inputBorderColor: UIColor(rgb: 0xe4e4e6),
|
||||
inputPlaceholderColor: UIColor(rgb: 0x818086),
|
||||
inputPlaceholderColor: UIColor(rgb: 0x8E8D92),
|
||||
inputTextColor: .black,
|
||||
inputClearButtonColor: UIColor(rgb: 0x7b7b81),
|
||||
inputClearButtonColor: UIColor(rgb: 0xBCBCC0),
|
||||
checkContentColor: .white
|
||||
)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -74,6 +74,36 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@end
|
||||
|
||||
@interface TONFees : NSObject
|
||||
|
||||
@property (nonatomic, readonly) int64_t inFwdFee;
|
||||
@property (nonatomic, readonly) int64_t storageFee;
|
||||
@property (nonatomic, readonly) int64_t gasFee;
|
||||
@property (nonatomic, readonly) int64_t fwdFee;
|
||||
|
||||
- (instancetype)initWithInFwdFee:(int64_t)inFwdFee storageFee:(int64_t)storageFee gasFee:(int64_t)gasFee fwdFee:(int64_t)fwdFee;
|
||||
|
||||
@end
|
||||
|
||||
@interface TONSendGramsQueryFees : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) TONFees *sourceFees;
|
||||
@property (nonatomic, strong, readonly) TONFees *destinationFees;
|
||||
|
||||
- (instancetype)initWithSourceFees:(TONFees *)sourceFees destinationFees:(TONFees *)destinationFees;
|
||||
|
||||
@end
|
||||
|
||||
@interface TONPreparedSendGramsQuery : NSObject
|
||||
|
||||
@property (nonatomic, readonly) int64_t queryId;
|
||||
@property (nonatomic, readonly) int64_t validUntil;
|
||||
@property (nonatomic, strong, readonly) NSData * _Nonnull bodyHash;
|
||||
|
||||
- (instancetype)initWithQueryId:(int64_t)queryId validUntil:(int64_t)validUntil bodyHash:(NSData *)bodyHash;
|
||||
|
||||
@end
|
||||
|
||||
@interface TONSendGramsResult : NSObject
|
||||
|
||||
@property (nonatomic, readonly) int64_t sentUntil;
|
||||
@ -92,7 +122,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (SSignal *)createKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword;
|
||||
- (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey;
|
||||
- (SSignal *)getAccountStateWithAddress:(NSString *)accountAddress;
|
||||
- (SSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId;
|
||||
- (SSignal *)generateSendGramsQueryFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId;
|
||||
- (SSignal *)generateFakeSendGramsQueryFromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout;
|
||||
- (SSignal *)estimateSendGramsQueryFees:(TONPreparedSendGramsQuery *)preparedQuery;
|
||||
- (SSignal *)commitPreparedSendGramsQuery:(TONPreparedSendGramsQuery *)preparedQuery;
|
||||
- (SSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword;
|
||||
- (SSignal *)importKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword wordList:(NSArray<NSString *> *)wordList;
|
||||
- (SSignal *)deleteKey:(TONKey *)key;
|
||||
|
@ -147,6 +147,48 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
|
||||
|
||||
@end
|
||||
|
||||
@implementation TONFees
|
||||
|
||||
- (instancetype)initWithInFwdFee:(int64_t)inFwdFee storageFee:(int64_t)storageFee gasFee:(int64_t)gasFee fwdFee:(int64_t)fwdFee {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_inFwdFee = inFwdFee;
|
||||
_storageFee = storageFee;
|
||||
_gasFee = gasFee;
|
||||
_fwdFee = fwdFee;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TONSendGramsQueryFees
|
||||
|
||||
- (instancetype)initWithSourceFees:(TONFees *)sourceFees destinationFees:(TONFees *)destinationFees {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_sourceFees = sourceFees;
|
||||
_destinationFees = destinationFees;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TONPreparedSendGramsQuery
|
||||
|
||||
- (instancetype)initWithQueryId:(int64_t)queryId validUntil:(int64_t)validUntil bodyHash:(NSData *)bodyHash {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queryId = queryId;
|
||||
_validUntil = validUntil;
|
||||
_bodyHash = bodyHash;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation TONSendGramsResult
|
||||
|
||||
- (instancetype)initWithSentUntil:(int64_t)sentUntil bodyHash:(NSData *)bodyHash {
|
||||
@ -540,7 +582,7 @@ typedef enum {
|
||||
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
|
||||
}
|
||||
|
||||
- (SSignal *)sendGramsFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId {
|
||||
- (SSignal *)generateSendGramsQueryFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId {
|
||||
return [[[[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
|
||||
if ([_sendGramRandomIds containsObject:@(randomId)]) {
|
||||
[_sendGramRandomIds addObject:@(randomId)];
|
||||
@ -570,17 +612,17 @@ typedef enum {
|
||||
}];
|
||||
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::sendGramsResult::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::sendGramsResult>(object);
|
||||
TONSendGramsResult *sendResult = [[TONSendGramsResult alloc] initWithSentUntil:result->sent_until_ bodyHash:makeData(result->body_hash_)];
|
||||
[subscriber putNext:sendResult];
|
||||
} else if (object->get_id() == tonlib_api::query_info::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::query_info>(object);
|
||||
TONPreparedSendGramsQuery *preparedQuery = [[TONPreparedSendGramsQuery alloc] initWithQueryId:result->id_ validUntil:result->valid_until_ bodyHash:makeData(result->body_hash_)];
|
||||
[subscriber putNext:preparedQuery];
|
||||
[subscriber putCompletion];
|
||||
} else {
|
||||
[subscriber putCompletion];
|
||||
}
|
||||
}];
|
||||
|
||||
auto query = make_object<tonlib_api::generic_sendGrams>(
|
||||
auto query = make_object<tonlib_api::generic_createSendGramsQuery>(
|
||||
make_object<tonlib_api::inputKey>(
|
||||
make_object<tonlib_api::key>(
|
||||
makeString(publicKeyData),
|
||||
@ -602,6 +644,101 @@ typedef enum {
|
||||
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
|
||||
}
|
||||
|
||||
- (SSignal *)generateFakeSendGramsQueryFromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount textMessage:(NSData *)textMessage forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout {
|
||||
return [[[[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
|
||||
|
||||
uint64_t requestId = _nextRequestId;
|
||||
_nextRequestId += 1;
|
||||
|
||||
__weak TON *weakSelf = self;
|
||||
SQueue *queue = _queue;
|
||||
_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::query_info::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::query_info>(object);
|
||||
TONPreparedSendGramsQuery *preparedQuery = [[TONPreparedSendGramsQuery alloc] initWithQueryId:result->id_ validUntil:result->valid_until_ bodyHash:makeData(result->body_hash_)];
|
||||
[subscriber putNext:preparedQuery];
|
||||
[subscriber putCompletion];
|
||||
} else {
|
||||
[subscriber putCompletion];
|
||||
}
|
||||
}];
|
||||
|
||||
auto query = make_object<tonlib_api::generic_createSendGramsQuery>(
|
||||
make_object<tonlib_api::inputKeyFake>(),
|
||||
make_object<tonlib_api::accountAddress>(fromAddress.UTF8String),
|
||||
make_object<tonlib_api::accountAddress>(address.UTF8String),
|
||||
amount,
|
||||
timeout,
|
||||
forceIfDestinationNotInitialized,
|
||||
makeString(textMessage)
|
||||
);
|
||||
_client->send({ requestId, std::move(query) });
|
||||
|
||||
return [[SBlockDisposable alloc] initWithBlock:^{
|
||||
}];
|
||||
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
|
||||
}
|
||||
|
||||
- (SSignal *)estimateSendGramsQueryFees:(TONPreparedSendGramsQuery *)preparedQuery {
|
||||
return [[[[SSignal alloc] initWithGenerator:^id<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::query_fees::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::query_fees>(object);
|
||||
TONFees *sourceFees = [[TONFees alloc] initWithInFwdFee:result->source_fees_->in_fwd_fee_ storageFee:result->source_fees_->storage_fee_ gasFee:result->source_fees_->gas_fee_ fwdFee:result->source_fees_->fwd_fee_];
|
||||
TONFees *destinationFees = [[TONFees alloc] initWithInFwdFee:result->destination_fees_->in_fwd_fee_ storageFee:result->destination_fees_->storage_fee_ gasFee:result->destination_fees_->gas_fee_ fwdFee:result->destination_fees_->fwd_fee_];
|
||||
[subscriber putNext:[[TONSendGramsQueryFees alloc] initWithSourceFees:sourceFees destinationFees:destinationFees]];
|
||||
[subscriber putCompletion];
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}];
|
||||
|
||||
auto query = make_object<tonlib_api::query_estimateFees>(
|
||||
preparedQuery.queryId,
|
||||
true
|
||||
);
|
||||
_client->send({ requestId, std::move(query) });
|
||||
|
||||
return [[SBlockDisposable alloc] initWithBlock:^{
|
||||
}];
|
||||
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
|
||||
}
|
||||
|
||||
- (SSignal *)commitPreparedSendGramsQuery:(TONPreparedSendGramsQuery *)preparedQuery {
|
||||
return [[[[SSignal alloc] initWithGenerator:^id<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::ok::ID) {
|
||||
[subscriber putCompletion];
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}];
|
||||
|
||||
auto query = make_object<tonlib_api::query_send>(
|
||||
preparedQuery.queryId
|
||||
);
|
||||
_client->send({ requestId, std::move(query) });
|
||||
|
||||
return [[SBlockDisposable alloc] initWithBlock:^{
|
||||
}];
|
||||
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
|
||||
}
|
||||
|
||||
- (SSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword {
|
||||
return [[[[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
|
||||
NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding];
|
||||
|
@ -350,19 +350,19 @@ public final class TonInstance {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func sendGramsFromWallet(decryptedSecret: Data, localPassword: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: Data, forceIfDestinationNotInitialized: Bool, timeout: Int32, randomId: Int64) -> Signal<PendingWalletTransaction, SendGramsFromWalletError> {
|
||||
fileprivate func prepareSendGramsFromWalletQuery(decryptedSecret: Data, localPassword: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: Data, forceIfDestinationNotInitialized: Bool, timeout: Int32, randomId: Int64) -> Signal<TONPreparedSendGramsQuery, SendGramsFromWalletError> {
|
||||
let key = TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret)
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
impl.withInstance { ton in
|
||||
let cancel = ton.sendGrams(from: key, localPassword: localPassword, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId).start(next: { result in
|
||||
guard let result = result as? TONSendGramsResult else {
|
||||
let cancel = ton.generateSendGramsQuery(from: key, localPassword: localPassword, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId).start(next: { result in
|
||||
guard let result = result as? TONPreparedSendGramsQuery else {
|
||||
subscriber.putError(.generic)
|
||||
return
|
||||
}
|
||||
subscriber.putNext(PendingWalletTransaction(timestamp: Int64(Date().timeIntervalSince1970), validUntilTimestamp: result.sentUntil, bodyHash: result.bodyHash, address: toAddress, value: amount, comment: textMessage))
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
}, error: { error in
|
||||
if let error = error as? TONError {
|
||||
@ -395,6 +395,131 @@ public final class TonInstance {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func prepareFakeSendGramsFromWalletQuery(walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: Data, timeout: Int32) -> Signal<TONPreparedSendGramsQuery, SendGramsFromWalletError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
impl.withInstance { ton in
|
||||
let cancel = ton.generateFakeSendGramsQuery(fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: true, timeout: timeout).start(next: { result in
|
||||
guard let result = result as? TONPreparedSendGramsQuery else {
|
||||
subscriber.putError(.generic)
|
||||
return
|
||||
}
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
}, error: { error in
|
||||
if let error = error as? TONError {
|
||||
if error.text.hasPrefix("INVALID_ACCOUNT_ADDRESS") {
|
||||
subscriber.putError(.invalidAddress)
|
||||
} else if error.text.hasPrefix("DANGEROUS_TRANSACTION") {
|
||||
subscriber.putError(.destinationIsNotInitialized)
|
||||
} else if error.text.hasPrefix("MESSAGE_TOO_LONG") {
|
||||
subscriber.putError(.messageTooLong)
|
||||
} else if error.text.hasPrefix("NOT_ENOUGH_FUNDS") {
|
||||
subscriber.putError(.notEnoughFunds)
|
||||
} else if error.text.hasPrefix("LITE_SERVER_") {
|
||||
subscriber.putError(.network)
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
disposable.set(ActionDisposable {
|
||||
cancel?.dispose()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func estimateSendGramsQueryFees(preparedQuery: TONPreparedSendGramsQuery) -> Signal<TONSendGramsQueryFees, SendGramsFromWalletError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
impl.withInstance { ton in
|
||||
let cancel = ton.estimateSendGramsQueryFees(preparedQuery).start(next: { result in
|
||||
guard let result = result as? TONSendGramsQueryFees else {
|
||||
subscriber.putError(.generic)
|
||||
return
|
||||
}
|
||||
subscriber.putNext(result)
|
||||
subscriber.putCompletion()
|
||||
}, error: { error in
|
||||
if let error = error as? TONError {
|
||||
if error.text.hasPrefix("INVALID_ACCOUNT_ADDRESS") {
|
||||
subscriber.putError(.invalidAddress)
|
||||
} else if error.text.hasPrefix("DANGEROUS_TRANSACTION") {
|
||||
subscriber.putError(.destinationIsNotInitialized)
|
||||
} else if error.text.hasPrefix("MESSAGE_TOO_LONG") {
|
||||
subscriber.putError(.messageTooLong)
|
||||
} else if error.text.hasPrefix("NOT_ENOUGH_FUNDS") {
|
||||
subscriber.putError(.notEnoughFunds)
|
||||
} else if error.text.hasPrefix("LITE_SERVER_") {
|
||||
subscriber.putError(.network)
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
}, completed: nil)
|
||||
disposable.set(ActionDisposable {
|
||||
cancel?.dispose()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func commitPreparedSendGramsQuery(_ preparedQuery: TONPreparedSendGramsQuery) -> Signal<Never, SendGramsFromWalletError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
impl.withInstance { ton in
|
||||
let cancel = ton.commit(preparedQuery).start(next: { result in
|
||||
preconditionFailure()
|
||||
}, error: { error in
|
||||
if let error = error as? TONError {
|
||||
if error.text.hasPrefix("INVALID_ACCOUNT_ADDRESS") {
|
||||
subscriber.putError(.invalidAddress)
|
||||
} else if error.text.hasPrefix("DANGEROUS_TRANSACTION") {
|
||||
subscriber.putError(.destinationIsNotInitialized)
|
||||
} else if error.text.hasPrefix("MESSAGE_TOO_LONG") {
|
||||
subscriber.putError(.messageTooLong)
|
||||
} else if error.text.hasPrefix("NOT_ENOUGH_FUNDS") {
|
||||
subscriber.putError(.notEnoughFunds)
|
||||
} else if error.text.hasPrefix("LITE_SERVER_") {
|
||||
subscriber.putError(.network)
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
disposable.set(ActionDisposable {
|
||||
cancel?.dispose()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func walletRestoreWords(publicKey: WalletPublicKey, decryptedSecret: Data, localPassword: Data) -> Signal<[String], WalletRestoreWordsError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
@ -769,12 +894,46 @@ public enum SendGramsFromWalletError {
|
||||
case network
|
||||
}
|
||||
|
||||
public struct EstimatedSendGramsFees {
|
||||
public let inFwdFee: Int64
|
||||
public let storageFee: Int64
|
||||
public let gasFee: Int64
|
||||
public let fwdFee: Int64
|
||||
}
|
||||
|
||||
public func verifySendGramsRequestAndEstimateFees(tonInstance: TonInstance, walletInfo: WalletInfo, toAddress: String, amount: Int64, textMessage: Data, timeout: Int32) -> Signal<EstimatedSendGramsFees, SendGramsFromWalletError> {
|
||||
return walletAddress(publicKey: walletInfo.publicKey, tonInstance: tonInstance)
|
||||
|> castError(SendGramsFromWalletError.self)
|
||||
|> mapToSignal { fromAddress -> Signal<EstimatedSendGramsFees, SendGramsFromWalletError> in
|
||||
return tonInstance.prepareFakeSendGramsFromWalletQuery(walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, timeout: timeout)
|
||||
|> mapToSignal { preparedQuery -> Signal<EstimatedSendGramsFees, SendGramsFromWalletError> in
|
||||
return tonInstance.estimateSendGramsQueryFees(preparedQuery: preparedQuery)
|
||||
|> map { result -> EstimatedSendGramsFees in
|
||||
return EstimatedSendGramsFees(inFwdFee: result.sourceFees.inFwdFee, storageFee: result.sourceFees.storageFee, gasFee: result.sourceFees.gasFee, fwdFee: result.sourceFees.fwdFee)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func sendGramsFromWallet(storage: WalletStorageInterface, tonInstance: TonInstance, walletInfo: WalletInfo, decryptedSecret: Data, localPassword: Data, toAddress: String, amount: Int64, textMessage: Data, forceIfDestinationNotInitialized: Bool, timeout: Int32, randomId: Int64) -> Signal<PendingWalletTransaction, SendGramsFromWalletError> {
|
||||
return walletAddress(publicKey: walletInfo.publicKey, tonInstance: tonInstance)
|
||||
|> castError(SendGramsFromWalletError.self)
|
||||
|> mapToSignal { fromAddress -> Signal<PendingWalletTransaction, SendGramsFromWalletError> in
|
||||
return tonInstance.sendGramsFromWallet(decryptedSecret: decryptedSecret, localPassword: localPassword, walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId)
|
||||
|> mapToSignal { result -> Signal<PendingWalletTransaction, SendGramsFromWalletError> in
|
||||
return tonInstance.prepareSendGramsFromWalletQuery(decryptedSecret: decryptedSecret, localPassword: localPassword, walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: forceIfDestinationNotInitialized, timeout: timeout, randomId: randomId)
|
||||
|> mapToSignal { preparedQuery -> Signal<PendingWalletTransaction, SendGramsFromWalletError> in
|
||||
return tonInstance.commitPreparedSendGramsQuery(preparedQuery)
|
||||
|> retryTonRequest(isNetworkError: { error in
|
||||
if case .network = error {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|> mapToSignal { _ -> Signal<PendingWalletTransaction, SendGramsFromWalletError> in
|
||||
return .complete()
|
||||
}
|
||||
|> then(.single(PendingWalletTransaction(timestamp: Int64(Date().timeIntervalSince1970), validUntilTimestamp: preparedQuery.validUntil, bodyHash: preparedQuery.bodyHash, address: toAddress, value: amount, comment: textMessage)))
|
||||
|> mapToSignal { result in
|
||||
return storage.updateWalletRecords { records in
|
||||
var records = records
|
||||
for i in 0 ..< records.count {
|
||||
@ -793,6 +952,7 @@ public func sendGramsFromWallet(storage: WalletStorageInterface, tonInstance: To
|
||||
|> castError(SendGramsFromWalletError.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct WalletTransactionId: Codable, Hashable {
|
||||
|
@ -347,6 +347,9 @@ public func walletSendScreen(context: WalletContext, randomId: Int64, walletInfo
|
||||
let presentationData = context.presentationData
|
||||
let state = stateValue.with { $0 }
|
||||
let amount = amountValue(state.amount)
|
||||
let commentData = state.comment.data(using: .utf8)
|
||||
let formattedAddress = String(state.address[state.address.startIndex..<state.address.index(state.address.startIndex, offsetBy: walletAddressLength / 2)] + " \n " + state.address[state.address.index(state.address.startIndex, offsetBy: walletAddressLength / 2)..<state.address.endIndex])
|
||||
let destinationAddress = state.address
|
||||
|
||||
updateState { state in
|
||||
var state = state
|
||||
@ -354,15 +357,28 @@ public func walletSendScreen(context: WalletContext, randomId: Int64, walletInfo
|
||||
return state
|
||||
}
|
||||
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
||||
presentControllerImpl?(controller, nil)
|
||||
|
||||
let _ = (verifySendGramsRequestAndEstimateFees(tonInstance: context.tonInstance, walletInfo: walletInfo, toAddress: destinationAddress, amount: amount, textMessage: commentData ?? Data(), timeout: 0)
|
||||
|> deliverOnMainQueue).start(next: { [weak controller] fees in
|
||||
controller?.dismiss()
|
||||
|
||||
let presentationData = context.presentationData
|
||||
|
||||
let title = NSAttributedString(string: presentationData.strings.Wallet_Send_Confirmation, font: Font.semibold(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
|
||||
let address = state.address[state.address.startIndex..<state.address.index(state.address.startIndex, offsetBy: walletAddressLength / 2)] + " \n " + state.address[state.address.index(state.address.startIndex, offsetBy: walletAddressLength / 2)..<state.address.endIndex]
|
||||
let feeAmount = fees.inFwdFee + fees.storageFee + fees.gasFee + fees.fwdFee
|
||||
|
||||
let text = presentationData.strings.Wallet_Send_ConfirmationText(formatBalanceText(amount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator), String(address)).0
|
||||
let (text, ranges) = presentationData.strings.Wallet_Send_ConfirmationText(formatBalanceText(amount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator), formattedAddress, "\(formatBalanceText(feeAmount, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))")
|
||||
let bodyAttributes = MarkdownAttributeSet(font: Font.regular(13.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
let boldAttributes = MarkdownAttributeSet(font: Font.semibold(13.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
let attributedText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: bodyAttributes, bold: boldAttributes, link: bodyAttributes, linkAttribute: { _ in return nil }), textAlignment: .center))
|
||||
attributedText.addAttribute(.font, value: Font.monospace(14.0), range: NSMakeRange(attributedText.string.count - address.count - 1, address.count))
|
||||
for (index, range) in ranges {
|
||||
if index == 1 {
|
||||
attributedText.addAttribute(.font, value: Font.monospace(14.0), range: range)
|
||||
}
|
||||
}
|
||||
|
||||
var dismissAlertImpl: ((Bool) -> Void)?
|
||||
let theme = context.presentationData.theme
|
||||
@ -414,6 +430,36 @@ public func walletSendScreen(context: WalletContext, randomId: Int64, walletInfo
|
||||
controller?.dismiss()
|
||||
}
|
||||
}
|
||||
}, error: { [weak controller] error in
|
||||
controller?.dismiss()
|
||||
|
||||
let presentationData = context.presentationData
|
||||
|
||||
var title: String?
|
||||
let text: String
|
||||
switch error {
|
||||
case .generic:
|
||||
text = presentationData.strings.Wallet_UnknownError
|
||||
case .network:
|
||||
title = presentationData.strings.Wallet_Send_NetworkErrorTitle
|
||||
text = presentationData.strings.Wallet_Send_NetworkErrorText
|
||||
case .notEnoughFunds:
|
||||
title = presentationData.strings.Wallet_Send_ErrorNotEnoughFundsTitle
|
||||
text = presentationData.strings.Wallet_Send_ErrorNotEnoughFundsText
|
||||
case .messageTooLong:
|
||||
text = presentationData.strings.Wallet_UnknownError
|
||||
case .invalidAddress:
|
||||
text = presentationData.strings.Wallet_Send_ErrorInvalidAddress
|
||||
case .secretDecryptionFailed:
|
||||
text = presentationData.strings.Wallet_Send_ErrorDecryptionFailed
|
||||
case .destinationIsNotInitialized:
|
||||
text = presentationData.strings.Wallet_UnknownError
|
||||
}
|
||||
let theme = presentationData.theme
|
||||
let controller = textAlertController(alertContext: AlertControllerContext(theme: theme.alert, themeSignal: .single(theme.alert)), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Wallet_Alert_OK, action: {
|
||||
})])
|
||||
presentControllerImpl?(controller, nil)
|
||||
})
|
||||
})
|
||||
|
||||
let walletState: Signal<WalletState?, NoError> = getCombinedWalletState(storage: context.storage, subject: .wallet(walletInfo), tonInstance: context.tonInstance, onlyCached: true)
|
||||
|
@ -403,8 +403,8 @@ public final class WalletStrings: Equatable {
|
||||
public func Wallet_Time_PreciseDate_m11(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[182]!, self._r[182]!, [_1, _2, _3])
|
||||
}
|
||||
public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[183]!, self._r[183]!, [_1, _2])
|
||||
public func Wallet_Send_ConfirmationText(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[183]!, self._r[183]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_Created_ExportErrorText: String { return self._s[185]! }
|
||||
public func Wallet_Updated_YesterdayAt(_ _0: String) -> (String, [(Int, NSRange)]) {
|
||||
|
@ -2283,7 +2283,7 @@ private final class WordCheckInputNode: ASDisplayNode, UITextFieldDelegate {
|
||||
self.backgroundNode = ASImageNode()
|
||||
self.backgroundNode.displaysAsynchronously = false
|
||||
self.backgroundNode.displayWithoutProcessing = true
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 10.0, color: theme.setup.inputBackgroundColor)
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: theme.setup.inputBackgroundColor)
|
||||
|
||||
self.labelNode = ImmediateTextNode()
|
||||
self.labelNode.attributedText = NSAttributedString(string: "\(index + 1):", font: Font.regular(17.0), textColor: theme.setup.inputPlaceholderColor)
|
||||
|
@ -22,6 +22,7 @@ ton_lib_names = [
|
||||
"crc32c",
|
||||
"keys",
|
||||
"lite-client-common",
|
||||
"smc-envelope",
|
||||
"tdactor",
|
||||
"tddb",
|
||||
"tdnet",
|
||||
|
6
submodules/ton/tonlib-src/CMakeLists.txt
vendored
6
submodules/ton/tonlib-src/CMakeLists.txt
vendored
@ -179,6 +179,7 @@ endif()
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
if (TON_ARCH AND NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${TON_ARCH}")
|
||||
@ -350,6 +351,9 @@ target_link_libraries(test-ed25519 PRIVATE ton_crypto)
|
||||
add_executable(test-vm test/test-td-main.cpp ${TONVM_TEST_SOURCE})
|
||||
target_link_libraries(test-vm PRIVATE ton_crypto fift-lib)
|
||||
|
||||
add_executable(test-smartcont test/test-td-main.cpp ${SMARTCONT_TEST_SOURCE})
|
||||
target_link_libraries(test-smartcont PRIVATE smc-envelope fift-lib ton_db)
|
||||
|
||||
add_executable(test-cells test/test-td-main.cpp ${CELLS_TEST_SOURCE})
|
||||
target_link_libraries(test-cells PRIVATE ton_crypto)
|
||||
|
||||
@ -385,10 +389,12 @@ endif()
|
||||
enable_testing()
|
||||
set(TEST_OPTIONS "--regression ${CMAKE_CURRENT_SOURCE_DIR}/test/regression-tests.ans --filter -Bench")
|
||||
separate_arguments(TEST_OPTIONS)
|
||||
add_test(test-ed25519-crypto crypto/test-ed25519-crypto)
|
||||
add_test(test-ed25519 test-ed25519)
|
||||
add_test(test-vm test-vm ${TEST_OPTIONS})
|
||||
add_test(test-fift test-fift ${TEST_OPTIONS})
|
||||
add_test(test-cells test-cells ${TEST_OPTIONS})
|
||||
add_test(test-smartcont test-smartcont)
|
||||
add_test(test-net test-net)
|
||||
add_test(test-actors test-tdactor)
|
||||
|
||||
|
@ -62,6 +62,9 @@ void AdnlExtClientImpl::hangup() {
|
||||
conn_ = {};
|
||||
is_closing_ = true;
|
||||
ref_cnt_--;
|
||||
for (auto &it : out_queries_) {
|
||||
td::actor::ActorOwn<>(it.second); // send hangup
|
||||
}
|
||||
try_stop();
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "common/bitstring.h"
|
||||
#include "common/errorcode.h"
|
||||
#include "td/utils/buffer.h"
|
||||
|
||||
#include <functional>
|
||||
@ -52,6 +53,9 @@ class AdnlQuery : public td::actor::Actor {
|
||||
}
|
||||
void tear_down() override {
|
||||
destroy_(id_);
|
||||
if (promise_) {
|
||||
promise_.set_error(td::Status::Error(ErrorCode::cancelled, "Cancelled"));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
24
submodules/ton/tonlib-src/common/int-to-string.hpp
Normal file
24
submodules/ton/tonlib-src/common/int-to-string.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "td/utils/int_types.h"
|
||||
#include "td/utils/Slice.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if_t<std::is_integral<T>::value, td::MutableSlice> store_int_to_slice(td::MutableSlice S,
|
||||
const T &v) {
|
||||
CHECK(S.size() >= sizeof(T));
|
||||
S.copy_from(td::Slice(reinterpret_cast<const td::uint8 *>(&v), sizeof(T)));
|
||||
return S.remove_prefix(sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if_t<std::is_integral<T>::value, T> fetch_int_from_slice(td::Slice S) {
|
||||
CHECK(S.size() >= sizeof(T));
|
||||
T v;
|
||||
td::MutableSlice(reinterpret_cast<td::uint8 *>(&v), sizeof(T)).copy_from(S.truncate(sizeof(T)));
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace ton
|
@ -88,6 +88,7 @@ set(TON_CRYPTO_SOURCE
|
||||
vm/cells/CellBuilder.cpp
|
||||
vm/cells/CellHash.cpp
|
||||
vm/cells/CellSlice.cpp
|
||||
vm/cells/CellString.cpp
|
||||
vm/cells/CellTraits.cpp
|
||||
vm/cells/CellUsageTree.cpp
|
||||
vm/cells/DataCell.cpp
|
||||
@ -99,6 +100,7 @@ set(TON_CRYPTO_SOURCE
|
||||
vm/cells/CellBuilder.h
|
||||
vm/cells/CellHash.h
|
||||
vm/cells/CellSlice.h
|
||||
vm/cells/CellString.h
|
||||
vm/cells/CellTraits.h
|
||||
vm/cells/CellUsageTree.h
|
||||
vm/cells/CellWithStorage.h
|
||||
@ -197,6 +199,24 @@ set(BLOCK_SOURCE
|
||||
block/transaction.h
|
||||
)
|
||||
|
||||
set(SMC_ENVELOPE_SOURCE
|
||||
smc-envelope/GenericAccount.cpp
|
||||
smc-envelope/MultisigWallet.cpp
|
||||
smc-envelope/SmartContract.cpp
|
||||
smc-envelope/SmartContractCode.cpp
|
||||
smc-envelope/TestGiver.cpp
|
||||
smc-envelope/TestWallet.cpp
|
||||
smc-envelope/Wallet.cpp
|
||||
|
||||
smc-envelope/GenericAccount.h
|
||||
smc-envelope/MultisigWallet.h
|
||||
smc-envelope/SmartContract.h
|
||||
smc-envelope/SmartContractCode.h
|
||||
smc-envelope/TestGiver.h
|
||||
smc-envelope/TestWallet.h
|
||||
smc-envelope/Wallet.h
|
||||
)
|
||||
|
||||
set(ED25519_TEST_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/Ed25519.cpp
|
||||
PARENT_SCOPE
|
||||
@ -217,6 +237,11 @@ set(TONVM_TEST_SOURCE
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(SMARTCONT_TEST_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/test-smartcont.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(FIFT_TEST_SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test/fift.cpp
|
||||
PARENT_SCOPE
|
||||
@ -279,6 +304,7 @@ if (TON_USE_ASAN AND NOT WIN32)
|
||||
set(TURN_OFF_LSAN export LSAN_OPTIONS=detect_leaks=0)
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY smartcont/auto)
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
set(GENERATE_TLB_CMD tlbc)
|
||||
add_custom_command(
|
||||
@ -295,29 +321,51 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||
add_custom_target(gen_fif ALL)
|
||||
function(GenFif)
|
||||
set(options )
|
||||
set(oneValueArgs DEST)
|
||||
set(oneValueArgs DEST NAME)
|
||||
set(multiValueArgs SOURCE)
|
||||
set(FUNC_LIB_SOURCE smartcont/stdlib.fc)
|
||||
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
||||
string(REGEX REPLACE "[^a-zA-Z_]" "_" ID ${ARG_DEST})
|
||||
set(ARG_DEST_FIF "${ARG_DEST}.fif")
|
||||
add_custom_command(
|
||||
COMMENT "Generate ${ARG_DEST}"
|
||||
COMMENT "Generate ${ARG_DEST_FIF}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND func -PS -o ${ARG_DEST} ${FUNC_LIB_SOURCE} ${ARG_SOURCE}
|
||||
COMMAND func -PS -o ${ARG_DEST_FIF} ${FUNC_LIB_SOURCE} ${ARG_SOURCE}
|
||||
MAIN_DEPENDENCY ${ARG_SOURCE}
|
||||
DEPENDS func ${FUNC_LIB_SOURCE}
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST}
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_FIF}
|
||||
)
|
||||
add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST})
|
||||
set(ARG_DEST_CPP "${ARG_DEST}.cpp")
|
||||
add_custom_command(
|
||||
COMMENT "Generate ${ARG_DEST_CPP}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND fift -Ifift/lib:smartcont -s asm-to-cpp.fif ${ARG_DEST_FIF} ${ARG_DEST_CPP} ${ARG_NAME}
|
||||
MAIN_DEPENDENCY ${ARG_SOURCE}
|
||||
DEPENDS fift ${ARG_DEST_FIF} smartcont/asm-to-cpp.fif
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_CPP}
|
||||
)
|
||||
add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST_FIF} ${ARG_DEST_CPP})
|
||||
add_dependencies(gen_fif gen_fif_${ID})
|
||||
endfunction()
|
||||
|
||||
GenFif(DEST smartcont/config-code.fif SOURCE smartcont/config-code.fc)
|
||||
GenFif(DEST smartcont/wallet-code.fif SOURCE smartcont/wallet-code.fc)
|
||||
GenFif(DEST smartcont/simple-wallet-code.fif SOURCE smartcont/simple-wallet-code.fc)
|
||||
GenFif(DEST smartcont/highload-wallet-code.fif SOURCE smartcont/highload-wallet-code.fc)
|
||||
GenFif(DEST smartcont/highload-wallet-v2-code.fif SOURCE smartcont/highload-wallet-v2-code.fc)
|
||||
GenFif(DEST smartcont/elector-code.fif SOURCE smartcont/elector-code.fc)
|
||||
GenFif(DEST smartcont/auto/config-code SOURCE smartcont/config-code.fc NAME config)
|
||||
GenFif(DEST smartcont/auto/wallet-code SOURCE smartcont/wallet-code.fc NAME wallet)
|
||||
GenFif(DEST smartcont/auto/simple-wallet-code SOURCE smartcont/simple-wallet-code.fc NAME simple-wallet)
|
||||
GenFif(DEST smartcont/auto/highload-wallet-code SOURCE smartcont/highload-wallet-code.fc NAME highload-wallet)
|
||||
GenFif(DEST smartcont/auto/highload-wallet-v2-code SOURCE smartcont/highload-wallet-v2-code.fc NAME highoad-wallet-v2)
|
||||
GenFif(DEST smartcont/auto/elector-code SOURCE smartcont/elector-code.fc NAME elector-code)
|
||||
GenFif(DEST smartcont/auto/multisig-code SOURCE smartcont/multisig-code.fc NAME multisig)
|
||||
GenFif(DEST smartcont/auto/restricted-wallet-code SOURCE smartcont/restricted-wallet-code.fc NAME restricted-wallet)
|
||||
GenFif(DEST smartcont/auto/restricted-wallet2-code SOURCE smartcont/restricted-wallet2-code.fc NAME restricted-wallet2)
|
||||
|
||||
GenFif(DEST smartcont/auto/simple-wallet-ext-code SOURCE smartcont/simple-wallet-ext-code.fc NAME simple-wallet-ext)
|
||||
endif()
|
||||
|
||||
add_library(smc-envelope ${SMC_ENVELOPE_SOURCE})
|
||||
target_include_directories(smc-envelope PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
target_link_libraries(smc-envelope PUBLIC ton_crypto PRIVATE tdutils ton_block)
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
add_dependencies(smc-envelope gen_fif)
|
||||
endif()
|
||||
|
||||
add_executable(create-state block/create-state.cpp)
|
||||
|
@ -10481,7 +10481,7 @@ bool BlockInfo::skip(vm::CellSlice& cs) const {
|
||||
&& cs.advance(392)
|
||||
&& (!not_master || cs.advance_refs(1))
|
||||
&& cs.advance_refs(1)
|
||||
&& (!vert_seq_no || cs.advance_refs(1));
|
||||
&& (!vert_seqno_incr || cs.advance_refs(1));
|
||||
}
|
||||
|
||||
bool BlockInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
|
||||
@ -10501,7 +10501,7 @@ bool BlockInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
|
||||
&& cs.advance(288)
|
||||
&& (!not_master || t_BlkMasterInfo.validate_skip_ref(cs, weak))
|
||||
&& BlkPrevInfo{after_merge}.validate_skip_ref(cs, weak)
|
||||
&& (!vert_seq_no || t_BlkPrevInfo_0.validate_skip_ref(cs, weak));
|
||||
&& (!vert_seqno_incr || t_BlkPrevInfo_0.validate_skip_ref(cs, weak));
|
||||
}
|
||||
|
||||
bool BlockInfo::unpack(vm::CellSlice& cs, BlockInfo::Record& data) const {
|
||||
@ -10531,7 +10531,7 @@ bool BlockInfo::unpack(vm::CellSlice& cs, BlockInfo::Record& data) const {
|
||||
&& cs.fetch_uint_to(32, data.prev_key_block_seqno)
|
||||
&& (!data.not_master || cs.fetch_ref_to(data.master_ref))
|
||||
&& cs.fetch_ref_to(data.prev_ref)
|
||||
&& (!data.vert_seq_no || cs.fetch_ref_to(data.prev_vert_ref));
|
||||
&& (!data.vert_seqno_incr || cs.fetch_ref_to(data.prev_vert_ref));
|
||||
}
|
||||
|
||||
bool BlockInfo::cell_unpack(Ref<vm::Cell> cell_ref, BlockInfo::Record& data) const {
|
||||
@ -10567,7 +10567,7 @@ bool BlockInfo::pack(vm::CellBuilder& cb, const BlockInfo::Record& data) const {
|
||||
&& cb.store_ulong_rchk_bool(data.prev_key_block_seqno, 32)
|
||||
&& (!data.not_master || cb.store_ref_bool(data.master_ref))
|
||||
&& cb.store_ref_bool(data.prev_ref)
|
||||
&& (!data.vert_seq_no || cb.store_ref_bool(data.prev_vert_ref));
|
||||
&& (!data.vert_seqno_incr || cb.store_ref_bool(data.prev_vert_ref));
|
||||
}
|
||||
|
||||
bool BlockInfo::cell_pack(Ref<vm::Cell>& cell_ref, const BlockInfo::Record& data) const {
|
||||
@ -10613,7 +10613,7 @@ bool BlockInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
|
||||
&& (!not_master || (pp.field("master_ref") && t_BlkMasterInfo.print_ref(pp, cs.fetch_ref())))
|
||||
&& pp.field("prev_ref")
|
||||
&& BlkPrevInfo{after_merge}.print_ref(pp, cs.fetch_ref())
|
||||
&& (!vert_seq_no || (pp.field("prev_vert_ref") && t_BlkPrevInfo_0.print_ref(pp, cs.fetch_ref())))
|
||||
&& (!vert_seqno_incr || (pp.field("prev_vert_ref") && t_BlkPrevInfo_0.print_ref(pp, cs.fetch_ref())))
|
||||
&& pp.close();
|
||||
}
|
||||
|
||||
|
@ -4466,7 +4466,7 @@ struct BlockInfo::Record {
|
||||
unsigned prev_key_block_seqno; // prev_key_block_seqno : uint32
|
||||
Ref<Cell> master_ref; // master_ref : not_master?^BlkMasterInfo
|
||||
Ref<Cell> prev_ref; // prev_ref : ^(BlkPrevInfo after_merge)
|
||||
Ref<Cell> prev_vert_ref; // prev_vert_ref : vert_seq_no?^(BlkPrevInfo 0)
|
||||
Ref<Cell> prev_vert_ref; // prev_vert_ref : vert_seqno_incr?^(BlkPrevInfo 0)
|
||||
Record() = default;
|
||||
Record(unsigned _version, bool _not_master, bool _after_merge, bool _before_split, bool _after_split, bool _want_split, bool _want_merge, bool _key_block, bool _vert_seqno_incr, int _flags, int _seq_no, int _vert_seq_no, Ref<CellSlice> _shard, unsigned _gen_utime, unsigned long long _start_lt, unsigned long long _end_lt, unsigned _gen_validator_list_hash_short, unsigned _gen_catchain_seqno, unsigned _min_ref_mc_seqno, unsigned _prev_key_block_seqno, Ref<Cell> _master_ref, Ref<Cell> _prev_ref, Ref<Cell> _prev_vert_ref) : version(_version), not_master(_not_master), after_merge(_after_merge), before_split(_before_split), after_split(_after_split), want_split(_want_split), want_merge(_want_merge), key_block(_key_block), vert_seqno_incr(_vert_seqno_incr), flags(_flags), seq_no(_seq_no), vert_seq_no(_vert_seq_no), shard(std::move(_shard)), gen_utime(_gen_utime), start_lt(_start_lt), end_lt(_end_lt), gen_validator_list_hash_short(_gen_validator_list_hash_short), gen_catchain_seqno(_gen_catchain_seqno), min_ref_mc_seqno(_min_ref_mc_seqno), prev_key_block_seqno(_prev_key_block_seqno), master_ref(std::move(_master_ref)), prev_ref(std::move(_prev_ref)), prev_vert_ref(std::move(_prev_vert_ref)) {}
|
||||
};
|
||||
|
@ -718,12 +718,9 @@ td::Status ShardState::unpack_state(ton::BlockIdExt blkid, Ref<vm::Cell> prev_st
|
||||
return td::Status::Error(-666, "shardchain state for "s + blkid.to_str() +
|
||||
" corresponds to incorrect workchain or shard " + shard1.to_str());
|
||||
}
|
||||
if (state.vert_seq_no) {
|
||||
return td::Status::Error(
|
||||
-666, "shardchain state for "s + blkid.to_str() + " has non-zero vert_seq_no, which is unsupported");
|
||||
}
|
||||
id_ = blkid;
|
||||
root_ = std::move(prev_state_root);
|
||||
vert_seqno_ = state.vert_seq_no;
|
||||
before_split_ = state.before_split;
|
||||
account_dict_ = std::make_unique<vm::AugmentedDictionary>(
|
||||
vm::load_cell_slice(std::move(state.accounts)).prefetch_ref(), 256, block::tlb::aug_ShardAccounts);
|
||||
@ -811,7 +808,7 @@ td::Status ShardState::unpack_out_msg_queue_info(Ref<vm::Cell> out_msg_queue_inf
|
||||
}
|
||||
out_msg_queue_ =
|
||||
std::make_unique<vm::AugmentedDictionary>(std::move(qinfo.out_queue), 352, block::tlb::aug_OutMsgQueue);
|
||||
if (verbosity >= 3 * 0) {
|
||||
if (verbosity >= 3 * 1) {
|
||||
LOG(DEBUG) << "unpacking ProcessedUpto of our previous block " << id_.to_str();
|
||||
block::gen::t_ProcessedInfo.print(std::cerr, qinfo.proc_info);
|
||||
}
|
||||
@ -953,14 +950,16 @@ td::Status ShardState::merge_with(ShardState& sib) {
|
||||
lt_ = std::max(lt_, sib.lt_);
|
||||
// 9. compute underload & overload history
|
||||
underload_history_ = overload_history_ = 0;
|
||||
// 10. compute vert_seqno
|
||||
vert_seqno_ = std::max(vert_seqno_, sib.vert_seqno_);
|
||||
// Anything else? add here
|
||||
// ...
|
||||
|
||||
// 10. compute new root
|
||||
// 100. compute new root
|
||||
if (!block::gen::t_ShardState.cell_pack_split_state(root_, std::move(root_), std::move(sib.root_))) {
|
||||
return td::Status::Error(-667, "cannot construct a virtual split_state after a merge");
|
||||
}
|
||||
// 11. invalidate sibling, change id_ to the (virtual) common parent
|
||||
// 101. invalidate sibling, change id_ to the (virtual) common parent
|
||||
sib.invalidate();
|
||||
id_.id.shard = shard.shard;
|
||||
id_.file_hash.set_zero();
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <ostream>
|
||||
#include "tl/tlblib.hpp"
|
||||
#include "td/utils/bits.h"
|
||||
#include "td/utils/CancellationToken.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
#include "ton/ton-types.h"
|
||||
|
||||
@ -162,12 +163,12 @@ struct MsgProcessedUpto {
|
||||
MsgProcessedUpto(ton::ShardId _shard, ton::BlockSeqno _mcseqno, ton::LogicalTime _lt, td::ConstBitPtr _hash)
|
||||
: shard(_shard), mc_seqno(_mcseqno), last_inmsg_lt(_lt), last_inmsg_hash(_hash) {
|
||||
}
|
||||
bool operator<(const MsgProcessedUpto& other) const & {
|
||||
bool operator<(const MsgProcessedUpto& other) const& {
|
||||
return shard < other.shard || (shard == other.shard && mc_seqno < other.mc_seqno);
|
||||
}
|
||||
bool contains(const MsgProcessedUpto& other) const &;
|
||||
bool contains(const MsgProcessedUpto& other) const&;
|
||||
bool contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash,
|
||||
ton::BlockSeqno other_mc_seqno) const &;
|
||||
ton::BlockSeqno other_mc_seqno) const&;
|
||||
// NB: this is for checking whether we have already imported an internal message
|
||||
bool already_processed(const EnqueuedMsgDescr& msg) const;
|
||||
};
|
||||
@ -384,7 +385,7 @@ struct ShardState {
|
||||
int global_id_;
|
||||
ton::UnixTime utime_;
|
||||
ton::LogicalTime lt_;
|
||||
ton::BlockSeqno mc_blk_seqno_, min_ref_mc_seqno_;
|
||||
ton::BlockSeqno mc_blk_seqno_, min_ref_mc_seqno_, vert_seqno_;
|
||||
ton::BlockIdExt mc_blk_ref_;
|
||||
ton::LogicalTime mc_blk_lt_;
|
||||
bool before_split_{false};
|
||||
@ -573,7 +574,7 @@ struct BlockProofChain {
|
||||
bool last_link_incomplete() const {
|
||||
return !links.empty() && last_link().incomplete();
|
||||
}
|
||||
td::Status validate();
|
||||
td::Status validate(td::CancellationToken cancellation_token = {});
|
||||
};
|
||||
|
||||
int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull old_shard, ton::ShardIdFull subshard);
|
||||
|
@ -421,7 +421,7 @@ block_info#9bc7a987 version:uint32
|
||||
prev_key_block_seqno:uint32
|
||||
master_ref:not_master?^BlkMasterInfo
|
||||
prev_ref:^(BlkPrevInfo after_merge)
|
||||
prev_vert_ref:vert_seq_no?^(BlkPrevInfo 0)
|
||||
prev_vert_ref:vert_seqno_incr?^(BlkPrevInfo 0)
|
||||
= BlockInfo;
|
||||
|
||||
prev_blk_info$_ prev:ExtBlkRef = BlkPrevInfo 0;
|
||||
|
@ -32,7 +32,7 @@ namespace block {
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
td::Status check_block_header_proof(td::Ref<vm::Cell> root, ton::BlockIdExt blkid, ton::Bits256* store_shard_hash_to,
|
||||
bool check_state_hash, td::uint32* save_utime) {
|
||||
bool check_state_hash, td::uint32* save_utime, ton::LogicalTime* save_lt) {
|
||||
ton::RootHash vhash{root->get_hash().bits()};
|
||||
if (vhash != blkid.root_hash) {
|
||||
return td::Status::Error(PSTRING() << " block header for block " << blkid.to_str() << " has incorrect root hash "
|
||||
@ -50,6 +50,9 @@ td::Status check_block_header_proof(td::Ref<vm::Cell> root, ton::BlockIdExt blki
|
||||
if (save_utime) {
|
||||
*save_utime = info.gen_utime;
|
||||
}
|
||||
if (save_lt) {
|
||||
*save_lt = info.end_lt;
|
||||
}
|
||||
if (store_shard_hash_to) {
|
||||
vm::CellSlice upd_cs{vm::NoVmSpec(), blk.state_update};
|
||||
if (!(upd_cs.is_special() && upd_cs.prefetch_long(8) == 4 // merkle update
|
||||
@ -157,7 +160,7 @@ td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td:
|
||||
|
||||
td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr,
|
||||
td::Ref<vm::Cell> root, ton::LogicalTime* last_trans_lt, ton::Bits256* last_trans_hash,
|
||||
td::uint32* save_utime) {
|
||||
td::uint32* save_utime, ton::LogicalTime* save_lt) {
|
||||
TRY_RESULT_PREFIX(Q_roots, vm::std_boc_deserialize_multi(std::move(proof)), "cannot deserialize account proof");
|
||||
if (Q_roots.size() != 2) {
|
||||
return td::Status::Error(PSLICE() << "account state proof must have exactly two roots");
|
||||
@ -174,7 +177,7 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const
|
||||
}
|
||||
ton::Bits256 state_hash = state_root->get_hash().bits();
|
||||
TRY_STATUS_PREFIX(check_block_header_proof(vm::MerkleProof::virtualize(std::move(Q_roots[0]), 1), shard_blk,
|
||||
&state_hash, true, save_utime),
|
||||
&state_hash, true, save_utime, save_lt),
|
||||
"error in account shard block header proof : ");
|
||||
block::gen::ShardStateUnsplit::Record sstate;
|
||||
if (!(tlb::unpack_cell(std::move(state_root), sstate))) {
|
||||
@ -218,8 +221,6 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const
|
||||
td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const {
|
||||
TRY_RESULT_PREFIX(root, vm::std_boc_deserialize(state.as_slice(), true), "cannot deserialize account state");
|
||||
|
||||
LOG(INFO) << "got account state for " << addr << " with respect to blocks " << blk.to_str()
|
||||
<< (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str());
|
||||
if (blk != ref_blk && ref_blk.id.seqno != ~0U) {
|
||||
return td::Status::Error(PSLICE() << "obtained getAccountState() for a different reference block " << blk.to_str()
|
||||
<< " instead of requested " << ref_blk.to_str());
|
||||
@ -238,7 +239,7 @@ td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, b
|
||||
|
||||
Info res;
|
||||
TRY_STATUS(block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt,
|
||||
&res.last_trans_hash, &res.gen_utime));
|
||||
&res.last_trans_hash, &res.gen_utime, &res.gen_lt));
|
||||
res.root = std::move(root);
|
||||
|
||||
return res;
|
||||
@ -424,7 +425,7 @@ td::Status BlockProofLink::validate(td::uint32* save_utime) const {
|
||||
}
|
||||
}
|
||||
|
||||
td::Status BlockProofChain::validate() {
|
||||
td::Status BlockProofChain::validate(td::CancellationToken cancellation_token) {
|
||||
valid = false;
|
||||
has_key_block = false;
|
||||
has_utime = false;
|
||||
@ -450,6 +451,9 @@ td::Status BlockProofChain::validate() {
|
||||
<< link.from.to_str() << " but the previous link ends at different block "
|
||||
<< cur.to_str());
|
||||
}
|
||||
if (cancellation_token) {
|
||||
return td::Status::Error("Cancelled");
|
||||
}
|
||||
auto err = link.validate(&last_utime);
|
||||
if (err.is_error()) {
|
||||
return td::Status::Error(PSTRING() << "link #" << i << " in BlockProofChain is invalid: " << err.to_string());
|
||||
|
@ -26,11 +26,12 @@ using td::Ref;
|
||||
|
||||
td::Status check_block_header_proof(td::Ref<vm::Cell> root, ton::BlockIdExt blkid,
|
||||
ton::Bits256* store_shard_hash_to = nullptr, bool check_state_hash = false,
|
||||
td::uint32* save_utime = nullptr);
|
||||
td::uint32* save_utime = nullptr, ton::LogicalTime* save_lt = nullptr);
|
||||
td::Status check_shard_proof(ton::BlockIdExt blk, ton::BlockIdExt shard_blk, td::Slice shard_proof);
|
||||
td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const block::StdAddress& addr,
|
||||
td::Ref<vm::Cell> root, ton::LogicalTime* last_trans_lt = nullptr,
|
||||
ton::Bits256* last_trans_hash = nullptr, td::uint32* save_utime = nullptr);
|
||||
ton::Bits256* last_trans_hash = nullptr, td::uint32* save_utime = nullptr,
|
||||
ton::LogicalTime* save_lt = nullptr);
|
||||
td::Result<td::Bits256> check_state_proof(ton::BlockIdExt blkid, td::Slice proof);
|
||||
td::Result<Ref<vm::Cell>> check_extract_state_proof(ton::BlockIdExt blkid, td::Slice proof, td::Slice data);
|
||||
|
||||
@ -48,6 +49,7 @@ struct AccountState {
|
||||
td::Ref<vm::Cell> root;
|
||||
ton::LogicalTime last_trans_lt = 0;
|
||||
ton::Bits256 last_trans_hash;
|
||||
ton::LogicalTime gen_lt{0};
|
||||
td::uint32 gen_utime{0};
|
||||
};
|
||||
|
||||
|
@ -517,6 +517,58 @@ 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 {
|
||||
GasLimitsPrices res;
|
||||
auto id = is_masterchain ? 20 : 21;
|
||||
auto cell = get_config_param(id);
|
||||
if (cell.is_null()) {
|
||||
return td::Status::Error(PSLICE() << "configuration parameter " << id << " with gas prices is absent");
|
||||
}
|
||||
auto cs = vm::load_cell_slice(std::move(cell));
|
||||
block::gen::GasLimitsPrices::Record_gas_flat_pfx flat;
|
||||
if (tlb::unpack(cs, flat)) {
|
||||
cs = *flat.other;
|
||||
res.flat_gas_limit = flat.flat_gas_limit;
|
||||
res.flat_gas_price = flat.flat_gas_price;
|
||||
}
|
||||
auto f = [&](const auto& r, td::uint64 spec_limit) {
|
||||
res.gas_limit = r.gas_limit;
|
||||
res.special_gas_limit = spec_limit;
|
||||
res.gas_credit = r.gas_credit;
|
||||
res.gas_price = r.gas_price;
|
||||
res.freeze_due_limit = r.freeze_due_limit;
|
||||
res.delete_due_limit = r.delete_due_limit;
|
||||
};
|
||||
block::gen::GasLimitsPrices::Record_gas_prices_ext rec;
|
||||
if (tlb::unpack(cs, rec)) {
|
||||
f(rec, rec.special_gas_limit);
|
||||
} else {
|
||||
block::gen::GasLimitsPrices::Record_gas_prices rec0;
|
||||
if (tlb::unpack(cs, rec0)) {
|
||||
f(rec0, rec0.gas_limit);
|
||||
} else {
|
||||
return td::Status::Error(PSLICE() << "configuration parameter " << id
|
||||
<< " with gas prices is invalid - can't parse");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
td::Result<MsgPrices> Config::get_msg_prices(bool is_masterchain) const {
|
||||
auto id = is_masterchain ? 24 : 25;
|
||||
auto cell = get_config_param(id);
|
||||
if (cell.is_null()) {
|
||||
return td::Status::Error(PSLICE() << "configuration parameter " << id << " with msg prices is absent");
|
||||
}
|
||||
auto cs = vm::load_cell_slice(std::move(cell));
|
||||
block::gen::MsgForwardPrices::Record rec;
|
||||
if (!tlb::unpack(cs, rec)) {
|
||||
return td::Status::Error(PSLICE() << "configuration parameter " << id
|
||||
<< " with msg prices is invalid - can't parse");
|
||||
}
|
||||
return MsgPrices(rec.lump_price, rec.bit_price, rec.cell_price, rec.ihr_price_factor, rec.first_frac, rec.next_frac);
|
||||
}
|
||||
|
||||
CatchainValidatorsConfig Config::unpack_catchain_validators_config(Ref<vm::Cell> cell) {
|
||||
block::gen::CatchainConfig::Record cfg;
|
||||
if (cell.is_null() || !tlb::unpack_cell(std::move(cell), cfg)) {
|
||||
@ -1019,8 +1071,8 @@ 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 {
|
||||
[&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)) {
|
||||
@ -1415,7 +1467,7 @@ 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() ](
|
||||
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;
|
||||
|
@ -50,7 +50,7 @@ struct ValidatorDescr {
|
||||
: pubkey(_pubkey), weight(_weight), cum_weight(_cum_weight) {
|
||||
adnl_addr.set_zero();
|
||||
}
|
||||
bool operator<(td::uint64 wt_pos) const & {
|
||||
bool operator<(td::uint64 wt_pos) const& {
|
||||
return cum_weight < wt_pos;
|
||||
}
|
||||
};
|
||||
@ -327,6 +327,46 @@ struct StoragePrices {
|
||||
, mc_bit_price(_mc_bprice)
|
||||
, mc_cell_price(_mc_cprice) {
|
||||
}
|
||||
static td::RefInt256 compute_storage_fees(ton::UnixTime now, const std::vector<block::StoragePrices>& pricing,
|
||||
const vm::CellStorageStat& storage_stat, ton::UnixTime last_paid,
|
||||
bool is_special, bool is_masterchain);
|
||||
};
|
||||
|
||||
struct GasLimitsPrices {
|
||||
td::uint64 flat_gas_limit{0};
|
||||
td::uint64 flat_gas_price{0};
|
||||
td::uint64 gas_price{0};
|
||||
td::uint64 special_gas_limit{0};
|
||||
td::uint64 gas_limit{0};
|
||||
td::uint64 gas_credit{0};
|
||||
td::uint64 block_gas_limit{0};
|
||||
td::uint64 freeze_due_limit{0};
|
||||
td::uint64 delete_due_limit{0};
|
||||
|
||||
td::RefInt256 compute_gas_price(td::uint64 gas_used) const;
|
||||
};
|
||||
|
||||
// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms
|
||||
// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms
|
||||
// bits in the root cell of a message are not included in msg.bits (lump_price pays for them)
|
||||
|
||||
struct MsgPrices {
|
||||
td::uint64 lump_price;
|
||||
td::uint64 bit_price;
|
||||
td::uint64 cell_price;
|
||||
td::uint32 ihr_factor;
|
||||
td::uint32 first_frac;
|
||||
td::uint32 next_frac;
|
||||
td::uint64 compute_fwd_fees(td::uint64 cells, td::uint64 bits) const;
|
||||
std::pair<td::uint64, td::uint64> compute_fwd_ihr_fees(td::uint64 cells, td::uint64 bits,
|
||||
bool ihr_disabled = false) const;
|
||||
MsgPrices() = default;
|
||||
MsgPrices(td::uint64 lump, td::uint64 bitp, td::uint64 cellp, td::uint32 ihrf, td::uint32 firstf, td::uint32 nextf)
|
||||
: lump_price(lump), bit_price(bitp), cell_price(cellp), ihr_factor(ihrf), first_frac(firstf), next_frac(nextf) {
|
||||
}
|
||||
td::RefInt256 get_first_part(td::RefInt256 total) const;
|
||||
td::uint64 get_first_part(td::uint64 total) const;
|
||||
td::RefInt256 get_next_part(td::RefInt256 total) const;
|
||||
};
|
||||
|
||||
struct CatchainValidatorsConfig {
|
||||
@ -499,6 +539,8 @@ class Config {
|
||||
bool is_special_smartcontract(const ton::StdSmcAddress& addr) const;
|
||||
static td::Result<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;
|
||||
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;
|
||||
td::Status visit_validator_params() const;
|
||||
@ -556,7 +598,7 @@ class ConfigInfo : public Config, public ShardConfig {
|
||||
needAccountsRoot = 64,
|
||||
needPrevBlocks = 128
|
||||
};
|
||||
int vert_seqno{-1};
|
||||
ton::BlockSeqno vert_seqno{~0U};
|
||||
int global_id_{0};
|
||||
ton::UnixTime utime{0};
|
||||
ton::LogicalTime lt{0};
|
||||
@ -604,6 +646,9 @@ class ConfigInfo : public Config, public ShardConfig {
|
||||
Ref<vm::Cell> get_state_extra_root() const {
|
||||
return state_extra_root_;
|
||||
}
|
||||
ton::BlockSeqno get_vert_seqno() const {
|
||||
return vert_seqno;
|
||||
}
|
||||
ton::CatchainSeqno get_shard_cc_seqno(ton::ShardIdFull shard) const;
|
||||
bool get_last_key_block(ton::BlockIdExt& blkid, ton::LogicalTime& blklt, bool strict = false) const;
|
||||
bool get_old_mc_block_id(ton::BlockSeqno seqno, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const;
|
||||
|
@ -421,7 +421,9 @@ void add_partial_storage_payment(td::BigInt256& payment, ton::UnixTime delta, co
|
||||
payment += b;
|
||||
}
|
||||
|
||||
td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector<block::StoragePrices>& pricing) const {
|
||||
td::RefInt256 StoragePrices::compute_storage_fees(ton::UnixTime now, const std::vector<block::StoragePrices>& pricing,
|
||||
const vm::CellStorageStat& storage_stat, ton::UnixTime last_paid,
|
||||
bool is_special, bool is_masterchain) {
|
||||
if (now <= last_paid || !last_paid || is_special || pricing.empty() || now <= pricing[0].valid_since) {
|
||||
return {};
|
||||
}
|
||||
@ -438,7 +440,7 @@ td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector
|
||||
ton::UnixTime valid_until = (i < n - 1 ? std::min(now, pricing[i + 1].valid_since) : now);
|
||||
if (upto < valid_until) {
|
||||
assert(upto >= pricing[i].valid_since);
|
||||
add_partial_storage_payment(total.unique_write(), valid_until - upto, pricing[i], storage_stat, is_masterchain());
|
||||
add_partial_storage_payment(total.unique_write(), valid_until - upto, pricing[i], storage_stat, is_masterchain);
|
||||
}
|
||||
upto = valid_until;
|
||||
}
|
||||
@ -446,6 +448,10 @@ td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector
|
||||
return total;
|
||||
}
|
||||
|
||||
td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector<block::StoragePrices>& pricing) const {
|
||||
return StoragePrices::compute_storage_fees(now, pricing, storage_stat, last_paid, is_special, is_masterchain());
|
||||
}
|
||||
|
||||
Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime req_start_lt, ton::UnixTime _now,
|
||||
Ref<vm::Cell> _inmsg)
|
||||
: trans_type(ttype)
|
||||
@ -739,7 +745,8 @@ td::uint64 ComputePhaseConfig::gas_bought_for(td::RefInt256 nanograms) const {
|
||||
}
|
||||
|
||||
td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const {
|
||||
return td::rshift(gas_price256 * gas_used, 16, 1);
|
||||
return gas_used <= flat_gas_limit ? td::make_refint(flat_gas_price)
|
||||
: td::rshift(gas_price256 * (gas_used - flat_gas_limit), 16, 1) + flat_gas_price;
|
||||
}
|
||||
|
||||
bool Transaction::compute_gas_limits(ComputePhase& cp, const ComputePhaseConfig& cfg) {
|
||||
@ -805,7 +812,6 @@ bool Transaction::prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputeP
|
||||
}
|
||||
|
||||
Ref<vm::Tuple> Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
|
||||
// TODO: fix initialization of c7
|
||||
td::BitArray<256> rand_seed;
|
||||
td::RefInt256 rand_seed_int{true};
|
||||
if (!(prepare_rand_seed(rand_seed, cfg) && rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false))) {
|
||||
@ -969,7 +975,7 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
|
||||
gas = vm.get_gas_limits();
|
||||
cp.gas_used = std::min<long long>(gas.gas_consumed(), gas.gas_limit);
|
||||
cp.accepted = (gas.gas_credit == 0);
|
||||
cp.success = (cp.accepted && (unsigned)cp.exit_code <= 1);
|
||||
cp.success = (cp.accepted && vm.committed());
|
||||
if (cp.accepted & use_msg_state) {
|
||||
was_activated = true;
|
||||
acc_status = Account::acc_active;
|
||||
@ -978,8 +984,8 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
|
||||
<< ", limit=" << gas.gas_limit << ", credit=" << gas.gas_credit;
|
||||
LOG(INFO) << "out_of_gas=" << cp.out_of_gas << ", accepted=" << cp.accepted << ", success=" << cp.success;
|
||||
if (cp.success) {
|
||||
cp.new_data = vm.get_c4(); // c4 -> persistent data
|
||||
cp.actions = vm.get_d(5); // c5 -> action list
|
||||
cp.new_data = vm.get_committed_state().c4; // c4 -> persistent data
|
||||
cp.actions = vm.get_committed_state().c5; // c5 -> action list
|
||||
int out_act_num = output_actions_count(cp.actions);
|
||||
if (verbosity > 2) {
|
||||
std::cerr << "new smart contract data: ";
|
||||
@ -1304,9 +1310,9 @@ bool Transaction::check_rewrite_dest_addr(Ref<vm::CellSlice>& dest_addr, const A
|
||||
int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap, const ActionPhaseConfig& cfg,
|
||||
int redoing) {
|
||||
block::gen::OutAction::Record_action_send_msg act_rec;
|
||||
// mode: +128 = attach all remaining balance, +64 = attach all remaining balance of the inbound message, +1 = pay message fees, +2 = skip if message cannot be sent
|
||||
// mode: +128 = attach all remaining balance, +64 = attach all remaining balance of the inbound message, +32 = delete smart contract if balance becomes zero, +1 = pay message fees, +2 = skip if message cannot be sent
|
||||
vm::CellSlice cs{cs0};
|
||||
if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xc3) || (act_rec.mode & 0xc0) == 0xc0) {
|
||||
if (!tlb::unpack_exact(cs, act_rec) || (act_rec.mode & ~0xe3) || (act_rec.mode & 0xc0) == 0xc0) {
|
||||
return -1;
|
||||
}
|
||||
bool skip_invalid = (act_rec.mode & 2);
|
||||
@ -1573,7 +1579,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
|
||||
ap.total_action_fees += fees_collected;
|
||||
ap.total_fwd_fees += fees_total;
|
||||
|
||||
if (act_rec.mode & 0x80) {
|
||||
if ((act_rec.mode & 0xa0) == 0xa0) {
|
||||
CHECK(ap.remaining_balance.is_zero());
|
||||
ap.acc_delete_req = ap.reserved_balance.is_zero();
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ struct NewOutMsg {
|
||||
NewOutMsg(ton::LogicalTime _lt, Ref<vm::Cell> _msg, Ref<vm::Cell> _trans)
|
||||
: lt(_lt), msg(std::move(_msg)), trans(std::move(_trans)) {
|
||||
}
|
||||
bool operator<(const NewOutMsg& other) const & {
|
||||
bool operator<(const NewOutMsg& other) const& {
|
||||
return lt < other.lt || (lt == other.lt && msg->get_hash() < other.msg->get_hash());
|
||||
}
|
||||
bool operator>(const NewOutMsg& other) const & {
|
||||
bool operator>(const NewOutMsg& other) const& {
|
||||
return lt > other.lt || (lt == other.lt && other.msg->get_hash() < msg->get_hash());
|
||||
}
|
||||
};
|
||||
@ -132,29 +132,6 @@ struct ComputePhaseConfig {
|
||||
bool parse_GasLimitsPrices(Ref<vm::Cell> cell, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit);
|
||||
};
|
||||
|
||||
// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms
|
||||
// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms
|
||||
// bits in the root cell of a message are not included in msg.bits (lump_price pays for them)
|
||||
|
||||
struct MsgPrices {
|
||||
td::uint64 lump_price;
|
||||
td::uint64 bit_price;
|
||||
td::uint64 cell_price;
|
||||
td::uint32 ihr_factor;
|
||||
td::uint32 first_frac;
|
||||
td::uint32 next_frac;
|
||||
td::uint64 compute_fwd_fees(td::uint64 cells, td::uint64 bits) const;
|
||||
std::pair<td::uint64, td::uint64> compute_fwd_ihr_fees(td::uint64 cells, td::uint64 bits,
|
||||
bool ihr_disabled = false) const;
|
||||
MsgPrices() = default;
|
||||
MsgPrices(td::uint64 lump, td::uint64 bitp, td::uint64 cellp, td::uint32 ihrf, td::uint32 firstf, td::uint32 nextf)
|
||||
: lump_price(lump), bit_price(bitp), cell_price(cellp), ihr_factor(ihrf), first_frac(firstf), next_frac(nextf) {
|
||||
}
|
||||
td::RefInt256 get_first_part(td::RefInt256 total) const;
|
||||
td::uint64 get_first_part(td::uint64 total) const;
|
||||
td::RefInt256 get_next_part(td::RefInt256 total) const;
|
||||
};
|
||||
|
||||
struct ActionPhaseConfig {
|
||||
int max_actions{255};
|
||||
MsgPrices fwd_std;
|
||||
|
@ -224,6 +224,8 @@ class BitSliceGen {
|
||||
BitSliceGen(BitSliceGen&& bs, unsigned _offs, unsigned _len);
|
||||
BitSliceGen(Pt* _ptr, unsigned _len) : ref(), ptr(_ptr), offs(0), len(_len) {
|
||||
}
|
||||
explicit BitSliceGen(Slice slice) : BitSliceGen(slice.data(), slice.size() * 8) {
|
||||
}
|
||||
~BitSliceGen() {
|
||||
}
|
||||
Pt* get_ptr() const {
|
||||
|
@ -756,6 +756,12 @@ x{EDF9} @Defop BOOLEVAL
|
||||
{ PUSHINT c3 PREPAREVAR } cond
|
||||
} dup : PREPARE : PREPAREDICT
|
||||
//
|
||||
// inline support
|
||||
{ dup sbits { @addop } {
|
||||
dup srefs 1- abort"exactly one reference expected in inline"
|
||||
ref@ CALLREF } cond
|
||||
} : INLINE
|
||||
//
|
||||
// throwing and handling exceptions
|
||||
{ dup 6 ufits
|
||||
{ <b x{F22_} s, swap 6 u, }
|
||||
@ -964,11 +970,14 @@ x{F4B7} @Defop SUBDICTURPGET
|
||||
|
||||
x{F800} @Defop ACCEPT
|
||||
x{F801} @Defop SETGASLIMIT
|
||||
x{F80F} @Defop COMMIT
|
||||
|
||||
x{F82} @Defop(4u) GETPARAM
|
||||
x{F823} @Defop NOW
|
||||
x{F824} @Defop BLOCKLT
|
||||
x{F825} @Defop LTIME
|
||||
x{F826} @Defop BALANCE
|
||||
x{F827} @Defop RANDSEED
|
||||
x{F828} @Defop MYADDR
|
||||
x{F829} @Defop CONFIGROOT
|
||||
x{F830} @Defop CONFIGDICT
|
||||
@ -1047,6 +1056,7 @@ x{FFF0} @Defop SETCPX
|
||||
//
|
||||
variable @proccnt
|
||||
variable @proclist
|
||||
variable @procdict
|
||||
19 constant @procdictkeylen
|
||||
{ @proclist @ cons @proclist ! } : @proclistadd
|
||||
{ dup @procdictkeylen fits not abort"procedure index out of range"
|
||||
@ -1061,26 +1071,39 @@ variable @proclist
|
||||
{ swap @declproc }
|
||||
cond } : DECLMETHOD
|
||||
"main" @proclistadd
|
||||
dictnew
|
||||
dictnew @procdict !
|
||||
} : PROGRAM{
|
||||
{ dup sbits 1000 > { s>c <b swap ref, b> <s } if } : @adj-long-proc
|
||||
{ // d i s
|
||||
@adj-long-proc swap rot @procdictkeylen idict!+ not abort"cannot define procedure, redefined?"
|
||||
} : PROC
|
||||
{ 2dup swap @procdictkeylen idict@ abort"procedure already defined"
|
||||
1 { -rot @normal? b> <s PROC } does @doafter<{
|
||||
} : PROC:<{
|
||||
{ 0 swap @procdictkeylen idict@ not abort"`main` procedure not defined" drop
|
||||
{ over sbits < { s>c <b swap ref, b> <s } if } : @adj-long-proc
|
||||
{ // i s l
|
||||
@adj-long-proc swap @procdict @ @procdictkeylen
|
||||
idict!+ not abort"cannot define procedure, redefined?"
|
||||
@procdict !
|
||||
} : @def-proc
|
||||
{ 1000 @def-proc } : PROC
|
||||
{ 0 @def-proc } : PROCREF
|
||||
{ @procdict @ @procdictkeylen idict@ abort"procedure already defined"
|
||||
} : @fail-ifdef
|
||||
{ over @fail-ifdef
|
||||
2 { rot @normal? rot b> <s swap @def-proc drop } does
|
||||
null swap @doafter<{
|
||||
} : @PROC:<{
|
||||
{ 1000 @PROC:<{ } : PROC:<{
|
||||
{ 0 @PROC:<{ } : PROCREF:<{
|
||||
{ dup @procdict @ @procdictkeylen idict@
|
||||
{ nip INLINE } { CALLDICT } cond
|
||||
} dup : INLINECALL : INLINECALLDICT
|
||||
{ 0 @procdict @ @procdictkeylen idict@ not abort"`main` procedure not defined" drop
|
||||
} : @chkmaindef
|
||||
{ dup @chkmaindef
|
||||
{ @chkmaindef
|
||||
@proclist @ { dup null? not } {
|
||||
uncons swap dup find not
|
||||
{ +": undefined procedure name in list" abort } if
|
||||
execute 3 pick @procdictkeylen idict@ not
|
||||
execute @procdict @ @procdictkeylen idict@ not
|
||||
{ +": procedure declared but left undefined" abort } if
|
||||
drop (forget)
|
||||
} while
|
||||
drop @proclist null! @proccnt 0!
|
||||
@procdict dup @ swap null!
|
||||
} : }END
|
||||
forget @proclist forget @proccnt
|
||||
{ }END <{ SETCP0 swap @procdictkeylen DICTPUSHCONST DICTIGETJMP 11 THROWARG }> } : }END>
|
||||
|
@ -42,8 +42,8 @@
|
||||
{ dup 10 < { 48 } { 55 } cond + } : Digit
|
||||
{ dup 10 < { 48 } { 87 } cond + } : digit
|
||||
// x s b -- x' s'
|
||||
{ -rot swap rot /mod Digit rot swap hold } : B#
|
||||
{ -rot swap rot /mod digit rot swap hold } : b#
|
||||
{ rot swap /mod Digit rot swap hold } : B#
|
||||
{ rot swap /mod digit rot swap hold } : b#
|
||||
{ 16 B# } : X#
|
||||
{ 16 b# } : x#
|
||||
// x s b -- 0 s'
|
||||
@ -110,3 +110,4 @@ variable base
|
||||
{ null ' cons rot times } : list
|
||||
{ true (atom) drop } : atom
|
||||
{ bl word atom 1 'nop } ::_ `
|
||||
{ hole dup 1 { @ execute } does create } : recursive
|
||||
|
@ -123,3 +123,28 @@ forget val, forget val@ forget .val
|
||||
{ 0 lib+ } : private_lib
|
||||
// ( D c -- D' ) Add public library c to collection D
|
||||
{ 1 lib+ } : public_lib
|
||||
|
||||
// serialize simple transfers with long comments
|
||||
// b B n -- b'
|
||||
recursive append-long-bytes {
|
||||
over Blen over <= { drop B, } {
|
||||
B| <b swap 127 append-long-bytes b> -rot B, swap ref,
|
||||
} cond
|
||||
} swap !
|
||||
// b S n -- b'
|
||||
{ swap $>B swap append-long-bytes } : append-long-string
|
||||
// S -- c
|
||||
{ <b over $len { 0 32 u, swap 36 append-long-string } { nip } cond b>
|
||||
} : simple-transfer-body
|
||||
|
||||
// ( S -- x ) parse public key
|
||||
{ dup $len 48 <> abort"public key must be 48 characters long"
|
||||
base64>B dup Blen 36 <> abort"public key must be 48 characters long"
|
||||
34 B| 16 B>u@ over crc16 <> abort"crc16 mismatch in public key"
|
||||
16 B>u@+ 0x3ee6 <> abort"invalid tag in public key"
|
||||
256 B>u@
|
||||
} : parse-pubkey
|
||||
{ bl word parse-pubkey 1 'nop } ::_ PK'
|
||||
// ( x -- S ) serialize public key
|
||||
{ 256 u>B B{3ee6} swap B+ dup crc16 16 u>B B+ B>base64 } : pubkey>$
|
||||
{ pubkey>$ type } : .pubkey
|
||||
|
@ -43,6 +43,9 @@ td::Result<std::string> load_TonUtil_fif(std::string dir = "") {
|
||||
td::Result<std::string> load_Lists_fif(std::string dir = "") {
|
||||
return load_source("Lists.fif", dir);
|
||||
}
|
||||
td::Result<std::string> load_Lisp_fif(std::string dir = "") {
|
||||
return load_source("Lisp.fif", dir);
|
||||
}
|
||||
|
||||
class MemoryFileLoader : public fift::FileLoader {
|
||||
public:
|
||||
@ -91,7 +94,8 @@ class MemoryFileLoader : public fift::FileLoader {
|
||||
};
|
||||
|
||||
td::Result<fift::SourceLookup> create_source_lookup(std::string main, bool need_preamble = true, bool need_asm = true,
|
||||
bool need_ton_util = true, std::string dir = "") {
|
||||
bool need_ton_util = true, bool need_lisp = true,
|
||||
std::string dir = "") {
|
||||
auto loader = std::make_unique<MemoryFileLoader>();
|
||||
loader->add_file("/main.fif", std::move(main));
|
||||
if (need_preamble) {
|
||||
@ -112,6 +116,10 @@ td::Result<fift::SourceLookup> create_source_lookup(std::string main, bool need_
|
||||
loader->add_file("/TonUtil.fif", std::move(f));
|
||||
}
|
||||
}
|
||||
if (need_lisp) {
|
||||
TRY_RESULT(f, load_Lisp_fif(dir));
|
||||
loader->add_file("/Lisp.fif", std::move(f));
|
||||
}
|
||||
auto res = fift::SourceLookup(std::move(loader));
|
||||
res.add_include_path("/");
|
||||
return std::move(res);
|
||||
@ -143,7 +151,7 @@ td::Result<fift::SourceLookup> run_fift(fift::SourceLookup source_lookup, std::o
|
||||
} // namespace
|
||||
td::Result<FiftOutput> mem_run_fift(std::string source, std::vector<std::string> args, std::string fift_dir) {
|
||||
std::stringstream ss;
|
||||
TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, fift_dir));
|
||||
TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, true, fift_dir));
|
||||
TRY_RESULT_ASSIGN(source_lookup, run_fift(std::move(source_lookup), &ss, true, std::move(args)));
|
||||
FiftOutput res;
|
||||
res.source_lookup = std::move(source_lookup);
|
||||
@ -159,8 +167,8 @@ td::Result<FiftOutput> mem_run_fift(SourceLookup source_lookup, std::vector<std:
|
||||
return std::move(res);
|
||||
}
|
||||
td::Result<fift::SourceLookup> create_mem_source_lookup(std::string main, std::string fift_dir, bool need_preamble,
|
||||
bool need_asm, bool need_ton_util) {
|
||||
return create_source_lookup(main, need_preamble, need_asm, need_ton_util, fift_dir);
|
||||
bool need_asm, bool need_ton_util, bool need_lisp) {
|
||||
return create_source_lookup(main, need_preamble, need_asm, need_ton_util, need_lisp, fift_dir);
|
||||
}
|
||||
|
||||
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir, bool is_raw) {
|
||||
@ -168,7 +176,7 @@ td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_d
|
||||
TRY_RESULT(source_lookup,
|
||||
create_source_lookup(PSTRING() << "\"Asm.fif\" include\n " << (is_raw ? "<{" : "") << asm_code << "\n"
|
||||
<< (is_raw ? "}>c" : "") << " boc>B \"res\" B>file",
|
||||
true, true, true, fift_dir));
|
||||
true, true, true, false, fift_dir));
|
||||
TRY_RESULT(res, run_fift(std::move(source_lookup), &ss));
|
||||
TRY_RESULT(boc, res.read_file("res"));
|
||||
return vm::std_boc_deserialize(std::move(boc.data));
|
||||
|
@ -28,7 +28,7 @@ struct FiftOutput {
|
||||
};
|
||||
td::Result<fift::SourceLookup> create_mem_source_lookup(std::string main, std::string fift_dir = "",
|
||||
bool need_preamble = true, bool need_asm = true,
|
||||
bool need_ton_util = true);
|
||||
bool need_ton_util = true, bool need_lisp = true);
|
||||
td::Result<FiftOutput> mem_run_fift(std::string source, std::vector<std::string> args = {}, std::string fift_dir = "");
|
||||
td::Result<FiftOutput> mem_run_fift(SourceLookup source_lookup, std::vector<std::string> args);
|
||||
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir = "", bool is_raw = true);
|
||||
|
@ -614,6 +614,43 @@ void interpret_str_reverse(vm::Stack& stack) {
|
||||
stack.push_string(std::move(s));
|
||||
}
|
||||
|
||||
void interpret_utf8_str_len(vm::Stack& stack) {
|
||||
std::string s = stack.pop_string();
|
||||
long long cnt = 0;
|
||||
for (char c : s) {
|
||||
if ((c & 0xc0) != 0x80) {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
stack.push_smallint(cnt);
|
||||
}
|
||||
|
||||
void interpret_utf8_str_split(vm::Stack& stack) {
|
||||
stack.check_underflow(2);
|
||||
unsigned c = stack.pop_smallint_range(0xffff);
|
||||
std::string s = stack.pop_string();
|
||||
if (c > s.size()) {
|
||||
throw IntError{"not enough utf8 characters for cutting"};
|
||||
}
|
||||
auto it = s.begin();
|
||||
for (; it < s.end(); ++it) {
|
||||
if ((*it & 0xc0) != 0x80) {
|
||||
if (!c) {
|
||||
stack.push_string(std::string{s.begin(), it});
|
||||
stack.push_string(std::string{it, s.end()});
|
||||
return;
|
||||
}
|
||||
--c;
|
||||
}
|
||||
}
|
||||
if (!c) {
|
||||
stack.push_string(std::move(s));
|
||||
stack.push_string(std::string{});
|
||||
} else {
|
||||
throw IntError{"not enough utf8 characters for cutting"};
|
||||
}
|
||||
}
|
||||
|
||||
void interpret_str_remove_trailing_int(vm::Stack& stack, int arg) {
|
||||
char x = (char)(arg ? arg : stack.pop_long_range(127));
|
||||
std::string s = stack.pop_string();
|
||||
@ -1797,6 +1834,16 @@ void interpret_char(IntCtx& ctx) {
|
||||
push_argcount(ctx, 1);
|
||||
}
|
||||
|
||||
void interpret_char_internal(vm::Stack& stack) {
|
||||
auto s = stack.pop_string();
|
||||
int len = (s.size() < 10 ? (int)s.size() : 10);
|
||||
int code = str_utf8_code(s.c_str(), len);
|
||||
if (code < 0 || s.size() != (unsigned)len) {
|
||||
throw IntError{"exactly one character expected"};
|
||||
}
|
||||
stack.push_smallint(code);
|
||||
}
|
||||
|
||||
int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool allow_frac = true,
|
||||
bool throw_error = false) {
|
||||
if (allow_frac) {
|
||||
@ -2149,7 +2196,23 @@ void interpret_run_vm(IntCtx& ctx, bool with_gas) {
|
||||
OstreamLogger ostream_logger(ctx.error_stream);
|
||||
auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
|
||||
vm::GasLimits gas{gas_limit};
|
||||
int res = vm::run_vm_code(cs, ctx.stack, 3, &data, log, nullptr, &gas);
|
||||
int res = vm::run_vm_code(cs, ctx.stack, 1, &data, log, nullptr, &gas, get_vm_libraries());
|
||||
ctx.stack.push_smallint(res);
|
||||
ctx.stack.push_cell(std::move(data));
|
||||
if (with_gas) {
|
||||
ctx.stack.push_smallint(gas.gas_consumed());
|
||||
}
|
||||
}
|
||||
|
||||
void interpret_run_vm_c7(IntCtx& ctx, bool with_gas) {
|
||||
long long gas_limit = with_gas ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
|
||||
auto c7 = ctx.stack.pop_tuple();
|
||||
auto data = ctx.stack.pop_cell();
|
||||
auto cs = ctx.stack.pop_cellslice();
|
||||
OstreamLogger ostream_logger(ctx.error_stream);
|
||||
auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
|
||||
vm::GasLimits gas{gas_limit};
|
||||
int res = vm::run_vm_code(cs, ctx.stack, 1, &data, log, nullptr, &gas, get_vm_libraries(), std::move(c7));
|
||||
ctx.stack.push_smallint(res);
|
||||
ctx.stack.push_cell(std::move(data));
|
||||
if (with_gas) {
|
||||
@ -2278,6 +2341,21 @@ void interpret_get_cmdline_arg(IntCtx& ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void interpret_getenv(vm::Stack& stack) {
|
||||
auto str = stack.pop_string();
|
||||
auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr;
|
||||
stack.push_string(value ? std::string{value} : "");
|
||||
}
|
||||
|
||||
void interpret_getenv_exists(vm::Stack& stack) {
|
||||
auto str = stack.pop_string();
|
||||
auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr;
|
||||
if (value) {
|
||||
stack.push_string(std::string{value});
|
||||
}
|
||||
stack.push_bool((bool)value);
|
||||
}
|
||||
|
||||
// x1 .. xn n 'w -->
|
||||
void interpret_execute_internal(IntCtx& ctx) {
|
||||
Ref<WordDef> word_def = pop_exec_token(ctx);
|
||||
@ -2315,7 +2393,7 @@ void compile_one_literal(WordList& wlist, vm::StackEntry val) {
|
||||
auto x = std::move(val).as_int();
|
||||
if (!x->signed_fits_bits(257)) {
|
||||
throw IntError{"invalid numeric literal"};
|
||||
} else if (x->signed_fits_bits(64)) {
|
||||
} else if (x->signed_fits_bits(td::BigIntInfo::word_shift)) {
|
||||
wlist.push_back(Ref<StackWord>{true, std::bind(interpret_const, _1, x->to_long())});
|
||||
} else {
|
||||
wlist.push_back(Ref<StackWord>{true, std::bind(interpret_big_const, _1, std::move(x))});
|
||||
@ -2465,6 +2543,7 @@ void init_words_common(Dictionary& d) {
|
||||
// char/string manipulation
|
||||
d.def_active_word("\"", interpret_quote_str);
|
||||
d.def_active_word("char ", interpret_char);
|
||||
d.def_stack_word("(char) ", interpret_char_internal);
|
||||
d.def_ctx_word("emit ", interpret_emit);
|
||||
d.def_ctx_word("space ", std::bind(interpret_emit_const, _1, ' '));
|
||||
d.def_ctx_word("cr ", std::bind(interpret_emit_const, _1, '\n'));
|
||||
@ -2484,6 +2563,8 @@ void init_words_common(Dictionary& d) {
|
||||
d.def_stack_word("-trailing0 ", std::bind(interpret_str_remove_trailing_int, _1, '0'));
|
||||
d.def_stack_word("$len ", interpret_str_len);
|
||||
d.def_stack_word("Blen ", interpret_bytes_len);
|
||||
d.def_stack_word("$Len ", interpret_utf8_str_len);
|
||||
d.def_stack_word("$Split ", interpret_utf8_str_split);
|
||||
d.def_ctx_word("Bx. ", std::bind(interpret_bytes_hex_print_raw, _1, true));
|
||||
d.def_stack_word("B>X ", std::bind(interpret_bytes_to_hex, _1, true));
|
||||
d.def_stack_word("B>x ", std::bind(interpret_bytes_to_hex, _1, false));
|
||||
@ -2572,6 +2653,8 @@ void init_words_common(Dictionary& d) {
|
||||
d.def_ctx_word("file-exists? ", interpret_file_exists);
|
||||
// custom & crypto
|
||||
d.def_ctx_word("now ", interpret_now);
|
||||
d.def_stack_word("getenv ", interpret_getenv);
|
||||
d.def_stack_word("getenv? ", interpret_getenv_exists);
|
||||
d.def_stack_word("newkeypair ", interpret_new_keypair);
|
||||
d.def_stack_word("priv>pub ", interpret_priv_key_to_pub);
|
||||
d.def_stack_word("ed25519_sign ", interpret_ed25519_sign);
|
||||
@ -2696,6 +2779,8 @@ void init_words_vm(Dictionary& d) {
|
||||
d.def_ctx_word("gasrunvmdict ", std::bind(interpret_run_vm_dict, _1, true));
|
||||
d.def_ctx_word("runvm ", std::bind(interpret_run_vm, _1, false));
|
||||
d.def_ctx_word("gasrunvm ", std::bind(interpret_run_vm, _1, true));
|
||||
d.def_ctx_word("runvmctx ", std::bind(interpret_run_vm_c7, _1, false));
|
||||
d.def_ctx_word("gasrunvmctx ", std::bind(interpret_run_vm_c7, _1, true));
|
||||
d.def_ctx_word("dbrunvm ", interpret_db_run_vm);
|
||||
d.def_ctx_word("dbrunvm-parallel ", interpret_db_run_vm_parallel);
|
||||
}
|
||||
|
@ -205,6 +205,9 @@ void VarDescr::clear_value() {
|
||||
}
|
||||
|
||||
void VarDescrList::show(std::ostream& os) const {
|
||||
if (unreachable) {
|
||||
os << "<unreachable> ";
|
||||
}
|
||||
os << "[";
|
||||
for (const auto& v : list) {
|
||||
os << ' ' << v;
|
||||
|
@ -272,6 +272,12 @@ VarDescrList& VarDescrList::operator+=(const VarDescrList& y) {
|
||||
}
|
||||
|
||||
VarDescrList VarDescrList::operator|(const VarDescrList& y) const {
|
||||
if (y.unreachable) {
|
||||
return *this;
|
||||
}
|
||||
if (unreachable) {
|
||||
return y;
|
||||
}
|
||||
VarDescrList res;
|
||||
auto it1 = list.cbegin();
|
||||
auto it2 = y.list.cbegin();
|
||||
@ -289,7 +295,11 @@ VarDescrList VarDescrList::operator|(const VarDescrList& y) const {
|
||||
}
|
||||
|
||||
VarDescrList& VarDescrList::operator|=(const VarDescrList& y) {
|
||||
if (y.unreachable) {
|
||||
return *this;
|
||||
} else {
|
||||
return *this = *this | y;
|
||||
}
|
||||
}
|
||||
|
||||
VarDescrList& VarDescrList::operator&=(const VarDescrList& values) {
|
||||
@ -299,14 +309,20 @@ VarDescrList& VarDescrList::operator&=(const VarDescrList& values) {
|
||||
*item &= vd;
|
||||
}
|
||||
}
|
||||
unreachable |= values.unreachable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VarDescrList& VarDescrList::import_values(const VarDescrList& values) {
|
||||
for (const VarDescr& vd : values.list) {
|
||||
VarDescr* item = operator[](vd.idx);
|
||||
if (item) {
|
||||
item->set_value(vd);
|
||||
if (values.unreachable) {
|
||||
set_unreachable();
|
||||
} else
|
||||
for (auto& vd : list) {
|
||||
auto new_vd = values[vd.idx];
|
||||
if (new_vd) {
|
||||
vd.set_value(*new_vd);
|
||||
} else {
|
||||
vd.clear_value();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
@ -658,8 +674,11 @@ void Op::prepare_args(VarDescrList values) {
|
||||
const VarDescr* val = values[right[i]];
|
||||
if (val) {
|
||||
args[i].set_value(*val);
|
||||
args[i].clear_unused();
|
||||
// args[i].clear_unused();
|
||||
} else {
|
||||
args[i].clear_value();
|
||||
}
|
||||
args[i].clear_unused();
|
||||
}
|
||||
}
|
||||
|
||||
@ -670,7 +689,7 @@ VarDescrList Op::fwd_analyze(VarDescrList values) {
|
||||
case _Import:
|
||||
break;
|
||||
case _Return:
|
||||
values.list.clear();
|
||||
values.set_unreachable();
|
||||
break;
|
||||
case _IntConst: {
|
||||
values.add_newval(left[0]).set_const(int_const);
|
||||
|
@ -193,21 +193,21 @@ void AsmOp::out(std::ostream& os) const {
|
||||
os << (b ? "SWAP" : "NOP");
|
||||
break;
|
||||
}
|
||||
os << "s" << a << " s" << b << " XCHG";
|
||||
os << SReg(a) << ' ' << SReg(b) << " XCHG";
|
||||
break;
|
||||
case a_push:
|
||||
if (!(a & -2)) {
|
||||
os << (a ? "OVER" : "DUP");
|
||||
break;
|
||||
}
|
||||
os << "s" << a << " PUSH";
|
||||
os << SReg(a) << " PUSH";
|
||||
break;
|
||||
case a_pop:
|
||||
if (!(a & -2)) {
|
||||
os << (a ? "NIP" : "DROP");
|
||||
break;
|
||||
}
|
||||
os << "s" << a << " POP";
|
||||
os << SReg(a) << " POP";
|
||||
break;
|
||||
default:
|
||||
throw src::Fatal{"unknown assembler operation"};
|
||||
|
@ -50,13 +50,13 @@ void define_builtin_func(std::string name, TypeExpr* func_type, const T& func, b
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void define_builtin_func_x(std::string name, TypeExpr* func_type, const T& func, std::initializer_list<int> arg_order,
|
||||
void define_builtin_func(std::string name, TypeExpr* func_type, const T& func, std::initializer_list<int> arg_order,
|
||||
std::initializer_list<int> ret_order = {}, bool impure = false) {
|
||||
SymDef* def = predefine_builtin_func(name, func_type);
|
||||
def->value = new SymValAsmFunc{func_type, func, arg_order, ret_order, impure};
|
||||
}
|
||||
|
||||
void define_builtin_func_x(std::string name, TypeExpr* func_type, const AsmOp& macro,
|
||||
void define_builtin_func(std::string name, TypeExpr* func_type, const AsmOp& macro,
|
||||
std::initializer_list<int> arg_order, std::initializer_list<int> ret_order = {},
|
||||
bool impure = false) {
|
||||
SymDef* def = predefine_builtin_func(name, func_type);
|
||||
@ -429,10 +429,14 @@ AsmOp compile_mul(std::vector<VarDescr>& res, std::vector<VarDescr>& args) {
|
||||
}
|
||||
return exec_arg_op("MULCONST", y.int_const, 1);
|
||||
}
|
||||
if (k >= 0) {
|
||||
if (k > 0) {
|
||||
y.unused();
|
||||
return exec_arg_op("LSHIFT#", k, 1);
|
||||
}
|
||||
if (k == 0) {
|
||||
y.unused();
|
||||
return AsmOp::Nop();
|
||||
}
|
||||
}
|
||||
if (x.is_int_const()) {
|
||||
int k = is_pos_pow2(x.int_const);
|
||||
@ -451,10 +455,14 @@ AsmOp compile_mul(std::vector<VarDescr>& res, std::vector<VarDescr>& args) {
|
||||
}
|
||||
return exec_arg_op("MULCONST", x.int_const, 1);
|
||||
}
|
||||
if (k >= 0) {
|
||||
if (k > 0) {
|
||||
x.unused();
|
||||
return exec_arg_op("LSHIFT#", k, 1);
|
||||
}
|
||||
if (k == 0) {
|
||||
x.unused();
|
||||
return AsmOp::Nop();
|
||||
}
|
||||
}
|
||||
return exec_op("MUL", 2);
|
||||
}
|
||||
@ -668,6 +676,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
||||
return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v != 0);
|
||||
}
|
||||
int v = compute_compare(x, y, mode);
|
||||
// std::cerr << "compute_compare(" << x << ", " << y << ", " << mode << ") = " << v << std::endl;
|
||||
assert(v);
|
||||
if (!(v & (v - 1))) {
|
||||
r.set_const(v - (v >> 2) - 2);
|
||||
@ -685,6 +694,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
||||
if (v & 4) {
|
||||
r.val &= VarDescr::ConstOne;
|
||||
}
|
||||
// std::cerr << "result: " << r << std::endl;
|
||||
static const char* cmp_int_names[] = {"", "GTINT", "EQINT", "GTINT", "LESSINT", "NEQINT", "LESSINT"};
|
||||
static const char* cmp_names[] = {"", "GREATER", "EQUAL", "GEQ", "LESS", "NEQ", "LEQ", "CMP"};
|
||||
static int cmp_int_delta[] = {0, 0, 0, -1, 0, 0, 1};
|
||||
@ -846,10 +856,7 @@ void define_builtins() {
|
||||
auto X = TypeExpr::new_var();
|
||||
auto Y = TypeExpr::new_var();
|
||||
auto Z = TypeExpr::new_var();
|
||||
auto T = TypeExpr::new_var();
|
||||
auto XY = TypeExpr::new_tensor({X, Y});
|
||||
auto XYZ = TypeExpr::new_tensor({X, Y, Z});
|
||||
auto XYZT = TypeExpr::new_tensor({X, Y, Z, T});
|
||||
auto arith_bin_op = TypeExpr::new_map(Int2, Int);
|
||||
auto arith_un_op = TypeExpr::new_map(Int, Int);
|
||||
auto impure_bin_op = TypeExpr::new_map(Int2, Unit);
|
||||
@ -867,16 +874,20 @@ void define_builtins() {
|
||||
define_builtin_func("-_", arith_un_op, compile_negate);
|
||||
define_builtin_func("_*_", arith_bin_op, compile_mul);
|
||||
define_builtin_func("_/_", arith_bin_op, std::bind(compile_div, _1, _2, -1));
|
||||
define_builtin_func("_/~_", arith_bin_op, std::bind(compile_div, _1, _2, 0));
|
||||
define_builtin_func("_/^_", arith_bin_op, std::bind(compile_div, _1, _2, 1));
|
||||
define_builtin_func("_~/_", arith_bin_op, std::bind(compile_div, _1, _2, 0));
|
||||
define_builtin_func("_^/_", arith_bin_op, std::bind(compile_div, _1, _2, 1));
|
||||
define_builtin_func("_%_", arith_bin_op, std::bind(compile_mod, _1, _2, -1));
|
||||
define_builtin_func("_%~_", arith_bin_op, std::bind(compile_mod, _1, _2, 0));
|
||||
define_builtin_func("_%^_", arith_bin_op, std::bind(compile_mod, _1, _2, -1));
|
||||
define_builtin_func("_~%_", arith_bin_op, std::bind(compile_mod, _1, _2, 0));
|
||||
define_builtin_func("_^%_", arith_bin_op, std::bind(compile_mod, _1, _2, 1));
|
||||
define_builtin_func("_/%_", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2));
|
||||
define_builtin_func("divmod", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2));
|
||||
define_builtin_func("~divmod", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2));
|
||||
define_builtin_func("moddiv", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2), {}, {1, 0});
|
||||
define_builtin_func("~moddiv", TypeExpr::new_map(Int2, Int2), AsmOp::Custom("DIVMOD", 2, 2), {}, {1, 0});
|
||||
define_builtin_func("_<<_", arith_bin_op, compile_lshift);
|
||||
define_builtin_func("_>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, -1));
|
||||
define_builtin_func("_>>~_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0));
|
||||
define_builtin_func("_>>^_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1));
|
||||
define_builtin_func("_~>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0));
|
||||
define_builtin_func("_^>>_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1));
|
||||
define_builtin_func("_&_", arith_bin_op, AsmOp::Custom("AND", 2));
|
||||
define_builtin_func("_|_", arith_bin_op, AsmOp::Custom("OR", 2));
|
||||
define_builtin_func("_^_", arith_bin_op, AsmOp::Custom("XOR", 2));
|
||||
@ -885,15 +896,15 @@ void define_builtins() {
|
||||
define_builtin_func("^_-=_", arith_bin_op, compile_sub);
|
||||
define_builtin_func("^_*=_", arith_bin_op, compile_mul);
|
||||
define_builtin_func("^_/=_", arith_bin_op, std::bind(compile_div, _1, _2, -1));
|
||||
define_builtin_func("^_/~=_", arith_bin_op, std::bind(compile_div, _1, _2, 0));
|
||||
define_builtin_func("^_/^=_", arith_bin_op, std::bind(compile_div, _1, _2, 1));
|
||||
define_builtin_func("^_~/=_", arith_bin_op, std::bind(compile_div, _1, _2, 0));
|
||||
define_builtin_func("^_^/=_", arith_bin_op, std::bind(compile_div, _1, _2, 1));
|
||||
define_builtin_func("^_%=_", arith_bin_op, std::bind(compile_mod, _1, _2, -1));
|
||||
define_builtin_func("^_%~=_", arith_bin_op, std::bind(compile_mod, _1, _2, 0));
|
||||
define_builtin_func("^_%^=_", arith_bin_op, std::bind(compile_mod, _1, _2, 1));
|
||||
define_builtin_func("^_~%=_", arith_bin_op, std::bind(compile_mod, _1, _2, 0));
|
||||
define_builtin_func("^_^%=_", arith_bin_op, std::bind(compile_mod, _1, _2, 1));
|
||||
define_builtin_func("^_<<=_", arith_bin_op, compile_lshift);
|
||||
define_builtin_func("^_>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, -1));
|
||||
define_builtin_func("^_>>~=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0));
|
||||
define_builtin_func("^_>>^=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1));
|
||||
define_builtin_func("^_~>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 0));
|
||||
define_builtin_func("^_^>>=_", arith_bin_op, std::bind(compile_rshift, _1, _2, 1));
|
||||
define_builtin_func("^_&=_", arith_bin_op, AsmOp::Custom("AND", 2));
|
||||
define_builtin_func("^_|=_", arith_bin_op, AsmOp::Custom("OR", 2));
|
||||
define_builtin_func("^_^=_", arith_bin_op, AsmOp::Custom("XOR", 2));
|
||||
@ -911,43 +922,24 @@ void define_builtins() {
|
||||
define_builtin_func("false", Int, /* AsmOp::Const("FALSE") */ std::bind(compile_bool_const, _1, _2, false));
|
||||
// define_builtin_func("null", Null, AsmOp::Const("PUSHNULL"));
|
||||
define_builtin_func("nil", Tuple, AsmOp::Const("PUSHNULL"));
|
||||
define_builtin_func("Nil", Tuple, AsmOp::Const("NIL"));
|
||||
define_builtin_func("null?", TypeExpr::new_forall({X}, TypeExpr::new_map(X, Int)), compile_is_null);
|
||||
define_builtin_func("cons", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor(X, Tuple), Tuple)),
|
||||
AsmOp::Custom("CONS", 2, 1));
|
||||
define_builtin_func("uncons", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, TypeExpr::new_tensor(X, Tuple))),
|
||||
AsmOp::Custom("UNCONS", 1, 2));
|
||||
define_builtin_func_x("list_next",
|
||||
TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, TypeExpr::new_tensor(Tuple, X))),
|
||||
AsmOp::Custom("UNCONS", 1, 2), {}, {1, 0});
|
||||
define_builtin_func("car", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, X)), AsmOp::Custom("CAR", 1, 1));
|
||||
define_builtin_func("cdr", TypeExpr::new_map(Tuple, Tuple), AsmOp::Custom("CDR", 1, 1));
|
||||
define_builtin_func("pair", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(XY, Tuple)), AsmOp::Custom("PAIR", 2, 1));
|
||||
define_builtin_func("unpair", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(Tuple, XY)),
|
||||
AsmOp::Custom("UNPAIR", 1, 2));
|
||||
define_builtin_func("triple", TypeExpr::new_forall({X, Y, Z}, TypeExpr::new_map(XYZ, Tuple)),
|
||||
AsmOp::Custom("TRIPLE", 3, 1));
|
||||
define_builtin_func("untriple", TypeExpr::new_forall({X, Y, Z}, TypeExpr::new_map(Tuple, XYZ)),
|
||||
AsmOp::Custom("UNTRIPLE", 1, 3));
|
||||
define_builtin_func("tuple4", TypeExpr::new_forall({X, Y, Z, T}, TypeExpr::new_map(XYZT, Tuple)),
|
||||
AsmOp::Custom("4 TUPLE", 4, 1));
|
||||
define_builtin_func("untuple4", TypeExpr::new_forall({X, Y, Z, T}, TypeExpr::new_map(Tuple, XYZT)),
|
||||
AsmOp::Custom("4 UNTUPLE", 1, 4));
|
||||
define_builtin_func("throw", impure_un_op, compile_throw, true);
|
||||
define_builtin_func("throw_if", impure_bin_op, std::bind(compile_cond_throw, _1, _2, true), true);
|
||||
define_builtin_func("throw_unless", impure_bin_op, std::bind(compile_cond_throw, _1, _2, false), true);
|
||||
define_builtin_func_x("load_int", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, true), {}, {1, 0});
|
||||
define_builtin_func_x("load_uint", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, false), {}, {1, 0});
|
||||
define_builtin_func("load_int", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, true), {}, {1, 0});
|
||||
define_builtin_func("load_uint", fetch_int_op, std::bind(compile_fetch_int, _1, _2, true, false), {}, {1, 0});
|
||||
define_builtin_func("preload_int", prefetch_int_op, std::bind(compile_fetch_int, _1, _2, false, true));
|
||||
define_builtin_func("preload_uint", prefetch_int_op, std::bind(compile_fetch_int, _1, _2, false, false));
|
||||
define_builtin_func_x("store_int", store_int_op, std::bind(compile_store_int, _1, _2, true), {1, 0, 2});
|
||||
define_builtin_func_x("store_uint", store_int_op, std::bind(compile_store_int, _1, _2, false), {1, 0, 2});
|
||||
define_builtin_func_x("~store_int", store_int_method, std::bind(compile_store_int, _1, _2, true), {1, 0, 2});
|
||||
define_builtin_func_x("~store_uint", store_int_method, std::bind(compile_store_int, _1, _2, false), {1, 0, 2});
|
||||
define_builtin_func_x("load_bits", fetch_slice_op, std::bind(compile_fetch_slice, _1, _2, true), {}, {1, 0});
|
||||
define_builtin_func("store_int", store_int_op, std::bind(compile_store_int, _1, _2, true), {1, 0, 2});
|
||||
define_builtin_func("store_uint", store_int_op, std::bind(compile_store_int, _1, _2, false), {1, 0, 2});
|
||||
define_builtin_func("~store_int", store_int_method, std::bind(compile_store_int, _1, _2, true), {1, 0, 2});
|
||||
define_builtin_func("~store_uint", store_int_method, std::bind(compile_store_int, _1, _2, false), {1, 0, 2});
|
||||
define_builtin_func("load_bits", fetch_slice_op, std::bind(compile_fetch_slice, _1, _2, true), {}, {1, 0});
|
||||
define_builtin_func("preload_bits", prefetch_slice_op, std::bind(compile_fetch_slice, _1, _2, false));
|
||||
define_builtin_func("int_at", TypeExpr::new_map(TupleInt, Int), compile_tuple_at);
|
||||
define_builtin_func("cell_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at);
|
||||
define_builtin_func("slice_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at);
|
||||
define_builtin_func("slice_at", TypeExpr::new_map(TupleInt, Slice), compile_tuple_at);
|
||||
define_builtin_func("tuple_at", TypeExpr::new_map(TupleInt, Tuple), compile_tuple_at);
|
||||
define_builtin_func("at", TypeExpr::new_forall({X}, TypeExpr::new_map(TupleInt, X)), compile_tuple_at);
|
||||
define_builtin_func("touch", TypeExpr::new_forall({X}, TypeExpr::new_map(X, X)), AsmOp::Nop());
|
||||
@ -960,13 +952,12 @@ void define_builtins() {
|
||||
AsmOp::Custom("s0 DUMP", 1, 1));
|
||||
define_builtin_func("run_method0", TypeExpr::new_map(Int, Unit),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true);
|
||||
define_builtin_func_x("run_method1",
|
||||
TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)),
|
||||
define_builtin_func("run_method1", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true);
|
||||
define_builtin_func_x(
|
||||
define_builtin_func(
|
||||
"run_method2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y}), Unit)),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 2, false); }, {1, 2, 0}, {}, true);
|
||||
define_builtin_func_x(
|
||||
define_builtin_func(
|
||||
"run_method3", TypeExpr::new_forall({X, Y, Z}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y, Z}), Unit)),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 3, false); }, {1, 2, 3, 0}, {}, true);
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ bool Op::generate_code_step(Stack& stack) {
|
||||
func->compile(stack.o, res, args); // compile res := f (args)
|
||||
} else {
|
||||
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
|
||||
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size());
|
||||
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size());
|
||||
}
|
||||
stack.push_new_var(left[0]);
|
||||
return true;
|
||||
@ -395,7 +395,7 @@ bool Op::generate_code_step(Stack& stack) {
|
||||
assert(stack.s[k + i].first == right1[i]);
|
||||
}
|
||||
if (cl == _CallInd) {
|
||||
stack.o << exec_arg_op("CALLARGS", (int)right.size() - 1, -1, (int)right.size() - 1);
|
||||
stack.o << exec_arg_op("CALLARGS", (int)right.size() - 1, (int)right.size(), (int)left.size());
|
||||
} else {
|
||||
auto func = dynamic_cast<const SymValAsmFunc*>(fun_ref->value);
|
||||
if (func) {
|
||||
@ -406,8 +406,11 @@ bool Op::generate_code_step(Stack& stack) {
|
||||
}
|
||||
func->compile(stack.o, res, args); // compile res := f (args)
|
||||
} else {
|
||||
auto fv = dynamic_cast<const SymValCodeFunc*>(fun_ref->value);
|
||||
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
|
||||
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size());
|
||||
bool is_inline = (fv && (fv->flags & 3));
|
||||
stack.o << AsmOp::Custom(name + (is_inline ? " INLINECALLDICT" : " CALLDICT"), (int)right.size(),
|
||||
(int)left.size());
|
||||
}
|
||||
}
|
||||
stack.s.resize(k);
|
||||
@ -421,6 +424,11 @@ bool Op::generate_code_step(Stack& stack) {
|
||||
if (block0->is_empty() && block1->is_empty()) {
|
||||
return true;
|
||||
}
|
||||
if (!next->noreturn() && (block0->noreturn() != block1->noreturn())) {
|
||||
// simple fix of unbalanced returns in if/else branches
|
||||
// (to be replaced with a finer condition working in loop bodies)
|
||||
throw src::ParseError{where, "`if` and `else` branches should both return or both not return"};
|
||||
}
|
||||
var_idx_t x = left[0];
|
||||
stack.rearrange_top(x, var_info[x] && var_info[x]->is_last());
|
||||
assert(stack[0] == x);
|
||||
@ -548,7 +556,7 @@ bool Op::generate_code_step(Stack& stack) {
|
||||
stack.opt_show();
|
||||
stack.s.pop_back();
|
||||
stack.modified();
|
||||
if (!next->is_empty()) {
|
||||
if (true || !next->is_empty()) {
|
||||
stack.o << "REPEAT:<{";
|
||||
stack.o.indent();
|
||||
stack.forget_const();
|
||||
@ -596,7 +604,7 @@ bool Op::generate_code_step(Stack& stack) {
|
||||
case _Until: {
|
||||
// stack.drop_vars_except(block0->var_info);
|
||||
// stack.opt_show();
|
||||
if (!next->is_empty()) {
|
||||
if (true || !next->is_empty()) {
|
||||
stack.o << "UNTIL:<{";
|
||||
stack.o.indent();
|
||||
stack.forget_const();
|
||||
@ -627,7 +635,7 @@ bool Op::generate_code_step(Stack& stack) {
|
||||
stack.drop_vars_except(block0->var_info);
|
||||
stack.opt_show();
|
||||
StackLayout layout1 = stack.vars();
|
||||
bool next_empty = next->is_empty();
|
||||
bool next_empty = false && next->is_empty();
|
||||
stack.o << "WHILE:<{";
|
||||
stack.o.indent();
|
||||
stack.forget_const();
|
||||
|
@ -60,21 +60,36 @@ void generate_output_func(SymDef* func_sym) {
|
||||
code.print(std::cerr, 9);
|
||||
}
|
||||
code.simplify_var_types();
|
||||
// std::cerr << "after simplify_var_types: \n"; code.print(std::cerr, 0);
|
||||
if (verbosity >= 5) {
|
||||
std::cerr << "after simplify_var_types: \n";
|
||||
code.print(std::cerr, 0);
|
||||
}
|
||||
code.prune_unreachable_code();
|
||||
// std::cerr << "after prune_unreachable: \n"; code.print(std::cerr, 0);
|
||||
if (verbosity >= 5) {
|
||||
std::cerr << "after prune_unreachable: \n";
|
||||
code.print(std::cerr, 0);
|
||||
}
|
||||
code.split_vars(true);
|
||||
// std::cerr << "after split_vars: \n"; code.print(std::cerr, 0);
|
||||
if (verbosity >= 5) {
|
||||
std::cerr << "after split_vars: \n";
|
||||
code.print(std::cerr, 0);
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
code.compute_used_code_vars();
|
||||
if (verbosity >= 5) {
|
||||
if (verbosity >= 4) {
|
||||
std::cerr << "after compute_used_vars: \n";
|
||||
code.print(std::cerr, 6);
|
||||
}
|
||||
code.fwd_analyze();
|
||||
// std::cerr << "after fwd_analyze: \n"; code.print(std::cerr, 6);
|
||||
if (verbosity >= 5) {
|
||||
std::cerr << "after fwd_analyze: \n";
|
||||
code.print(std::cerr, 6);
|
||||
}
|
||||
code.prune_unreachable_code();
|
||||
// std::cerr << "after prune_unreachable: \n"; code.print(std::cerr, 6);
|
||||
if (verbosity >= 5) {
|
||||
std::cerr << "after prune_unreachable: \n";
|
||||
code.print(std::cerr, 6);
|
||||
}
|
||||
}
|
||||
code.mark_noreturn();
|
||||
if (verbosity >= 3) {
|
||||
@ -83,7 +98,8 @@ void generate_output_func(SymDef* func_sym) {
|
||||
if (verbosity >= 2) {
|
||||
std::cerr << "\n---------- resulting code for " << name << " -------------\n";
|
||||
}
|
||||
*outs << std::string(indent * 2, ' ') << name << " PROC:<{\n";
|
||||
bool inline_ref = (func_val->flags & 2);
|
||||
*outs << std::string(indent * 2, ' ') << name << " PROC" << (inline_ref ? "REF" : "") << ":<{\n";
|
||||
code.generate_code(
|
||||
*outs,
|
||||
(stack_layout_comments ? Stack::_StkCmt | Stack::_CptStkCmt : 0) | (opt_level < 2 ? Stack::_DisableOpt : 0),
|
||||
|
@ -67,6 +67,8 @@ enum Keyword {
|
||||
_RshiftC,
|
||||
_DivR,
|
||||
_DivC,
|
||||
_ModR,
|
||||
_ModC,
|
||||
_DivMod,
|
||||
_PlusLet,
|
||||
_MinusLet,
|
||||
@ -75,10 +77,15 @@ enum Keyword {
|
||||
_DivRLet,
|
||||
_DivCLet,
|
||||
_ModLet,
|
||||
_ModRLet,
|
||||
_ModCLet,
|
||||
_LshiftLet,
|
||||
_RshiftLet,
|
||||
_RshiftRLet,
|
||||
_RshiftCLet,
|
||||
_AndLet,
|
||||
_OrLet,
|
||||
_XorLet,
|
||||
_Int,
|
||||
_Cell,
|
||||
_Slice,
|
||||
@ -87,9 +94,12 @@ enum Keyword {
|
||||
_Tuple,
|
||||
_Type,
|
||||
_Mapsto,
|
||||
_Forall,
|
||||
_Asm,
|
||||
_Impure,
|
||||
_Extern,
|
||||
_Inline,
|
||||
_InlineRef,
|
||||
_MethodId,
|
||||
_Operator,
|
||||
_Infix,
|
||||
@ -123,7 +133,7 @@ class IdSc {
|
||||
*/
|
||||
|
||||
struct TypeExpr {
|
||||
enum te_type { te_Unknown, te_Indirect, te_Atomic, te_Tensor, te_Map, te_Type, te_ForAll } constr;
|
||||
enum te_type { te_Unknown, te_Var, te_Indirect, te_Atomic, te_Tensor, te_Map, te_Type, te_ForAll } constr;
|
||||
enum {
|
||||
_Int = Keyword::_Int,
|
||||
_Cell = Keyword::_Cell,
|
||||
@ -168,6 +178,9 @@ struct TypeExpr {
|
||||
bool is_int() const {
|
||||
return is_atomic(_Int);
|
||||
}
|
||||
bool is_var() const {
|
||||
return constr == te_Var;
|
||||
}
|
||||
bool has_fixed_width() const {
|
||||
return minw == maxw;
|
||||
}
|
||||
@ -210,7 +223,10 @@ struct TypeExpr {
|
||||
return new_tensor({te1, te2, te3});
|
||||
}
|
||||
static TypeExpr* new_var() {
|
||||
return new TypeExpr{te_Unknown, --type_vars, 1};
|
||||
return new TypeExpr{te_Var, --type_vars, 1};
|
||||
}
|
||||
static TypeExpr* new_var(int idx) {
|
||||
return new TypeExpr{te_Var, idx, 1};
|
||||
}
|
||||
static TypeExpr* new_forall(std::vector<TypeExpr*> list, TypeExpr* body) {
|
||||
return new TypeExpr{te_ForAll, body, std::move(list)};
|
||||
@ -392,6 +408,7 @@ inline std::ostream& operator<<(std::ostream& os, const VarDescr& vd) {
|
||||
|
||||
struct VarDescrList {
|
||||
std::vector<VarDescr> list;
|
||||
bool unreachable{false};
|
||||
VarDescrList() : list() {
|
||||
}
|
||||
VarDescrList(const std::vector<VarDescr>& _list) : list(_list) {
|
||||
@ -425,6 +442,10 @@ struct VarDescrList {
|
||||
VarDescrList operator|(const VarDescrList& y) const;
|
||||
VarDescrList& operator|=(const VarDescrList& values);
|
||||
void show(std::ostream& os) const;
|
||||
void set_unreachable() {
|
||||
list.clear();
|
||||
unreachable = true;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const VarDescrList& values) {
|
||||
@ -632,6 +653,9 @@ struct CodeBlob {
|
||||
}
|
||||
bool import_params(FormalArgList arg_list);
|
||||
var_idx_t create_var(int cls, TypeExpr* var_type = 0, SymDef* sym = 0, const SrcLocation* loc = 0);
|
||||
var_idx_t create_tmp_var(TypeExpr* var_type = 0, const SrcLocation* loc = 0) {
|
||||
return create_var(TmpVar::_Tmp, var_type, nullptr, loc);
|
||||
}
|
||||
int split_vars(bool strict = false);
|
||||
bool compute_used_code_vars();
|
||||
bool compute_used_code_vars(std::unique_ptr<Op>& ops, const VarDescrList& var_info, bool edit) const;
|
||||
@ -670,8 +694,9 @@ struct SymVal : sym::SymValBase {
|
||||
TypeExpr* sym_type;
|
||||
td::RefInt256 method_id;
|
||||
bool impure;
|
||||
short flags; // +1 = inline, +2 = inline_ref
|
||||
SymVal(int _type, int _idx, TypeExpr* _stype = nullptr, bool _impure = false)
|
||||
: sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure) {
|
||||
: sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure), flags(0) {
|
||||
}
|
||||
~SymVal() override = default;
|
||||
TypeExpr* get_type() const {
|
||||
@ -710,6 +735,16 @@ struct SymValCodeFunc : SymValFunc {
|
||||
}
|
||||
};
|
||||
|
||||
struct SymValType : sym::SymValBase {
|
||||
TypeExpr* sym_type;
|
||||
SymValType(int _type, int _idx, TypeExpr* _stype = nullptr) : sym::SymValBase(_type, _idx), sym_type(_stype) {
|
||||
}
|
||||
~SymValType() override = default;
|
||||
TypeExpr* get_type() const {
|
||||
return sym_type;
|
||||
}
|
||||
};
|
||||
|
||||
extern int glob_func_cnt, undef_func_cnt;
|
||||
extern std::vector<SymDef*> glob_func;
|
||||
|
||||
@ -802,6 +837,10 @@ struct Expr {
|
||||
int define_new_vars(CodeBlob& code);
|
||||
int predefine_vars();
|
||||
std::vector<var_idx_t> pre_compile(CodeBlob& code) const;
|
||||
var_idx_t new_tmp(CodeBlob& code) const;
|
||||
std::vector<var_idx_t> new_tmp_vect(CodeBlob& code) const {
|
||||
return {new_tmp(code)};
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -212,6 +212,10 @@ int Expr::predefine_vars() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var_idx_t Expr::new_tmp(CodeBlob& code) const {
|
||||
return code.create_tmp_var(e_type, &here);
|
||||
}
|
||||
|
||||
std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
|
||||
switch (cls) {
|
||||
case _Tuple: {
|
||||
@ -241,8 +245,7 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
|
||||
res.insert(res.end(), add.cbegin(), add.cend());
|
||||
}
|
||||
}
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), sym);
|
||||
if (flags & _IsImpure) {
|
||||
op.flags |= Op::_Impure;
|
||||
@ -256,57 +259,52 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
|
||||
return {val};
|
||||
case _VarApply:
|
||||
if (args[0]->cls == _Glob) {
|
||||
std::vector<var_idx_t> res = args[1]->pre_compile(code);
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto res = args[1]->pre_compile(code);
|
||||
auto rvect = new_tmp_vect(code);
|
||||
auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), args[0]->sym);
|
||||
if (args[0]->flags & _IsImpure) {
|
||||
op.flags |= Op::_Impure;
|
||||
}
|
||||
return rvect;
|
||||
} else {
|
||||
std::vector<var_idx_t> res = args[1]->pre_compile(code);
|
||||
std::vector<var_idx_t> tfunc = args[0]->pre_compile(code);
|
||||
auto res = args[1]->pre_compile(code);
|
||||
auto tfunc = args[0]->pre_compile(code);
|
||||
if (tfunc.size() != 1) {
|
||||
throw src::Fatal{"stack tuple used as a function"};
|
||||
}
|
||||
res.push_back(tfunc[0]);
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
code.emplace_back(here, Op::_CallInd, rvect, std::move(res));
|
||||
return rvect;
|
||||
}
|
||||
case _Const: {
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
code.emplace_back(here, Op::_IntConst, rvect, intval);
|
||||
return rvect;
|
||||
}
|
||||
case _Glob: {
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
code.emplace_back(here, Op::_GlobVar, rvect, std::vector<var_idx_t>{}, sym);
|
||||
return rvect;
|
||||
}
|
||||
case _Letop: {
|
||||
std::vector<var_idx_t> right = args[1]->pre_compile(code);
|
||||
std::vector<var_idx_t> left = args[0]->pre_compile(code);
|
||||
code.emplace_back(here, Op::_Let, left, std::move(right));
|
||||
return left;
|
||||
auto right = args[1]->pre_compile(code);
|
||||
auto left = args[0]->pre_compile(code);
|
||||
code.emplace_back(here, Op::_Let, std::move(left), right);
|
||||
return right;
|
||||
}
|
||||
case _LetFirst: {
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> right = args[1]->pre_compile(code);
|
||||
std::vector<var_idx_t> left = args[0]->pre_compile(code);
|
||||
left.push_back(rv);
|
||||
auto rvect = new_tmp_vect(code);
|
||||
auto right = args[1]->pre_compile(code);
|
||||
auto left = args[0]->pre_compile(code);
|
||||
left.push_back(rvect[0]);
|
||||
code.emplace_back(here, Op::_Let, std::move(left), std::move(right));
|
||||
return std::vector<var_idx_t>{rv};
|
||||
return rvect;
|
||||
}
|
||||
case _CondExpr: {
|
||||
auto cond = args[0]->pre_compile(code);
|
||||
assert(cond.size() == 1);
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
Op& if_op = code.emplace_back(here, Op::_If, cond);
|
||||
code.push_set_cur(if_op.block0);
|
||||
code.emplace_back(here, Op::_Let, rvect, args[1]->pre_compile(code));
|
||||
|
@ -54,6 +54,7 @@ void define_keywords() {
|
||||
.add_kw_char('>')
|
||||
.add_kw_char('&')
|
||||
.add_kw_char('|')
|
||||
.add_kw_char('^')
|
||||
.add_kw_char('~');
|
||||
|
||||
using Kw = funC::Keyword;
|
||||
@ -64,22 +65,29 @@ void define_keywords() {
|
||||
.add_keyword("<=>", Kw::_Spaceship)
|
||||
.add_keyword("<<", Kw::_Lshift)
|
||||
.add_keyword(">>", Kw::_Rshift)
|
||||
.add_keyword(">>~", Kw::_RshiftR)
|
||||
.add_keyword(">>^", Kw::_RshiftC)
|
||||
.add_keyword("/~", Kw::_DivR)
|
||||
.add_keyword("/^", Kw::_DivC)
|
||||
.add_keyword("~>>", Kw::_RshiftR)
|
||||
.add_keyword("^>>", Kw::_RshiftC)
|
||||
.add_keyword("~/", Kw::_DivR)
|
||||
.add_keyword("^/", Kw::_DivC)
|
||||
.add_keyword("~%", Kw::_ModR)
|
||||
.add_keyword("^%", Kw::_ModC)
|
||||
.add_keyword("/%", Kw::_DivMod)
|
||||
.add_keyword("+=", Kw::_PlusLet)
|
||||
.add_keyword("-=", Kw::_MinusLet)
|
||||
.add_keyword("*=", Kw::_TimesLet)
|
||||
.add_keyword("/=", Kw::_DivLet)
|
||||
.add_keyword("~/=", Kw::_DivRLet)
|
||||
.add_keyword("^/=", Kw::_DivCLet)
|
||||
.add_keyword("%=", Kw::_ModLet)
|
||||
.add_keyword("/~=", Kw::_DivRLet)
|
||||
.add_keyword("/^=", Kw::_DivCLet)
|
||||
.add_keyword("~%=", Kw::_ModRLet)
|
||||
.add_keyword("^%=", Kw::_ModCLet)
|
||||
.add_keyword("<<=", Kw::_LshiftLet)
|
||||
.add_keyword(">>=", Kw::_RshiftLet)
|
||||
.add_keyword(">>~=", Kw::_RshiftRLet)
|
||||
.add_keyword(">>^=", Kw::_RshiftCLet);
|
||||
.add_keyword("~>>=", Kw::_RshiftRLet)
|
||||
.add_keyword("^>>=", Kw::_RshiftCLet)
|
||||
.add_keyword("&=", Kw::_AndLet)
|
||||
.add_keyword("|=", Kw::_OrLet)
|
||||
.add_keyword("^=", Kw::_XorLet);
|
||||
|
||||
sym::symbols.add_keyword("return", Kw::_Return)
|
||||
.add_keyword("var", Kw::_Var)
|
||||
@ -100,11 +108,15 @@ void define_keywords() {
|
||||
.add_keyword("builder", Kw::_Builder)
|
||||
.add_keyword("cont", Kw::_Cont)
|
||||
.add_keyword("tuple", Kw::_Tuple)
|
||||
.add_keyword("->", Kw::_Mapsto);
|
||||
.add_keyword("type", Kw::_Type)
|
||||
.add_keyword("->", Kw::_Mapsto)
|
||||
.add_keyword("forall", Kw::_Forall);
|
||||
|
||||
sym::symbols.add_keyword("extern", Kw::_Extern)
|
||||
.add_keyword("asm", Kw::_Asm)
|
||||
.add_keyword("impure", Kw::_Impure)
|
||||
.add_keyword("inline", Kw::_Inline)
|
||||
.add_keyword("inline_ref", Kw::_InlineRef)
|
||||
.add_keyword("method_id", Kw::_MethodId)
|
||||
.add_keyword("operator", Kw::_Operator)
|
||||
.add_keyword("infix", Kw::_Infix)
|
||||
|
@ -89,6 +89,15 @@ TypeExpr* parse_type1(Lexer& lex) {
|
||||
case '_':
|
||||
lex.next();
|
||||
return TypeExpr::new_hole();
|
||||
case _Ident: {
|
||||
auto sym = sym::lookup_symbol(lex.cur().val);
|
||||
if (sym && dynamic_cast<SymValType*>(sym->value)) {
|
||||
auto val = dynamic_cast<SymValType*>(sym->value);
|
||||
lex.next();
|
||||
return val->get_type();
|
||||
}
|
||||
lex.cur().error_at("`", "` is not a type identifier");
|
||||
}
|
||||
}
|
||||
lex.expect('(');
|
||||
if (lex.tp() == ')') {
|
||||
@ -132,9 +141,16 @@ FormalArg parse_formal_arg(Lexer& lex, int fa_idx) {
|
||||
loc = lex.cur().loc;
|
||||
} else if (lex.tp() != _Ident) {
|
||||
arg_type = parse_type(lex);
|
||||
} else {
|
||||
auto sym = sym::lookup_symbol(lex.cur().val);
|
||||
if (sym && dynamic_cast<SymValType*>(sym->value)) {
|
||||
auto val = dynamic_cast<SymValType*>(sym->value);
|
||||
lex.next();
|
||||
arg_type = val->get_type();
|
||||
} else {
|
||||
arg_type = TypeExpr::new_hole();
|
||||
}
|
||||
}
|
||||
if (lex.tp() == '_' || lex.tp() == ',' || lex.tp() == ')') {
|
||||
if (lex.tp() == '_') {
|
||||
loc = lex.cur().loc;
|
||||
@ -147,6 +163,9 @@ FormalArg parse_formal_arg(Lexer& lex, int fa_idx) {
|
||||
}
|
||||
loc = lex.cur().loc;
|
||||
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
||||
if (!new_sym_def) {
|
||||
lex.cur().error_at("cannot define symbol `", "`");
|
||||
}
|
||||
if (new_sym_def->value) {
|
||||
lex.cur().error_at("redefined formal parameter `", "`");
|
||||
}
|
||||
@ -295,6 +314,15 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
return res;
|
||||
}
|
||||
if (t == _Ident) {
|
||||
auto sym = sym::lookup_symbol(lex.cur().val);
|
||||
if (sym && dynamic_cast<SymValType*>(sym->value)) {
|
||||
auto val = dynamic_cast<SymValType*>(sym->value);
|
||||
Expr* res = new Expr{Expr::_Type, lex.cur().loc};
|
||||
res->flags = Expr::_IsType;
|
||||
res->e_type = val->get_type();
|
||||
lex.next();
|
||||
return res;
|
||||
}
|
||||
Expr* res = new Expr{Expr::_Var, lex.cur().loc};
|
||||
if (nv) {
|
||||
res->val = ~lex.cur().val;
|
||||
@ -302,14 +330,14 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
res->flags = Expr::_IsLvalue | Expr::_IsNewVar;
|
||||
// std::cerr << "defined new variable " << lex.cur().str << " : " << res->e_type << std::endl;
|
||||
} else {
|
||||
res->sym = sym::lookup_symbol(lex.cur().val);
|
||||
if (!res->sym) {
|
||||
if (!sym) {
|
||||
check_global_func(lex.cur());
|
||||
res->sym = sym::lookup_symbol(lex.cur().val);
|
||||
sym = sym::lookup_symbol(lex.cur().val);
|
||||
}
|
||||
res->sym = sym;
|
||||
SymVal* val = nullptr;
|
||||
if (res->sym) {
|
||||
val = dynamic_cast<SymVal*>(res->sym->value);
|
||||
if (sym) {
|
||||
val = dynamic_cast<SymVal*>(sym->value);
|
||||
}
|
||||
if (!val) {
|
||||
lex.cur().error_at("undefined identifier `", "`");
|
||||
@ -428,7 +456,6 @@ Expr* parse_expr80(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
res->flags = Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0);
|
||||
res->deduce_type(lex.cur());
|
||||
if (modify) {
|
||||
// FIXME (use _LetFirst instead of _Letop)
|
||||
auto tmp = res;
|
||||
res = new Expr{Expr::_LetFirst, {obj->copy(), tmp}};
|
||||
res->here = loc;
|
||||
@ -464,7 +491,7 @@ Expr* parse_expr75(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* res = parse_expr75(lex, code, nv);
|
||||
while (lex.tp() == '*' || lex.tp() == '/' || lex.tp() == '%' || lex.tp() == _DivMod || lex.tp() == _DivC ||
|
||||
lex.tp() == _DivR || lex.tp() == '&') {
|
||||
lex.tp() == _DivR || lex.tp() == _ModC || lex.tp() == _ModR || lex.tp() == '&') {
|
||||
res->chk_rvalue(lex.cur());
|
||||
int t = lex.tp();
|
||||
sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
|
||||
@ -482,7 +509,7 @@ Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// parse [-] E { (+ | - | `|` ) E }
|
||||
// parse [-] E { (+ | - | `|` | ^) E }
|
||||
Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
Expr* res;
|
||||
int t = lex.tp();
|
||||
@ -501,7 +528,7 @@ Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
} else {
|
||||
res = parse_expr30(lex, code, nv);
|
||||
}
|
||||
while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|') {
|
||||
while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|' || lex.tp() == '^') {
|
||||
res->chk_rvalue(lex.cur());
|
||||
t = lex.tp();
|
||||
sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
|
||||
@ -587,7 +614,8 @@ Expr* parse_expr10(Lexer& lex, CodeBlob& code, bool nv) {
|
||||
auto x = parse_expr13(lex, code, nv);
|
||||
int t = lex.tp();
|
||||
if (t == _PlusLet || t == _MinusLet || t == _TimesLet || t == _DivLet || t == _DivRLet || t == _DivCLet ||
|
||||
t == _ModLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || t == _RshiftRLet) {
|
||||
t == _ModLet || t == _ModCLet || t == _ModRLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet ||
|
||||
t == _RshiftRLet || t == _AndLet || t == _OrLet || t == _XorLet) {
|
||||
x->chk_lvalue(lex.cur());
|
||||
x->chk_rvalue(lex.cur());
|
||||
sym_idx_t name = symbols.lookup_add(std::string{"^_"} + lex.cur().str + "_");
|
||||
@ -960,9 +988,76 @@ SymValAsmFunc* parse_asm_func_body(Lexer& lex, TypeExpr* func_type, const Formal
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<TypeExpr*> parse_type_var_list(Lexer& lex) {
|
||||
std::vector<TypeExpr*> res;
|
||||
lex.expect(_Forall);
|
||||
int idx = 0;
|
||||
while (true) {
|
||||
if (lex.tp() == _Type) {
|
||||
lex.next();
|
||||
}
|
||||
if (lex.tp() != _Ident) {
|
||||
throw src::ParseError{lex.cur().loc, "free type identifier expected"};
|
||||
}
|
||||
auto loc = lex.cur().loc;
|
||||
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
|
||||
if (new_sym_def->value) {
|
||||
lex.cur().error_at("redefined type variable `", "`");
|
||||
}
|
||||
auto var = TypeExpr::new_var(idx);
|
||||
new_sym_def->value = new SymValType{SymVal::_Typename, idx++, var};
|
||||
res.push_back(var);
|
||||
lex.next();
|
||||
if (lex.tp() != ',') {
|
||||
break;
|
||||
}
|
||||
lex.next();
|
||||
}
|
||||
lex.expect(_Mapsto);
|
||||
return res;
|
||||
}
|
||||
|
||||
void type_var_usage(TypeExpr* expr, const std::vector<TypeExpr*>& typevars, std::vector<bool>& used) {
|
||||
if (expr->constr != TypeExpr::te_Var) {
|
||||
for (auto arg : expr->args) {
|
||||
type_var_usage(arg, typevars, used);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (std::size_t i = 0; i < typevars.size(); i++) {
|
||||
if (typevars[i] == expr) {
|
||||
used.at(i) = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
TypeExpr* compute_type_closure(TypeExpr* expr, const std::vector<TypeExpr*>& typevars) {
|
||||
if (typevars.empty()) {
|
||||
return expr;
|
||||
}
|
||||
std::vector<bool> used(typevars.size(), false);
|
||||
type_var_usage(expr, typevars, used);
|
||||
std::vector<TypeExpr*> used_vars;
|
||||
for (std::size_t i = 0; i < typevars.size(); i++) {
|
||||
if (used.at(i)) {
|
||||
used_vars.push_back(typevars[i]);
|
||||
}
|
||||
}
|
||||
if (!used_vars.empty()) {
|
||||
expr = TypeExpr::new_forall(std::move(used_vars), expr);
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
void parse_func_def(Lexer& lex) {
|
||||
SrcLocation loc{lex.cur().loc};
|
||||
sym::open_scope(lex);
|
||||
std::vector<TypeExpr*> type_vars;
|
||||
if (lex.tp() == _Forall) {
|
||||
type_vars = parse_type_var_list(lex);
|
||||
}
|
||||
auto ret_type = parse_type(lex);
|
||||
if (lex.tp() != _Ident) {
|
||||
throw src::ParseError{lex.cur().loc, "function name identifier expected"};
|
||||
@ -974,6 +1069,11 @@ void parse_func_def(Lexer& lex) {
|
||||
if (impure) {
|
||||
lex.next();
|
||||
}
|
||||
int f = 0;
|
||||
if (lex.tp() == _Inline || lex.tp() == _InlineRef) {
|
||||
f = (lex.tp() == _Inline) ? 1 : 2;
|
||||
lex.next();
|
||||
}
|
||||
td::RefInt256 method_id;
|
||||
std::string method_name;
|
||||
if (lex.tp() == _MethodId) {
|
||||
@ -1005,6 +1105,7 @@ void parse_func_def(Lexer& lex) {
|
||||
lex.expect('{', "function body block expected");
|
||||
}
|
||||
TypeExpr* func_type = TypeExpr::new_map(extract_total_arg_type(arg_list), ret_type);
|
||||
func_type = compute_type_closure(func_type, type_vars);
|
||||
if (verbosity >= 1) {
|
||||
std::cerr << "function " << func_name.str << " : " << func_type << std::endl;
|
||||
}
|
||||
@ -1071,6 +1172,17 @@ void parse_func_def(Lexer& lex) {
|
||||
lex.cur().error("integer method identifier for `"s + func_name.str + "` changed to a different value");
|
||||
}
|
||||
}
|
||||
if (f) {
|
||||
auto val = dynamic_cast<SymVal*>(func_sym->value);
|
||||
if (!val) {
|
||||
lex.cur().error("cannot set unknown function `"s + func_name.str + "` as an inline");
|
||||
}
|
||||
if (!(val->flags & 3)) {
|
||||
val->flags = (short)(val->flags | f);
|
||||
} else if ((val->flags & 3) != f) {
|
||||
lex.cur().error("inline mode for `"s + func_name.str + "` changed with respect to a previous declaration");
|
||||
}
|
||||
}
|
||||
if (verbosity >= 1) {
|
||||
std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl;
|
||||
}
|
||||
|
@ -59,20 +59,20 @@ operator _/%_ infix 20;
|
||||
return (x / y, x % y);
|
||||
}
|
||||
-}
|
||||
{-
|
||||
< type A, type B, type C >
|
||||
|
||||
forall A, B, C ->
|
||||
(B, C, A) rot (A x, B y, C z) {
|
||||
return (y, z, x);
|
||||
}
|
||||
-}
|
||||
|
||||
int ataninv(int base, int q) { ;; computes base*atan(1/q)
|
||||
base /~= q;
|
||||
base ~/= q;
|
||||
q *= - q;
|
||||
int sum = 0;
|
||||
int n = 1;
|
||||
do {
|
||||
sum += base /~ n;
|
||||
base /~= q;
|
||||
sum += base ~/ n;
|
||||
base ~/= q;
|
||||
n += 2;
|
||||
} until base == 0;
|
||||
return sum;
|
||||
@ -81,5 +81,9 @@ int ataninv(int base, int q) { ;; computes base*atan(1/q)
|
||||
int calc_pi() {
|
||||
int base = 64;
|
||||
repeat (70) { base *= 10; }
|
||||
return (ataninv(base << 2, 5) - ataninv(base, 239)) >>~ 4;
|
||||
return (ataninv(base << 2, 5) - ataninv(base, 239)) ~>> 4;
|
||||
}
|
||||
|
||||
int main() {
|
||||
return calc_pi();
|
||||
}
|
||||
|
22
submodules/ton/tonlib-src/crypto/func/test/a6_3.fc
Normal file
22
submodules/ton/tonlib-src/crypto/func/test/a6_3.fc
Normal file
@ -0,0 +1,22 @@
|
||||
forall A, B, C ->
|
||||
(B, C, A) rot(A x, B y, C z) {
|
||||
return (y, z, x);
|
||||
}
|
||||
|
||||
forall A, B, C ->
|
||||
_ rot2(A x, B y, C z) {
|
||||
return rot(rot(x, y, z));
|
||||
}
|
||||
|
||||
_ test() {
|
||||
return rot2(2, 3, 9);
|
||||
}
|
||||
|
||||
_ test2(cell x, slice y, tuple z) {
|
||||
return rot2(x, y, z);
|
||||
}
|
||||
|
||||
forall A ->
|
||||
_ test3(cell x, A y, int z) {
|
||||
return rot2(x, y, z);
|
||||
}
|
20
submodules/ton/tonlib-src/crypto/func/test/b3.fc
Normal file
20
submodules/ton/tonlib-src/crypto/func/test/b3.fc
Normal file
@ -0,0 +1,20 @@
|
||||
;; inline test
|
||||
_ unpack() inline {
|
||||
var ds = get_data().begin_parse();
|
||||
var res = (ds~load_uint(8), ds~load_int(32), ds~load_int(32));
|
||||
return res;
|
||||
}
|
||||
|
||||
() pack(a, x, y) impure inline_ref {
|
||||
set_data(begin_cell()
|
||||
.store_uint(a, 8)
|
||||
.store_int(x, 32)
|
||||
.store_int(y, 32)
|
||||
.end_cell());
|
||||
}
|
||||
|
||||
() main() impure {
|
||||
var (a, x, y) = unpack();
|
||||
x += y;
|
||||
pack(a, x, y);
|
||||
}
|
9
submodules/ton/tonlib-src/crypto/func/test/w1.fc
Normal file
9
submodules/ton/tonlib-src/crypto/func/test/w1.fc
Normal file
@ -0,0 +1,9 @@
|
||||
(int, int) nested_if(int id) method_id {
|
||||
dump_stack();
|
||||
if (id > 0) {
|
||||
if (id > 10) {
|
||||
return (2 * id, 3 * id);
|
||||
}
|
||||
}
|
||||
return (5, 6);
|
||||
}
|
14
submodules/ton/tonlib-src/crypto/func/test/w2.fc
Normal file
14
submodules/ton/tonlib-src/crypto/func/test/w2.fc
Normal file
@ -0,0 +1,14 @@
|
||||
_ f(cs) {
|
||||
return (cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8));
|
||||
}
|
||||
|
||||
_ main(cs) {
|
||||
var (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
|
||||
x11, x12, x13, x14, x15, x16, x17, x18, x19) = f(cs);
|
||||
return x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
|
||||
+ x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19;
|
||||
}
|
13
submodules/ton/tonlib-src/crypto/func/test/w3.fc
Normal file
13
submodules/ton/tonlib-src/crypto/func/test/w3.fc
Normal file
@ -0,0 +1,13 @@
|
||||
() main(cs) impure {
|
||||
int i = 0;
|
||||
if (cs.slice_refs()) {
|
||||
do {
|
||||
i = i + 1;
|
||||
} until(i > 10);
|
||||
}
|
||||
set_data(begin_cell()
|
||||
.store_uint(1, 32)
|
||||
.store_uint(2, 32)
|
||||
.store_uint(i, 32)
|
||||
.end_cell());
|
||||
}
|
13
submodules/ton/tonlib-src/crypto/func/test/w4.fc
Normal file
13
submodules/ton/tonlib-src/crypto/func/test/w4.fc
Normal file
@ -0,0 +1,13 @@
|
||||
_ main(cell dict, int t3) {
|
||||
int index = -1;
|
||||
do {
|
||||
(index, slice value, int found) = dict.udict_get_next?(32, index);
|
||||
if (found) {
|
||||
(int temp1, int temp2) = (value~load_uint(16), value~load_uint(32));
|
||||
if (t3 > temp2) {
|
||||
dict~udict_delete_get?(32, index);
|
||||
}
|
||||
}
|
||||
} until ( ~ found);
|
||||
return dict;
|
||||
}
|
14
submodules/ton/tonlib-src/crypto/func/test/w5.fc
Normal file
14
submodules/ton/tonlib-src/crypto/func/test/w5.fc
Normal file
@ -0,0 +1,14 @@
|
||||
(cell) recv_external(slice in_msg) impure {
|
||||
cell mydict = new_dict();
|
||||
builder r = begin_cell().store_int(10, 16);
|
||||
mydict~udict_set_builder(32, 1, r );
|
||||
int index = -1;
|
||||
do {
|
||||
(var index, var value, var found) = mydict.udict_get_next?(32, index);
|
||||
} until ( ~ found );
|
||||
return mydict;
|
||||
}
|
||||
|
||||
() recv_internal() impure {
|
||||
;; Nothing
|
||||
}
|
12
submodules/ton/tonlib-src/crypto/func/test/w6.fc
Normal file
12
submodules/ton/tonlib-src/crypto/func/test/w6.fc
Normal file
@ -0,0 +1,12 @@
|
||||
int test(int x) method_id {
|
||||
int i = 0;
|
||||
;; int f = false;
|
||||
do {
|
||||
i = i + 1;
|
||||
if (i > 5) {
|
||||
return 1;
|
||||
}
|
||||
int f = (i * i == 64);
|
||||
} until (f);
|
||||
return -1;
|
||||
}
|
14
submodules/ton/tonlib-src/crypto/func/test/w7.fc
Normal file
14
submodules/ton/tonlib-src/crypto/func/test/w7.fc
Normal file
@ -0,0 +1,14 @@
|
||||
int test(int y) {
|
||||
int x = 1;
|
||||
if (y > 0) {
|
||||
return 1;
|
||||
}
|
||||
return x > 0;
|
||||
}
|
||||
|
||||
int f(int y) {
|
||||
if (y > 0) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
@ -153,7 +153,7 @@ bool TypeExpr::remove_forall(TypeExpr*& te) {
|
||||
bool TypeExpr::remove_forall_in(TypeExpr*& te, TypeExpr* te2, const std::vector<TypeExpr*>& new_vars) {
|
||||
assert(te);
|
||||
assert(te2 && te2->constr == te_ForAll);
|
||||
if (te->constr == te_Unknown) {
|
||||
if (te->constr == te_Var) {
|
||||
for (std::size_t i = 0; i < new_vars.size(); i++) {
|
||||
if (te == te2->args[i + 1]) {
|
||||
te = new_vars[i];
|
||||
@ -201,12 +201,14 @@ std::ostream& operator<<(std::ostream& os, TypeExpr* type_expr) {
|
||||
std::ostream& TypeExpr::print(std::ostream& os, int lex_level) {
|
||||
switch (constr) {
|
||||
case te_Unknown:
|
||||
if (value >= 0) {
|
||||
return os << "??" << value;
|
||||
} else if (value >= -26) {
|
||||
return os << (char)(64 - value);
|
||||
case te_Var:
|
||||
if (value >= -26 && value < 0) {
|
||||
return os << "_" << (char)(91 + value);
|
||||
} else if (value >= 0 && value < 26) {
|
||||
return os << (char)(65 + value);
|
||||
} else {
|
||||
return os << "TVAR" << -value;
|
||||
return os << "TVAR" << value;
|
||||
}
|
||||
case te_Indirect:
|
||||
return os << args[0];
|
||||
|
@ -182,3 +182,48 @@ dictnew constant special-dict
|
||||
-2 constant run_ticktock
|
||||
-3 constant split_prepare
|
||||
-4 constant split_install
|
||||
|
||||
// public key conversion
|
||||
|
||||
|
||||
// restricted wallet creation
|
||||
"auto/restricted-wallet-code.fif" include =: RWCode1
|
||||
"auto/restricted-wallet2-code.fif" include =: RWCode2
|
||||
|
||||
// pubkey amount --
|
||||
{ over ."Key " pubkey>$ type ." -> "
|
||||
RWCode1 // code
|
||||
<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 6 .Addr cr
|
||||
} : create-wallet1
|
||||
|
||||
// D x t -- D'
|
||||
{ <b rot Gram, swap rot 16 b>idict! not abort"cannot add value"
|
||||
} : rdict-entry
|
||||
// balance -- dict
|
||||
{ dictnew
|
||||
over -32768 rdict-entry
|
||||
over 3/4 */ 92 rdict-entry
|
||||
over 1/2 */ 183 rdict-entry
|
||||
swap 1/4 */ 366 rdict-entry
|
||||
0 548 rdict-entry
|
||||
} : make-rdict
|
||||
|
||||
// pubkey amount --
|
||||
{ over ."Key " pubkey>$ type ." -> "
|
||||
RWCode2 // code
|
||||
<b 1 32 u, 3 pick 256 u, 3 roll make-rdict dict, b> // data
|
||||
empty_cell // libs
|
||||
3 roll // balance
|
||||
0 // split_depth
|
||||
0 // ticktock
|
||||
2 // mode: create
|
||||
register_smc
|
||||
Masterchain 6 .Addr cr
|
||||
} : create-wallet2
|
||||
|
31
submodules/ton/tonlib-src/crypto/smartcont/asm-to-cpp.fif
Executable file
31
submodules/ton/tonlib-src/crypto/smartcont/asm-to-cpp.fif
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <source> <destination> <name>" cr
|
||||
."Compiles asm from <source> file and stores serialization in a way prepared for usage from c++ to <destination> " cr 1 halt
|
||||
} : usage
|
||||
|
||||
|
||||
$# 3 - ' usage if
|
||||
|
||||
|
||||
$1 =: source
|
||||
$2 =: destination
|
||||
$3 =: name
|
||||
|
||||
."Include source from " source type cr
|
||||
source include
|
||||
|
||||
boc>B
|
||||
."Convert boc to base64" cr
|
||||
B>base64
|
||||
|
||||
{ char " chr tuck $+ $+ } : wrp
|
||||
wrp // "<code>"
|
||||
"with_tvm_code(" name wrp $+ +", " swap ");" 10 hold $+ $+ // "with_tm_code("<code>");\n"
|
||||
|
||||
$>B
|
||||
|
||||
."Store tvm code to " destination type cr
|
||||
destination B>file
|
@ -0,0 +1 @@
|
||||
with_tvm_code("config", "te6ccgECFQEAAjUAART/APSkE/Sg8sgLAQIBIAIDAgLHBAUCAvETFAIBzwYHAAaqglsCASAICQIBIA4PAgEgCgsCASAMDQDpAHQ0wP6QDAg+kQBpANxsBOxI8cAsZJfA+AC0x/TPyKCEE5WU1S6jj0yAdTRcfgzIG6SMH+U0NcL/+IDcAS6mzIh8AIh+CO8ArywkQLinYAkWPABghDudk9L8ATgMYIQ7nZPb/AF4BAkXwQgwAABgx6wsfKlgACU7UTQ1FAzgCD0FcjMAc8Wye1UgADM0NMHAcAR8onTH9Mf0w/TDzAgwgDyib7yiYAArHCAGMjLBVAFzxYUy27LH8s/yQH7AIAIBIBAQAgEgERIACSAQPADgAFscfgz0NcL//gjghBOQ29kcIIAxP/IyxAUy/+DHfoCE8tqEssfyz8BzxbJcPsAgAL8IYIQQ2ZQIbqbMdMf1NFAE4Ag9BWORyGCEE5Db2S6jhcx1CH7BCDHAJFbm+1DAu1TIfEGgu1T4o4iIYIQUGJLIbqVMTHT/9GOESGCEE5D7wW6kzHwBpMw8mDi4uIB4gGAArQw7UTQ1IAggCRTMfRqIG6TECNbjjgg0CDXScInjinTB9cLHwHAEfgjEr6wjhUBgCJUEET0blRTIfRuMIAkQBP0WjCTECNb4pQQNF8D4uLIzAHPFsntVIAB5IMI1xgg0x/TH9Mf+CMSufJj7UTQ1NMf0//RUUG68qEF+QFUEGP5EPKi+AAQNBLwBwKkyBLMyx/L/8ntVIA==");
|
344
submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif
Normal file
344
submodules/ton/tonlib-src/crypto/smartcont/auto/config-code.fif
Normal file
@ -0,0 +1,344 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/config-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC set_conf_param
|
||||
DECLPROC check_validator_set
|
||||
DECLPROC send_answer
|
||||
DECLPROC send_confirmation
|
||||
DECLPROC send_error
|
||||
DECLPROC recv_internal
|
||||
DECLPROC change_elector_code
|
||||
1666 DECLMETHOD after_code_upgrade
|
||||
DECLPROC perform_action
|
||||
DECLPROC recv_external
|
||||
DECLPROC run_ticktock
|
||||
set_conf_param PROC:<{
|
||||
// index value
|
||||
c4 PUSH // index value _3
|
||||
CTOS // index value cs
|
||||
LDREF // index value cfg_dict cs
|
||||
s3 s3 XCHG2
|
||||
32 PUSHINT // cs value index cfg_dict _9=32
|
||||
DICTISETREF // cs cfg_dict
|
||||
NEWC // cs cfg_dict _11
|
||||
STREF // cs _12
|
||||
SWAP // _12 cs
|
||||
STSLICER // _13
|
||||
ENDC // _14
|
||||
c4 POP
|
||||
}>
|
||||
check_validator_set PROC:<{
|
||||
// vset
|
||||
CTOS // cs
|
||||
8 LDU // _4 cs
|
||||
SWAP // cs _4
|
||||
17 EQINT // cs _8
|
||||
9 THROWIFNOT
|
||||
32 LDU // utime_since cs
|
||||
32 LDU // utime_since utime_until cs
|
||||
16 LDU // utime_since utime_until total cs
|
||||
16 LDU // utime_since utime_until total _42 _41
|
||||
DROP // utime_since utime_until total main
|
||||
DUP // utime_since utime_until total main main
|
||||
0 GTINT // utime_since utime_until total main _28
|
||||
9 THROWIFNOT
|
||||
GEQ // utime_since utime_until _31
|
||||
9 THROWIFNOT
|
||||
}>
|
||||
send_answer PROC:<{
|
||||
// addr query_id ans_tag mode
|
||||
0 PUSHINT // addr query_id ans_tag mode _4=0
|
||||
24 PUSHINT // addr query_id ans_tag mode _4=0 _5=24
|
||||
NEWC // addr query_id ans_tag mode _4=0 _5=24 _6
|
||||
6 STU // addr query_id ans_tag mode _4=0 _8
|
||||
s0 s5 XCHG2 // _4=0 query_id ans_tag mode _8 addr
|
||||
STSLICER // _4=0 query_id ans_tag mode _9
|
||||
s1 s4 XCHG // mode query_id ans_tag _4=0 _9
|
||||
111 STU // mode query_id ans_tag _23
|
||||
32 STU // mode query_id _25
|
||||
64 STU // mode _27
|
||||
ENDC // mode _28
|
||||
SWAP // _28 mode
|
||||
SENDRAWMSG
|
||||
}>
|
||||
send_confirmation PROC:<{
|
||||
// addr query_id ans_tag
|
||||
64 PUSHINT // addr query_id ans_tag _3=64
|
||||
send_answer CALLDICT
|
||||
}>
|
||||
send_error PROC:<{
|
||||
// addr query_id ans_tag
|
||||
64 PUSHINT // addr query_id ans_tag _3=64
|
||||
send_answer CALLDICT
|
||||
}>
|
||||
recv_internal PROC:<{
|
||||
// in_msg_cell in_msg
|
||||
SWAP // in_msg in_msg_cell
|
||||
CTOS // in_msg cs
|
||||
4 LDU // in_msg flags cs
|
||||
LDMSGADDR // in_msg flags _74 _73
|
||||
DROP // in_msg flags s_addr
|
||||
DUP // in_msg flags s_addr s_addr
|
||||
REWRITESTDADDR // in_msg flags s_addr src_wc src_addr
|
||||
SWAP // in_msg flags s_addr src_addr src_wc
|
||||
INC // in_msg flags s_addr src_addr _15
|
||||
s0 s3 XCHG
|
||||
1 PUSHINT // in_msg _15 s_addr src_addr flags _16=1
|
||||
AND // in_msg _15 s_addr src_addr _17
|
||||
s1 s3 XCHG // in_msg src_addr s_addr _15 _17
|
||||
OR // in_msg src_addr s_addr _18
|
||||
s3 PUSH // in_msg src_addr s_addr _18 in_msg
|
||||
SEMPTY // in_msg src_addr s_addr _18 _19
|
||||
OR // in_msg src_addr s_addr _20
|
||||
IFJMP:<{ // in_msg src_addr s_addr
|
||||
3 BLKDROP //
|
||||
}> // in_msg src_addr s_addr
|
||||
s0 s2 XCHG // s_addr src_addr in_msg
|
||||
32 LDU // s_addr src_addr tag in_msg
|
||||
64 LDU // s_addr src_addr tag query_id in_msg
|
||||
s2 PUSH
|
||||
1314280276 PUSHINT // s_addr src_addr tag query_id in_msg tag _29=1314280276
|
||||
EQUAL // s_addr src_addr tag query_id in_msg _30
|
||||
IFJMP:<{ // s_addr src_addr tag query_id in_msg
|
||||
s2 POP // s_addr src_addr in_msg query_id
|
||||
SWAP // s_addr src_addr query_id in_msg
|
||||
LDREF // s_addr src_addr query_id vset in_msg
|
||||
ENDS
|
||||
1 PUSHINT // s_addr src_addr query_id vset _36=1
|
||||
CONFIGOPTPARAM // s_addr src_addr query_id vset elector_param
|
||||
DUP // s_addr src_addr query_id vset elector_param elector_param
|
||||
ISNULL // s_addr src_addr query_id vset elector_param _39
|
||||
IF:<{ // s_addr src_addr query_id vset elector_param
|
||||
DROP // s_addr src_addr query_id vset
|
||||
-1 PUSHINT // s_addr src_addr query_id vset _40=-1
|
||||
}>ELSE<{ // s_addr src_addr query_id vset elector_param
|
||||
CTOS // s_addr src_addr query_id vset _42
|
||||
256 PLDU // s_addr src_addr query_id vset _40
|
||||
}> // s_addr src_addr query_id vset elector_addr
|
||||
s0 s3 XCHG
|
||||
FALSE
|
||||
s0 s4 XCHG // s_addr ok query_id vset src_addr elector_addr
|
||||
EQUAL // s_addr ok query_id vset _47
|
||||
IF:<{ // s_addr ok query_id vset
|
||||
s2 POP // s_addr vset query_id
|
||||
OVER // s_addr vset query_id vset
|
||||
check_validator_set CALLDICT // s_addr vset query_id t_since t_until
|
||||
OVER
|
||||
NOW // s_addr vset query_id t_since t_until t_since t
|
||||
GREATER // s_addr vset query_id t_since t_until _53
|
||||
s0 s2 XCHG // s_addr vset query_id _53 t_until t_since
|
||||
GREATER // s_addr vset query_id _53 _54
|
||||
AND // s_addr vset query_id ok
|
||||
}>ELSE<{
|
||||
s0 s2 XCHG // s_addr vset query_id ok
|
||||
}>
|
||||
IFJMP:<{ // s_addr vset query_id
|
||||
36 PUSHINT // s_addr vset query_id _56=36
|
||||
ROT // s_addr query_id _56=36 vset
|
||||
set_conf_param CALLDICT
|
||||
4000730955 PUSHINT // s_addr query_id _58=4000730955
|
||||
send_confirmation CALLDICT
|
||||
}> // s_addr vset query_id
|
||||
NIP // s_addr query_id
|
||||
4000730991 PUSHINT // s_addr query_id _60=4000730991
|
||||
send_error CALLDICT
|
||||
}> // s_addr src_addr tag query_id in_msg
|
||||
s2 s4 XCHG
|
||||
4 BLKDROP // tag
|
||||
DUP // tag tag
|
||||
0 EQINT // tag _64
|
||||
SWAP
|
||||
31 PUSHPOW2 // _64 tag _67
|
||||
AND // _64 _68
|
||||
OR // _69
|
||||
37 THROWIFNOT
|
||||
}>
|
||||
change_elector_code PROC:<{
|
||||
// cs
|
||||
1 PUSHINT // cs _2=1
|
||||
CONFIGOPTPARAM // cs _3
|
||||
CTOS // cs _4
|
||||
256 PLDU // cs dest_addr
|
||||
NOW // cs dest_addr query_id
|
||||
1313042276 PUSHINT // cs dest_addr query_id _9=1313042276
|
||||
0 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0
|
||||
50431 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0 _11=50431
|
||||
NEWC // cs dest_addr query_id _9=1313042276 _10=0 _11=50431 _12
|
||||
17 STU // cs dest_addr query_id _9=1313042276 _10=0 _14
|
||||
s1 s4 XCHG // cs _10=0 query_id _9=1313042276 dest_addr _14
|
||||
256 STU // cs _10=0 query_id _9=1313042276 _16
|
||||
30 PUSHPOW2 // cs _10=0 query_id _9=1313042276 _16 _19
|
||||
STGRAMS // cs _10=0 query_id _9=1313042276 _20
|
||||
s1 s3 XCHG // cs _9=1313042276 query_id _10=0 _20
|
||||
107 STU // cs _9=1313042276 query_id _34
|
||||
s1 s2 XCHG // cs query_id _9=1313042276 _34
|
||||
32 STU // cs query_id _36
|
||||
64 STU // cs _38
|
||||
SWAP // _38 cs
|
||||
STSLICER // _39
|
||||
ENDC // _40
|
||||
0 PUSHINT // _40 _41=0
|
||||
SENDRAWMSG
|
||||
}>
|
||||
after_code_upgrade PROC:<{
|
||||
// param old_code
|
||||
2DROP //
|
||||
}>
|
||||
perform_action PROC:<{
|
||||
// cfg_dict public_key action cs
|
||||
OVER
|
||||
1130778657 PUSHINT // cfg_dict public_key action cs action _4=1130778657
|
||||
EQUAL // cfg_dict public_key action cs _5
|
||||
IF:<{ // cfg_dict public_key action cs
|
||||
NIP // cfg_dict public_key cs
|
||||
32 LDU // cfg_dict public_key param_index cs
|
||||
LDREF // cfg_dict public_key param_index param_value cs
|
||||
ENDS
|
||||
s0 s1 s3 XCHG3
|
||||
32 PUSHINT // public_key param_value param_index cfg_dict _15=32
|
||||
DICTISETREF // public_key cfg_dict
|
||||
}>ELSE<{ // cfg_dict public_key action cs
|
||||
OVER
|
||||
1313042276 PUSHINT // cfg_dict public_key action cs action _17=1313042276
|
||||
EQUAL // cfg_dict public_key action cs _18
|
||||
IF:<{ // cfg_dict public_key action cs
|
||||
NIP // cfg_dict public_key cs
|
||||
LDREF // cfg_dict public_key new_code cs
|
||||
OVER // cfg_dict public_key new_code cs new_code
|
||||
SETCODE
|
||||
DUP // cfg_dict public_key new_code cs cs
|
||||
SEMPTY // cfg_dict public_key new_code cs _23
|
||||
IFNOT:<{ // cfg_dict public_key new_code cs
|
||||
c3 PUSH // cfg_dict public_key new_code cs old_code
|
||||
s0 s2 XCHG // cfg_dict public_key old_code cs new_code
|
||||
c3 POP
|
||||
OVER // cfg_dict public_key old_code cs old_code
|
||||
after_code_upgrade CALLDICT
|
||||
c3 POP
|
||||
}>ELSE<{
|
||||
2DROP // cfg_dict public_key
|
||||
}>
|
||||
}>ELSE<{ // cfg_dict public_key action cs
|
||||
OVER
|
||||
1348619041 PUSHINT // cfg_dict public_key action cs action _29=1348619041
|
||||
EQUAL // cfg_dict public_key action cs _30
|
||||
IF:<{ // cfg_dict public_key action cs
|
||||
NIP
|
||||
NIP // cfg_dict cs
|
||||
256 LDU // cfg_dict public_key cs
|
||||
ENDS
|
||||
}>ELSE<{ // cfg_dict public_key action cs
|
||||
OVER
|
||||
1313074949 PUSHINT // cfg_dict public_key action cs action _35=1313074949
|
||||
EQUAL // cfg_dict public_key action cs _36
|
||||
IF:<{ // cfg_dict public_key action cs
|
||||
NIP // cfg_dict public_key cs
|
||||
change_elector_code CALLDICT
|
||||
}>ELSE<{ // cfg_dict public_key action cs
|
||||
DROP // cfg_dict public_key action
|
||||
32 THROWIF
|
||||
}>
|
||||
}>
|
||||
}>
|
||||
SWAP // public_key cfg_dict
|
||||
}>
|
||||
SWAP // cfg_dict public_key
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
9 PUSHPOW2 // in_msg _3=512
|
||||
LDSLICEX // signature in_msg
|
||||
DUP // signature in_msg cs
|
||||
32 LDU // signature in_msg action cs
|
||||
32 LDU // signature in_msg action msg_seqno cs
|
||||
32 LDU // signature in_msg action msg_seqno valid_until cs
|
||||
NOW // signature in_msg action msg_seqno valid_until cs _19
|
||||
s1 s2 XCHG // signature in_msg action msg_seqno cs valid_until _19
|
||||
LESS // signature in_msg action msg_seqno cs _20
|
||||
35 THROWIF
|
||||
c4 PUSH // signature in_msg action msg_seqno cs _23
|
||||
CTOS // signature in_msg action msg_seqno cs cs2
|
||||
LDREF // signature in_msg action msg_seqno cs cfg_dict cs2
|
||||
32 LDU // signature in_msg action msg_seqno cs cfg_dict stored_seqno cs2
|
||||
256 LDU // signature in_msg action msg_seqno cs cfg_dict stored_seqno public_key cs2
|
||||
ENDS
|
||||
s4 s1 XCPU // signature in_msg action public_key cs cfg_dict stored_seqno msg_seqno stored_seqno
|
||||
EQUAL // signature in_msg action public_key cs cfg_dict stored_seqno _38
|
||||
33 THROWIFNOT
|
||||
s0 s5 XCHG // signature stored_seqno action public_key cs cfg_dict in_msg
|
||||
HASHSU // signature stored_seqno action public_key cs cfg_dict _41
|
||||
s0 s6 s3 XC2PU // cfg_dict stored_seqno action public_key cs _41 signature public_key
|
||||
CHKSIGNU // cfg_dict stored_seqno action public_key cs _42
|
||||
34 THROWIFNOT
|
||||
ACCEPT
|
||||
s3 s4 XCHG
|
||||
s1 s2 XCHG // stored_seqno cfg_dict public_key action cs
|
||||
perform_action CALLDICT // stored_seqno cfg_dict public_key
|
||||
s0 s2 XCHG // public_key cfg_dict stored_seqno
|
||||
INC // public_key cfg_dict _47
|
||||
NEWC // public_key cfg_dict _47 _48
|
||||
s1 s2 XCHG // public_key _47 cfg_dict _48
|
||||
STREF // public_key _47 _49
|
||||
32 STU // public_key _51
|
||||
256 STU // _53
|
||||
ENDC // _54
|
||||
c4 POP
|
||||
}>
|
||||
run_ticktock PROC:<{
|
||||
// is_tock
|
||||
DROP //
|
||||
c4 PUSH // _2
|
||||
CTOS // cs
|
||||
LDREF // cfg_dict cs
|
||||
32 PUSHINT // cfg_dict cs kl=32
|
||||
36 PUSHINT // cfg_dict cs kl=32 _10=36
|
||||
s3 s1 PUSH2 // cfg_dict cs kl=32 _10=36 cfg_dict kl=32
|
||||
DICTIGETOPTREF // cfg_dict cs kl=32 next_vset
|
||||
DUP // cfg_dict cs kl=32 next_vset next_vset
|
||||
ISNULL // cfg_dict cs kl=32 next_vset _12
|
||||
IFNOT:<{ // cfg_dict cs kl=32 next_vset
|
||||
DUP // cfg_dict cs kl=32 next_vset next_vset
|
||||
CTOS // cfg_dict cs kl=32 next_vset ds
|
||||
DUP // cfg_dict cs kl=32 next_vset ds ds
|
||||
SBITS // cfg_dict cs kl=32 next_vset ds _15
|
||||
39 GTINT // cfg_dict cs kl=32 next_vset ds _17
|
||||
IF:<{ // cfg_dict cs kl=32 next_vset ds
|
||||
8 LDU // cfg_dict cs kl=32 next_vset tag ds
|
||||
32 PLDU // cfg_dict cs kl=32 next_vset tag since
|
||||
SWAP // cfg_dict cs kl=32 next_vset since tag
|
||||
17 EQINT // cfg_dict cs kl=32 next_vset since _26
|
||||
NOW // cfg_dict cs kl=32 next_vset since _26 _27
|
||||
s1 s2 XCHG // cfg_dict cs kl=32 next_vset _26 since _27
|
||||
GEQ // cfg_dict cs kl=32 next_vset _26 _28
|
||||
AND // cfg_dict cs kl=32 next_vset _29
|
||||
IF:<{ // cfg_dict cs kl=32 next_vset
|
||||
SWAP
|
||||
34 PUSHINT
|
||||
s0 s4 s4 XC2PU // kl=32 cs next_vset _32=34 cfg_dict kl=32
|
||||
DICTISETGETOPTREF // kl=32 cs cfg_dict cur_vset
|
||||
s3 s1 s0 PUXCPU // kl=32 cs cur_vset _35=32 cfg_dict kl=32
|
||||
DICTISETGETOPTREF // kl=32 cs _51 _52
|
||||
DROP // kl=32 cs cfg_dict
|
||||
36 PUSHINT // kl=32 cs cfg_dict _38=36
|
||||
s0 s1 s3 XCHG3 // cs _38=36 cfg_dict kl=32
|
||||
DICTIDEL // cs _53 _54
|
||||
DROP // cs cfg_dict
|
||||
}>ELSE<{
|
||||
s2 s3 XCHG
|
||||
2DROP // cs cfg_dict
|
||||
}>
|
||||
}>ELSE<{
|
||||
s3 s4 XCHG
|
||||
3 BLKDROP // cs cfg_dict
|
||||
}>
|
||||
}>ELSE<{
|
||||
s2 s3 XCHG
|
||||
2DROP // cs cfg_dict
|
||||
}>
|
||||
NEWC // cs cfg_dict _40
|
||||
STREF // cs _41
|
||||
SWAP // _41 cs
|
||||
STSLICER // _42
|
||||
ENDC // _43
|
||||
c4 POP
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("elector-code", "te6ccgECVAEACrkAART/APSkE/Sg8sgLAQIBIAIDAgFIBAUAUaX//xh2omh6AnoCETdKrPgN+SBOKjgQ+At5ICz4DPkgcXgL+SB4DRhAAgLFBgcCASAKCwIBywgJACyqgjGCEE5Db2SCEM5Db2RwQzCAQPAGAgEgEBECASAzNAIDeqAMDQIBbg4PACSqB+1E0PQFIG6SMHCU0NcLH+IAQqss7UTQ9AUgbpJbcODwAxAmXwaDB/QOb6GT+gAwkjBw4gBzsKV7UTQ9AUgbpIwbeDwAxAmXwZthP+OHiKDB/R+b6FvoSCcAvoAMFIQbwJQA28Cklow4gGzEuYwMYAAzs+A7UTQ9AQx9AQwgwf0Dm+hk/oAMJIwcOKACASASEwIBICMkAgEgFBUCASAdHgIBIBYXAgEgGxwBASAYACE7UTQ9AT0BPQE+gDTH9P/0YAL8AdDTAwFxsJJfA+D6QDAhxwCUMQHwEOAB0x8hwACUWwHwEODTPyKCEE5zdEu6lTIQI/AL4DQhghBHZXQkupMT8BHgIYIQTkNvZLqOGVRSRPASloIQzkNvZJKEH+JwEDRDMIBA8AbgIYIQ7nZPS7oighDudk9vulIQsYrgMDMgGRoADDIQIwHwDwAkgx6wm4QfcBA0QzCAQPAG4V8DACkyBb0ABT0ABL0AAH6Assfy//J7VSAAITQ0x/TH/oA+gD0BNIA0gDRgAgEgHyACASAhIgArMgXyx8Vyx9QA/oCAfoC9ADKAMoAyYAAdIAP+DPQ0h/SH9If1wofgAEUcIAYyMsFUAfPFlj6AhXLahPLH8s/IcL/kssfkTHiyQH7AIAAbIIQ7m9FTHBDMIBA8AaACASAlJgIBIC0uAgEgJygCASApKgAjIIQ83RITIIQO5rKAEMwcvAGgAEcghBOVlNUcIIAxP/IyxAVy/+DHfoCFMtqE8sfEss/zMlx+wCAAMxTEoMH9A5voZT6ADCgkTDiyAH6AgKDB/RDgAQEgKwH+I/pE7UTQ9AQhbgSkFLGXEDVfBXDwB+AE0//TH9Mf0//UAdCDCNcZAdGCEGVMUHTIyx9SQMsfUjDLH1Jgy/9SIMv/ydBRFfkRlxBoXwhx8AfhIYMPuZcQaF8IdvAH4AfwAzEF/iANghA7msoAoSCqCyO5mBC8XwwxcvAH4FEioCwA/lF9vZcQrF8Mc/AH4ASXEJtfC3DwB+BTY4MH9A5voSCfMPoAWaAB0z8x0/8wUoC9kTHilxCbXwt08AfgUwG5lxCbXwt18AfgIPKs+AD4I8hY+gLLHxTLHxbL/xjL/0A3gwf0Q3AQVxA0ECMQJnDwBMj0AAHPFsntVCCTcPAI4FsCASAvMAIBIDEyAHkcCB/jjAkgwf0fG+hb6EgjhwC0//TPzH6ANIA0ZQxUTOgl1QYiPAKBwPiUEOgk1BCMOIBsxPmMDMBuvK7gAKEcFMAf447JoMH9HxvoW+hII4nAtP/0z8x+gDSANGUMVEzoI4RVHcIqYRRZqBSF6BLsPAKCQPiUFOgk1BSMOIBsxTmMDUDulMhu7DyuxKgAaGAAVwBgCD0Zm+hkjBw4dM/MdP/MfQE+gD6APQEMdEgwgCUEDTwDZUwECPwDOISgAKMMgL6RHD4M9DXC//tRND0BASkWr2xIW6xkl8E4PADBV8FUhW9BLMUsZJfA+D4AAGRW44d9AT0BPoAQzTwDnDIygAT9AD0AFmg+gIBzxbJ7VTigAgEgNTYCAUhOTwIBIDc4AgEgPT4CASA5OgIBIDs8AKU8AEH+kQBpLEhwACxlwWgVRMB8ALgUwKAIPQOb6GOJ9M/0//0BPoA+gALoMgVyz8Ty//0AAH6AgH6AlAGzxYBgCBURkT0Q5QwBaAB4hA1QUPwAoADZDEh+kQBpJ8wghD////+cBA0E4BA8Abg7UTQ9AT0BFAzgwf0Zm+hjhBfBIIQ/////nAQNBOAQPAG4TYF+gDRyBL0ABX0AAHPFsntVIIQ+W9zJHCAGMjLBVAEzxZQBPoCEstqEssfyz/JgED7AIABpHD4MyBuk18EcODQ1wv/I/pEAaQCvbGTXwNw4PgAAdQh+wQgxwCSXwSZAe1TAfEGgvIA4n+AAAxwgAgEgP0ACASBJSgA1HACjhMCbyIhbxACbxEkqKsPErYIEqBY5DAxgAQEgQQP+gBD4M9DTD9MPMdMP0XG2CXBtf45GKYMH9HxvoW+hII4wAvoA0x/TH9P/0//RA6PIFct/FMofUkDL/8nQURq2CMjLHxPL/8v/QBSBAaD0QQOklBA0WjDiAbNDMOYwNFi2CFMBuZZfB21tcCDgbYrmMzSlXJJvEeRwIIrmMjI0NEJDRABqA4EBoPSSb6FvoSCOIAHTf1EZtggB0x8x1wv/A9Mf0/8x1wv/QTAUbwRQBW8Ck0YWW+IEsxQASgJvIgFvEASkU0i+jhBUZQbwFFMCvJMyMiKSEzDik1A0MOJTNr4BXiLAAFJDuRKxll8EbW1wIOAg/iAipZJvEeRvEG8QcCBtbYrmMzMzNVIUuvKxECMBRQL+BW8iAW8kUxyDB/QOb6HyvfoAMdM/MdcL/1OLuY5XUTmoqw9SQLYIUUShJKo7LakEUYWgghCOgSeKI5KAc5KAU+LIywfLH1JAy/9SkMs/I5MTy/+TUAMw4gGAEFRKmfRDcCTIy/8Zyz9QBfoCF8oAQBmDB/RDlgoQRgNfA+IjikZHAAhLc/AKARiK4gOkKW4QShBGREBIAAZLc1sBASBLAa08AGAIvgz+QBTAbqTXwdw4CKOL1MkgCD0Dm+hjh/THzEg0x/T/zBQBLryufgjUAOgyMsfWM8WQASAIPRDlBUTXwPik0QUW+J/iuYgbpIwcJDiUAPwAn+BNAf4B8AM0+CMluZNfCHDgcPgzbpRfCPAT4IAR+DPQ+gD6APoA0x/RU2G5lF8M8BPgBJRfC/AT4AaTXwpw4BA4KFEyUHfwFSDAACCzKgYQWhBJEDhMzPAEIo4TMjIyMjLIEvQA9AABzxbJ7VTwE+HwBTL4IwGgpsQotgmAEPgz0IAQTADI1yHXCw9SYLYIUxOggBHIywdSMMsfyx8Xyw8Wyw8J0BnPFslw+DPQ1wv/UxjwCQn0BHAL+QBQY6ApoMjLHxnLH8v/FfQAUAP6AnD6AhbKAEA0gCD0Q8gT9AD0APQAAc8Wye1UfwCkIYAg9HxvoW+hII4/AtM/0/9TF7qOLTQD9AT6APoAKKsCUZmhUCmgyBXLPxbL/xL0AAH6AgH6AljPFgGAIFRBRPRDcJYQNRA0XwPik0MDMOKzEgIBIFBRAgEgUlMAGQhbpJbcJUB+QABuuKAAlQB8AMFXwWTXwNw4QL0BFExgCD0Dm+hk18EcOGAQNch1wv/gCL4MyHwGIAk+DNY8BixjhNwyMoAEvQA9AABzxbJ7VTwFzB/4F8DcIACTPABf44+JIAg9HxvoW+hII4kAtMfMPgju1MUvbCOETFUFUTwDhSgVHYTVHNY8AJwlEYVUETilhA3FkUFMOKzECYQRRTmBl8GbrOAA4QxgCT4M26SW3Dhcfgz0NcL//go+kQBpAK9sZJbcOCAIvgzIG6TXwNw4PAFMDIC0IAo1yHXCx/4I1EToVy5k18GcOBcocE8kTGRMOKAEfgz0PoAMAOg/iBSAqFwbXAQRRA0cPAEyPQA9AABzxbJ7VR/g");
|
1712
submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif
Normal file
1712
submodules/ton/tonlib-src/crypto/smartcont/auto/elector-code.fif
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
||||
with_tvm_code("highload-wallet", "te6ccgEBBgEAhgABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==");
|
@ -0,0 +1,79 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC recv_internal
|
||||
DECLPROC recv_external
|
||||
85143 DECLMETHOD seqno
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
9 PUSHPOW2 // in_msg _3=512
|
||||
LDSLICEX // signature in_msg
|
||||
DUP // signature in_msg cs
|
||||
32 LDU // signature in_msg _9 cs
|
||||
32 LDU // signature in_msg _9 _12 cs
|
||||
32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
|
||||
NOW // signature in_msg subwallet_id valid_until msg_seqno cs _19
|
||||
s1 s3 XCHG // signature in_msg subwallet_id cs msg_seqno valid_until _19
|
||||
LEQ // signature in_msg subwallet_id cs msg_seqno _20
|
||||
35 THROWIF
|
||||
c4 PUSH // signature in_msg subwallet_id cs msg_seqno _23
|
||||
CTOS // signature in_msg subwallet_id cs msg_seqno ds
|
||||
32 LDU // signature in_msg subwallet_id cs msg_seqno _28 ds
|
||||
32 LDU // signature in_msg subwallet_id cs msg_seqno _28 _31 ds
|
||||
256 LDU // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds
|
||||
ENDS
|
||||
s3 s2 XCPU // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet msg_seqno stored_seqno
|
||||
EQUAL // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet _39
|
||||
33 THROWIFNOT
|
||||
s4 s4 XCPU // signature in_msg stored_subwallet cs public_key stored_seqno subwallet_id stored_subwallet
|
||||
EQUAL // signature in_msg stored_subwallet cs public_key stored_seqno _42
|
||||
34 THROWIFNOT
|
||||
s0 s4 XCHG // signature stored_seqno stored_subwallet cs public_key in_msg
|
||||
HASHSU // signature stored_seqno stored_subwallet cs public_key _45
|
||||
s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs _45 signature public_key
|
||||
CHKSIGNU // public_key stored_seqno stored_subwallet cs _46
|
||||
35 THROWIFNOT
|
||||
LDDICT // public_key stored_seqno stored_subwallet dict cs
|
||||
ENDS
|
||||
ACCEPT
|
||||
-1 PUSHINT // public_key stored_seqno stored_subwallet dict i=-1
|
||||
UNTIL:<{
|
||||
OVER
|
||||
16 PUSHINT // public_key stored_seqno stored_subwallet dict i dict _57=16
|
||||
DICTIGETNEXT
|
||||
NULLSWAPIFNOT
|
||||
NULLSWAPIFNOT // public_key stored_seqno stored_subwallet dict cs i f
|
||||
DUP // public_key stored_seqno stored_subwallet dict cs i f f
|
||||
IF:<{ // public_key stored_seqno stored_subwallet dict cs i f
|
||||
s0 s2 XCHG // public_key stored_seqno stored_subwallet dict f i cs
|
||||
8 LDU // public_key stored_seqno stored_subwallet dict f i mode cs
|
||||
LDREF // public_key stored_seqno stored_subwallet dict f i mode _100 _99
|
||||
DROP // public_key stored_seqno stored_subwallet dict f i mode _63
|
||||
SWAP // public_key stored_seqno stored_subwallet dict f i _63 mode
|
||||
SENDRAWMSG
|
||||
}>ELSE<{
|
||||
s2 POP // public_key stored_seqno stored_subwallet dict f i
|
||||
}>
|
||||
SWAP // public_key stored_seqno stored_subwallet dict i f
|
||||
NOT // public_key stored_seqno stored_subwallet dict i _66
|
||||
}> // public_key stored_seqno stored_subwallet dict i
|
||||
2DROP // public_key stored_seqno stored_subwallet
|
||||
SWAP // public_key stored_subwallet stored_seqno
|
||||
INC // public_key stored_subwallet _68
|
||||
NEWC // public_key stored_subwallet _68 _69
|
||||
32 STU // public_key stored_subwallet _71
|
||||
32 STU // public_key _73
|
||||
256 STU // _75
|
||||
ENDC // _76
|
||||
c4 POP
|
||||
}>
|
||||
seqno PROC:<{
|
||||
//
|
||||
c4 PUSH // _0
|
||||
CTOS // _1
|
||||
32 PLDU // _3
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("highoad-wallet-v2", "te6ccgEBBwEA1wABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQHu8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44YIYAQ9HhvoW+hIJgC0wfUMAH7AJEy4gGz5luDJaHIQDSAQPRDiuYxyBLLHxPLP8v/9ADJ7VQGAATQMABBoZfl2omhpj5jpn+n/mPoCaKkQQCB6BzfQmMktv8ld0fFADoggED0lm+hb6EyURCUMFMDud4gkjM2k0MTW+IBsw==");
|
@ -0,0 +1,134 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-v2-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC recv_internal
|
||||
DECLPROC recv_external
|
||||
117746 DECLMETHOD processed?
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
9 PUSHPOW2 // in_msg _3=512
|
||||
LDSLICEX // signature in_msg
|
||||
DUP // signature in_msg cs
|
||||
32 LDU // signature in_msg _8 cs
|
||||
64 LDU // signature in_msg subwallet_id query_id cs
|
||||
NOW // signature in_msg subwallet_id query_id cs _15
|
||||
32 LSHIFT# // signature in_msg subwallet_id query_id cs bound
|
||||
s2 s0 PUSH2 // signature in_msg subwallet_id query_id cs bound query_id bound
|
||||
LESS // signature in_msg subwallet_id query_id cs bound _19
|
||||
35 THROWIF
|
||||
c4 PUSH // signature in_msg subwallet_id query_id cs bound _22
|
||||
CTOS // signature in_msg subwallet_id query_id cs bound ds
|
||||
32 LDU // signature in_msg subwallet_id query_id cs bound _28 ds
|
||||
64 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 ds
|
||||
256 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 _34 ds
|
||||
LDDICT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries ds
|
||||
ENDS
|
||||
s6 s0 PUSH2
|
||||
64 PUSHINT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries query_id old_queries _42=64
|
||||
DICTUGET
|
||||
NULLSWAPIFNOT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries _115 _116
|
||||
NIP // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries found?
|
||||
32 THROWIF
|
||||
s7 s3 XCPU // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key subwallet_id stored_subwallet
|
||||
EQUAL // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key _47
|
||||
34 THROWIFNOT
|
||||
s0 s7 XCHG // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned in_msg
|
||||
HASHSU // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned _50
|
||||
s0 s8 s7 XC2PU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _50 signature public_key
|
||||
CHKSIGNU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _51
|
||||
35 THROWIFNOT
|
||||
s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound cs
|
||||
LDDICT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs
|
||||
ENDS
|
||||
ACCEPT
|
||||
-1 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i=-1
|
||||
UNTIL:<{
|
||||
OVER
|
||||
16 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i dict _62=16
|
||||
DICTIGETNEXT
|
||||
NULLSWAPIFNOT
|
||||
NULLSWAPIFNOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f
|
||||
DUP // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f f
|
||||
IF:<{ // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f
|
||||
s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i cs
|
||||
8 LDU // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode cs
|
||||
LDREF // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _125 _124
|
||||
DROP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _68
|
||||
SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i _68 mode
|
||||
SENDRAWMSG
|
||||
}>ELSE<{
|
||||
s2 POP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i
|
||||
}>
|
||||
SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict i f
|
||||
NOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i _71
|
||||
}> // last_cleaned public_key old_queries query_id stored_subwallet bound dict i
|
||||
2DROP // last_cleaned public_key old_queries query_id stored_subwallet bound
|
||||
38 PUSHPOW2 // last_cleaned public_key old_queries query_id stored_subwallet bound _74
|
||||
SUB // last_cleaned public_key old_queries query_id stored_subwallet bound
|
||||
NEWC // last_cleaned public_key old_queries query_id stored_subwallet bound _77
|
||||
s0 s3 s4 XCHG3
|
||||
64 PUSHINT // last_cleaned public_key stored_subwallet bound _77 query_id old_queries _78=64
|
||||
DICTUSETB // last_cleaned public_key stored_subwallet bound old_queries
|
||||
UNTIL:<{
|
||||
DUP
|
||||
64 PUSHINT // last_cleaned public_key stored_subwallet bound old_queries old_queries _85=64
|
||||
DICTUREMMIN
|
||||
NULLSWAPIFNOT
|
||||
NULLSWAPIFNOT // last_cleaned public_key stored_subwallet bound old_queries _126 _128 _127 _129
|
||||
s2 POP // last_cleaned public_key stored_subwallet bound old_queries old_queries' f i
|
||||
s1 s0 XCPU // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f
|
||||
IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||
DROP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i
|
||||
s0 s3 PUSH2 // last_cleaned public_key stored_subwallet bound old_queries old_queries' i i bound
|
||||
LESS // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||
}> // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||
DUP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f
|
||||
IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||
s3 POP
|
||||
s6 POP // last_cleaned public_key stored_subwallet bound f old_queries
|
||||
}>ELSE<{
|
||||
s3 s1 s3 XCHG3
|
||||
2DROP // last_cleaned public_key stored_subwallet bound f old_queries
|
||||
}>
|
||||
SWAP // last_cleaned public_key stored_subwallet bound old_queries f
|
||||
NOT // last_cleaned public_key stored_subwallet bound old_queries _90
|
||||
}> // last_cleaned public_key stored_subwallet bound old_queries
|
||||
NIP // last_cleaned public_key stored_subwallet old_queries
|
||||
NEWC // last_cleaned public_key stored_subwallet old_queries _91
|
||||
s1 s2 XCHG // last_cleaned public_key old_queries stored_subwallet _91
|
||||
32 STU // last_cleaned public_key old_queries _93
|
||||
s1 s3 XCHG // old_queries public_key last_cleaned _93
|
||||
64 STU // old_queries public_key _95
|
||||
256 STU // old_queries _97
|
||||
STDICT // _98
|
||||
ENDC // _99
|
||||
c4 POP
|
||||
}>
|
||||
processed? PROC:<{
|
||||
// query_id
|
||||
c4 PUSH // query_id _2
|
||||
CTOS // query_id ds
|
||||
32 LDU // query_id _29 _28
|
||||
NIP // query_id ds
|
||||
64 LDU // query_id _11 ds
|
||||
256 LDU // query_id _11 _33 _32
|
||||
NIP // query_id _11 ds
|
||||
LDDICT // query_id last_cleaned old_queries ds
|
||||
ENDS
|
||||
s2 s(-1) PUXC
|
||||
64 PUSHINT // query_id last_cleaned query_id old_queries _22=64
|
||||
DICTUGET
|
||||
NULLSWAPIFNOT // query_id last_cleaned _36 _37
|
||||
NIP // query_id last_cleaned found
|
||||
IF:<{ // query_id last_cleaned
|
||||
2DROP //
|
||||
TRUE // _24
|
||||
}>ELSE<{ // query_id last_cleaned
|
||||
LEQ // _26
|
||||
NEGATE // _24
|
||||
}>
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("multisig", "te6ccgECMAEAA2oAART/APSkE/Sg8sgLAQIBIAIDAgFICAkEwPIgxwCOgzDbPOCDCNcYIPkBAdMH2zwiwAAToVNhePQOb6Hyn9cL/0iQ+RDyoAP0BCD5AQHTP/gjqh9TILnyYVMngED0Dm+hECNUSADbPAquXLDyYrEBpPgAVDiTVHo5KxcvFgQEnts8VHCrU5rbPO1U+A9wJm5TqL6xmBA6EHlQdl8GiuIEgyWhjichgED0lm+hb6EyURCUMFMCud4glDQ2N3+XEEkQR0QUW+ICsxBXECXmMAMaHwUGAiowKkZTBts8UHegECQQN0EGU1bbPH8kGgEKipJfBeIHAQwQJNs87VQfAgLNCgsCASAbHAIBIAwNAgEgEhMCASAODwIBIBARAAMMIAEBIC8BASAfAQEgJAIBIBQVAgEgGBkBASAWAQEgFwA4jhXSAAHyo9MHWNcBIPkBBPkBFLrypFjgW3BSAgIc2zwC8mX4AFpxAts87VQvHwEBIBoATwhbpEx4CBukTDgAdAg10rDAJrUAvAHyFjPFszJ4HHXI8gBzxb0AMmAAaFIwvo4aXwOTIddKmAHTB9QC+wAB6DFwyMoAAoBA9EOOEnHIywATywdYzwFYzxYCgED0Q+ICASAdHgIBICUmARO77ZbVAjcFnbPIHwIBSCAhABjIywfLB8s/9AD0AMkCASAiIwF5sR10IMI1xgg+QEB0weCAdTE7UPYUyB49A5vofKf1wv/XjH5EPKgrgH0BCFulhAjXwNxAeD5AVjbPAGkAYCQAPa7agOgA6AD6AgF6AhH8gID8gN15T/gD5HoAAOeLZMAAFa4ZV0EA1WZ2oexAAGBwjikD0IMI1xjTB/QEMFMWePQOb6HypdcL/1RFRPkQ8qauUiCxUgO9FKEjbuYyMjICASAnKAIBSCkqAVW3JVtnhiZQCAqIhn6BzfQxwmYmQDpAADMaYOYuAFrgJhwLb+4cBgY3dG4QLwGNtVmbZ4Br4G/tscbqIlAIHo+N9C30JBHEgFpAADHDRA8a5CTa4GT2E5kAOeLAMAgKiCq+iHJCZhxSQmYcUktGHEA2fMCL4JAvAgEgKywCA5k4LS4BDawabZ4vgcAvABWt+UEAzJV2oewYQAENqTbPBRfBIC8AFa3cLOCAarM7UPYgABztRNDTB9MH0z/0BPQE0Q==");
|
@ -0,0 +1,502 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/multisig-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC unpack_state
|
||||
DECLPROC pack_state
|
||||
DECLPROC check_signatures
|
||||
DECLPROC recv_internal
|
||||
DECLPROC unpack_query_data
|
||||
DECLPROC try_init
|
||||
DECLPROC update_pending_queries
|
||||
DECLPROC recv_external
|
||||
104746 DECLMETHOD get_query_state
|
||||
117746 DECLMETHOD processed?
|
||||
81625 DECLMETHOD create_init_state
|
||||
DECLPROC merge_list
|
||||
120004 DECLMETHOD get_public_keys
|
||||
87157 DECLMETHOD check_query_signatures
|
||||
109260 DECLMETHOD messages_by_mask
|
||||
85042 DECLMETHOD get_messages_unsigned_by_id
|
||||
120055 DECLMETHOD get_messages_unsigned
|
||||
114740 DECLMETHOD get_n_k
|
||||
83381 DECLMETHOD merge_inner_queries
|
||||
unpack_state PROCREF:<{
|
||||
//
|
||||
c4 PUSH // _1
|
||||
CTOS // ds
|
||||
8 LDU // _4 ds
|
||||
8 LDU // _4 _7 ds
|
||||
64 LDU // _4 _7 _10 ds
|
||||
LDDICT // _4 _7 _10 _13 ds
|
||||
LDDICT // res res res res res ds
|
||||
ENDS
|
||||
}>
|
||||
pack_state PROCREF:<{
|
||||
// pending_queries public_keys last_cleaned k n
|
||||
NEWC // pending_queries public_keys last_cleaned k n _5
|
||||
8 STU // pending_queries public_keys last_cleaned k _7
|
||||
8 STU // pending_queries public_keys last_cleaned _9
|
||||
64 STU // pending_queries public_keys _11
|
||||
STDICT // pending_queries _12
|
||||
STDICT // _13
|
||||
ENDC // _14
|
||||
}>
|
||||
check_signatures PROCREF:<{
|
||||
// public_keys signatures hash cnt_bits
|
||||
0 PUSHINT // public_keys signatures hash cnt_bits cnt=0
|
||||
UNTIL:<{
|
||||
s0 s3 XCHG // public_keys cnt hash cnt_bits signatures
|
||||
CTOS // public_keys cnt hash cnt_bits cs
|
||||
9 PUSHPOW2 // public_keys cnt hash cnt_bits cs _10=512
|
||||
LDSLICEX // public_keys cnt hash cnt_bits signature cs
|
||||
8 LDU // public_keys cnt hash cnt_bits signature i cs
|
||||
LDDICT // public_keys cnt hash cnt_bits signature i _43 _42
|
||||
DROP // public_keys cnt hash cnt_bits signature i signatures
|
||||
s1 s6 PUSH2
|
||||
8 PUSHINT // public_keys cnt hash cnt_bits signature i signatures i public_keys _20=8
|
||||
DICTUGET
|
||||
NULLSWAPIFNOT // public_keys cnt hash cnt_bits signature i signatures public_key found?
|
||||
37 THROWIFNOT
|
||||
256 PLDU // public_keys cnt hash cnt_bits signature i signatures _26
|
||||
s5 s3 s3 PUXC2 // public_keys cnt hash cnt_bits signatures i hash signature _26
|
||||
CHKSIGNU // public_keys cnt hash cnt_bits signatures i _27
|
||||
38 THROWIFNOT
|
||||
POW2 // public_keys cnt hash cnt_bits signatures mask
|
||||
s2 s(-1) PUXC // public_keys cnt hash old_cnt_bits signatures cnt_bits mask
|
||||
OR // public_keys cnt hash old_cnt_bits signatures cnt_bits
|
||||
s0 s2 PUXC // public_keys cnt hash cnt_bits signatures cnt_bits old_cnt_bits
|
||||
NEQ // public_keys cnt hash cnt_bits signatures should_check
|
||||
s1 s4 XCHG // public_keys signatures hash cnt_bits cnt should_check
|
||||
SUB // public_keys signatures hash cnt_bits cnt
|
||||
s3 PUSH // public_keys signatures hash cnt_bits cnt signatures
|
||||
ISNULL // public_keys signatures hash cnt_bits cnt _37
|
||||
}> // public_keys signatures hash cnt_bits cnt
|
||||
s2 POP
|
||||
s2 POP
|
||||
s2 POP // cnt cnt_bits
|
||||
}>
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
unpack_query_data PROCREF:<{
|
||||
// in_msg n query found?
|
||||
IFJMP:<{ // in_msg n query
|
||||
1 LDI // in_msg n _5 query
|
||||
SWAP // in_msg n query _5
|
||||
35 THROWIFNOT
|
||||
8 LDU // in_msg n _12 query
|
||||
ROT // in_msg _12 query n
|
||||
LDUX // in_msg cnt cnt_bits msg
|
||||
DUP // in_msg cnt cnt_bits msg msg
|
||||
HASHSU // in_msg cnt cnt_bits msg _18
|
||||
s0 s4 XCHG // _18 cnt cnt_bits msg in_msg
|
||||
HASHSU // _18 cnt cnt_bits msg _19
|
||||
s1 s4 XCHG // msg cnt cnt_bits _18 _19
|
||||
EQUAL // msg cnt cnt_bits _20
|
||||
36 THROWIFNOT
|
||||
ROT // cnt cnt_bits msg
|
||||
}> // in_msg n query
|
||||
2DROP // in_msg
|
||||
0 PUSHINT // in_msg _22=0
|
||||
s0 s1 PUXC // _22=0 _23=0 in_msg
|
||||
}>
|
||||
try_init PROCREF:<{
|
||||
//
|
||||
unpack_state INLINECALLDICT // n k last_cleaned public_keys pending_queries
|
||||
s0 s2 XCHG // n k pending_queries public_keys last_cleaned
|
||||
37 THROWIF
|
||||
ACCEPT
|
||||
2SWAP
|
||||
1 PUSHINT
|
||||
s0 s2 XCHG // pending_queries public_keys _9=1 k n
|
||||
pack_state INLINECALLDICT // _10
|
||||
c4 POP
|
||||
}>
|
||||
update_pending_queries PROCREF:<{
|
||||
// pending_queries msg query_id cnt cnt_bits n k
|
||||
s3 s(-1) PUXC // pending_queries msg query_id cnt cnt_bits n cnt k
|
||||
GEQ // pending_queries msg query_id cnt cnt_bits n _7
|
||||
IF:<{ // pending_queries msg query_id cnt cnt_bits n
|
||||
3 BLKDROP // pending_queries msg query_id
|
||||
WHILE:<{
|
||||
OVER // pending_queries msg query_id msg
|
||||
SREFS // pending_queries msg query_id _8
|
||||
}>DO<{ // pending_queries msg query_id
|
||||
SWAP // pending_queries query_id msg
|
||||
8 LDU // pending_queries query_id mode msg
|
||||
LDREF // pending_queries query_id mode _13 msg
|
||||
s0 s2 XCHG // pending_queries query_id msg _13 mode
|
||||
SENDRAWMSG
|
||||
SWAP // pending_queries msg query_id
|
||||
}> // pending_queries msg query_id
|
||||
NIP // pending_queries query_id
|
||||
0 PUSHINT // pending_queries query_id _17=0
|
||||
NEWC // pending_queries query_id _17=0 _18
|
||||
1 STI // pending_queries query_id _20
|
||||
s0 s2 XCHG
|
||||
64 PUSHINT // _20 query_id pending_queries _21=64
|
||||
DICTUSETB // pending_queries
|
||||
}>ELSE<{ // pending_queries msg query_id cnt cnt_bits n
|
||||
1 PUSHINT // pending_queries msg query_id cnt cnt_bits n _24=1
|
||||
NEWC // pending_queries msg query_id cnt cnt_bits n _24=1 _25
|
||||
1 STU // pending_queries msg query_id cnt cnt_bits n _27
|
||||
s1 s3 XCHG // pending_queries msg query_id n cnt_bits cnt _27
|
||||
8 STU // pending_queries msg query_id n cnt_bits _29
|
||||
ROT // pending_queries msg query_id cnt_bits _29 n
|
||||
STUX // pending_queries msg query_id _30
|
||||
ROT // pending_queries query_id _30 msg
|
||||
STSLICER // pending_queries query_id _31
|
||||
s0 s2 XCHG
|
||||
64 PUSHINT // _31 query_id pending_queries _32=64
|
||||
DICTUSETB // pending_queries
|
||||
}>
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
DUP // in_msg in_msg
|
||||
SEMPTY // in_msg _1
|
||||
IFJMP:<{ // in_msg
|
||||
DROP //
|
||||
try_init INLINECALLDICT
|
||||
}> // in_msg
|
||||
9 PUSHPOW2 // in_msg _5=512
|
||||
LDSLICEX // root_signature in_msg
|
||||
DUP // root_signature in_msg in_msg
|
||||
HASHSU // root_signature in_msg root_hash
|
||||
SWAP // root_signature root_hash in_msg
|
||||
8 LDU // root_signature root_hash root_i in_msg
|
||||
unpack_state INLINECALLDICT // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries
|
||||
s2 PUSH // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries last_cleaned
|
||||
0 EQINT // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries _20
|
||||
s1 s3 XCHG // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned _20
|
||||
SUB // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned
|
||||
s6 s1 PUSH2
|
||||
8 PUSHINT // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned root_i public_keys _24=8
|
||||
DICTUGET
|
||||
NULLSWAPIFNOT // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned public_key found?
|
||||
31 THROWIFNOT
|
||||
256 PLDU // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned _30
|
||||
s8 s9 s0 XCHG3 // last_cleaned public_keys root_i in_msg n k pending_queries root_hash root_signature _30
|
||||
CHKSIGNU // last_cleaned public_keys root_i in_msg n k pending_queries _31
|
||||
32 THROWIFNOT
|
||||
s0 s3 XCHG // last_cleaned public_keys root_i pending_queries n k in_msg
|
||||
LDDICT // last_cleaned public_keys root_i pending_queries n k signatures in_msg
|
||||
DUP // last_cleaned public_keys root_i pending_queries n k signatures in_msg in_msg
|
||||
HASHSU // last_cleaned public_keys root_i pending_queries n k signatures in_msg hash
|
||||
SWAP // last_cleaned public_keys root_i pending_queries n k signatures hash in_msg
|
||||
64 LDU // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg
|
||||
NOW // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg _43
|
||||
32 LSHIFT# // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound
|
||||
s2 s0 PUSH2 // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query_id bound
|
||||
LESS // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound _47
|
||||
33 THROWIF
|
||||
s2 s7 PUSH2
|
||||
64 PUSHINT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query_id pending_queries _51=64
|
||||
DICTUGET
|
||||
NULLSWAPIFNOT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query found?
|
||||
s2 s3 XCHG
|
||||
s8 s(-1) s(-1) PUXC2 // last_cleaned public_keys root_i pending_queries n k signatures hash query_id bound in_msg n query found?
|
||||
unpack_query_data INLINECALLDICT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id bound cnt cnt_bits msg
|
||||
s0 s10 XCHG // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits root_i
|
||||
POW2 // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask
|
||||
2DUP // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask cnt_bits mask
|
||||
AND // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask _61
|
||||
34 THROWIF
|
||||
OR // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits
|
||||
SWAP // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt_bits cnt
|
||||
INC // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt_bits cnt
|
||||
ACCEPT
|
||||
s8 s9 s3 XCPU2
|
||||
s10 s3 s9 PUSH3
|
||||
s11 PUSH // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries msg query_id cnt cnt_bits n k
|
||||
update_pending_queries INLINECALLDICT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries
|
||||
s0 s10 s11 PUSH3
|
||||
s9 s10 PUSH2 // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries pending_queries public_keys last_cleaned k n
|
||||
pack_state INLINECALLDICT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries _68
|
||||
c4 POP
|
||||
COMMIT
|
||||
0 PUSHINT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0
|
||||
s6 PUSH // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 signatures
|
||||
ISNULL // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73
|
||||
s10 s8 PUSH2 // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73 cnt k
|
||||
GEQ // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73 _74
|
||||
OR // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _75
|
||||
IFNOT:<{ // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0
|
||||
DROP // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries
|
||||
s10 PUSH
|
||||
s6 s5 s3 XCHG3
|
||||
s0 s6 XCHG // last_cleaned public_keys msg cnt n k bound pending_queries query_id public_keys signatures hash cnt_bits
|
||||
check_signatures INLINECALLDICT // last_cleaned public_keys msg cnt n k bound pending_queries query_id new_cnt cnt_bits
|
||||
s7 s7 XCHG2 // last_cleaned public_keys msg cnt_bits n k bound pending_queries query_id cnt new_cnt
|
||||
ADD // last_cleaned public_keys msg cnt_bits n k bound pending_queries query_id cnt
|
||||
s2 s4 XCHG
|
||||
s3 s7 XCHG
|
||||
s1 s0 s6 XCHG3
|
||||
s5 s6 PUSH2 // last_cleaned public_keys bound k n pending_queries msg query_id cnt cnt_bits n k
|
||||
update_pending_queries INLINECALLDICT // last_cleaned public_keys bound k n pending_queries
|
||||
-1 PUSHINT // last_cleaned public_keys bound k n pending_queries need_save=-1
|
||||
}>ELSE<{
|
||||
s3 s10 XCHG
|
||||
s7 s9 XCHG
|
||||
s7 s6 XCHG2
|
||||
6 BLKDROP // last_cleaned public_keys bound k n pending_queries need_save
|
||||
}>
|
||||
s0 s4 XCHG
|
||||
38 PUSHPOW2 // last_cleaned public_keys need_save k n pending_queries bound _83
|
||||
SUB // last_cleaned public_keys need_save k n pending_queries bound
|
||||
UNTIL:<{
|
||||
OVER
|
||||
64 PUSHINT // last_cleaned public_keys need_save k n pending_queries bound pending_queries _90=64
|
||||
DICTUREMMIN
|
||||
NULLSWAPIFNOT
|
||||
NULLSWAPIFNOT // last_cleaned public_keys need_save k n pending_queries bound _121 _123 _122 _124
|
||||
s2 POP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' f i
|
||||
s1 s0 XCPU // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f f
|
||||
IF:<{ // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
|
||||
DROP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i
|
||||
s0 s2 PUSH2 // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i i bound
|
||||
LESS // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
|
||||
}> // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
|
||||
DUP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f f
|
||||
IF:<{ // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
|
||||
s4 POP
|
||||
s6 POP
|
||||
s7 POP // pending_queries public_keys last_cleaned k n f bound
|
||||
-1 PUSHINT // pending_queries public_keys last_cleaned k n f bound need_save=-1
|
||||
}>ELSE<{
|
||||
s4 s9 XCHG
|
||||
s4 s7 XCHG
|
||||
s4 s1 s4 XCHG3
|
||||
2DROP // pending_queries public_keys last_cleaned k n f bound need_save
|
||||
}>
|
||||
s0 s2 XCHG // pending_queries public_keys last_cleaned k n need_save bound f
|
||||
NOT // pending_queries public_keys last_cleaned k n need_save bound _96
|
||||
s5 s7 XCHG
|
||||
s2 s5 XCHG // last_cleaned public_keys need_save k n pending_queries bound _96
|
||||
}> // last_cleaned public_keys need_save k n pending_queries bound
|
||||
DROP // last_cleaned public_keys need_save k n pending_queries
|
||||
s0 s3 XCHG // last_cleaned public_keys pending_queries k n need_save
|
||||
IF:<{ // last_cleaned public_keys pending_queries k n
|
||||
s2 s4 XCHG // pending_queries public_keys last_cleaned k n
|
||||
pack_state INLINECALLDICT // _97
|
||||
c4 POP
|
||||
}>ELSE<{
|
||||
5 BLKDROP //
|
||||
}>
|
||||
}>
|
||||
get_query_state PROC:<{
|
||||
// query_id
|
||||
unpack_state INLINECALLDICT // query_id _25 _26 _27 _28 _29
|
||||
NIP
|
||||
s2 POP // query_id n pending_queries last_cleaned
|
||||
64 PUSHINT // query_id n pending_queries last_cleaned _9=64
|
||||
s4 s2 s2 PUXC2 // query_id n last_cleaned query_id pending_queries _9=64
|
||||
DICTUGET
|
||||
NULLSWAPIFNOT // query_id n last_cleaned cs found
|
||||
IFJMP:<{ // query_id n last_cleaned cs
|
||||
NIP
|
||||
s2 POP // cs n
|
||||
SWAP // n cs
|
||||
1 LDI // n _11 cs
|
||||
SWAP // n cs _11
|
||||
IFJMP:<{ // n cs
|
||||
8 LDU // n _35 _34
|
||||
NIP // n cs
|
||||
0 PUSHINT // n cs _17=0
|
||||
s0 s2 XCHG // _17=0 cs n
|
||||
LDUX // _17=0 _37 _36
|
||||
DROP // _17=0 _18
|
||||
}> // n cs
|
||||
2DROP //
|
||||
-1 PUSHINT // _20=-1
|
||||
0 PUSHINT // _20=-1 _21=0
|
||||
}> // query_id n last_cleaned cs
|
||||
DROP
|
||||
NIP // query_id last_cleaned
|
||||
LEQ // _22
|
||||
NEGATE // _23
|
||||
0 PUSHINT // _23 _24=0
|
||||
}>
|
||||
processed? PROC:<{
|
||||
// query_id
|
||||
get_query_state CALLDICT // _4 _5
|
||||
DROP // x
|
||||
}>
|
||||
create_init_state PROC:<{
|
||||
// n k public_keys
|
||||
NEWDICT // n k public_keys _3
|
||||
s2 s3 XCHG2
|
||||
0 PUSHINT
|
||||
-ROT // _3 public_keys _4=0 k n
|
||||
pack_state INLINECALLDICT // _5
|
||||
}>
|
||||
merge_list PROC:<{
|
||||
// a b
|
||||
OVER // a b a
|
||||
ISNULL // a b _2
|
||||
IFJMP:<{ // a b
|
||||
NIP // b
|
||||
}> // a b
|
||||
DUP // a b b
|
||||
ISNULL // a b _3
|
||||
IFJMP:<{ // a b
|
||||
DROP // a
|
||||
}> // a b
|
||||
SWAP // b a
|
||||
CTOS // b as
|
||||
DUP // b as as
|
||||
SREFS // b as _6
|
||||
0 NEQINT // b as _8
|
||||
IFJMP:<{ // b as
|
||||
LDREF // b _10 as
|
||||
s0 s2 XCHG // as _10 b
|
||||
merge_list CALLDICT // as tail
|
||||
NEWC // as tail _13
|
||||
ROT // tail _13 as
|
||||
STSLICER // tail _14
|
||||
STREF // _15
|
||||
ENDC // _16
|
||||
}> // b as
|
||||
1 PUSHINT // b as _18=1
|
||||
SDSKIPLAST // b as
|
||||
NEWC // b as _20
|
||||
SWAP // b _20 as
|
||||
STSLICER // b _21
|
||||
STDICT // _22
|
||||
ENDC // _23
|
||||
}>
|
||||
get_public_keys PROC:<{
|
||||
//
|
||||
unpack_state INLINECALLDICT // _6 _7 _8 _9 _10
|
||||
s1 s4 XCHG
|
||||
4 BLKDROP // public_keys
|
||||
}>
|
||||
check_query_signatures PROC:<{
|
||||
// query
|
||||
CTOS // cs
|
||||
9 PUSHPOW2 // cs _5=512
|
||||
LDSLICEX // root_signature cs
|
||||
DUP // root_signature cs cs
|
||||
HASHSU // root_signature cs root_hash
|
||||
SWAP // root_signature root_hash cs
|
||||
8 LDU // root_signature root_hash root_i cs
|
||||
get_public_keys CALLDICT // root_signature root_hash root_i cs public_keys
|
||||
s2 s0 PUSH2
|
||||
8 PUSHINT // root_signature root_hash root_i cs public_keys root_i public_keys _17=8
|
||||
DICTUGET
|
||||
NULLSWAPIFNOT // root_signature root_hash root_i cs public_keys public_key found?
|
||||
31 THROWIFNOT
|
||||
256 PLDU // root_signature root_hash root_i cs public_keys _23
|
||||
5 1 REVERSE // public_keys cs root_i root_hash root_signature _23
|
||||
CHKSIGNU // public_keys cs root_i _24
|
||||
32 THROWIFNOT
|
||||
POW2 // public_keys cs mask
|
||||
SWAP // public_keys mask cs
|
||||
LDDICT // public_keys mask signatures cs
|
||||
OVER // public_keys mask signatures cs signatures
|
||||
ISNULL // public_keys mask signatures cs _32
|
||||
IFJMP:<{ // public_keys mask signatures cs
|
||||
s2 s3 XCHG
|
||||
3 BLKDROP // mask
|
||||
1 PUSHINT // mask _33=1
|
||||
SWAP // _33=1 mask
|
||||
}> // public_keys mask signatures cs
|
||||
HASHSU // public_keys mask signatures _35
|
||||
ROT // public_keys signatures _35 mask
|
||||
check_signatures INLINECALLDICT // cnt mask
|
||||
SWAP // mask cnt
|
||||
INC // mask _38
|
||||
SWAP // _38 mask
|
||||
}>
|
||||
messages_by_mask PROC:<{
|
||||
// mask
|
||||
unpack_state INLINECALLDICT // mask _29 _30 _31 _32 _33
|
||||
s0 s3 XCHG
|
||||
3 BLKDROP // mask n pending_queries
|
||||
-1 PUSHINT // mask n pending_queries i=-1
|
||||
NEWDICT // mask n pending_queries i=-1 a
|
||||
UNTIL:<{
|
||||
s1 s2 XCPU
|
||||
64 PUSHINT // mask n pending_queries a i pending_queries _13=64
|
||||
DICTUGETNEXT
|
||||
NULLSWAPIFNOT
|
||||
NULLSWAPIFNOT // mask n pending_queries a cs i f
|
||||
DUP // mask n pending_queries a cs i f f
|
||||
IF:<{ // mask n pending_queries a cs i f
|
||||
s0 s2 XCHG // mask n pending_queries a f i cs
|
||||
1 LDI // mask n pending_queries a f i _15 cs
|
||||
SWAP // mask n pending_queries a f i cs _15
|
||||
IF:<{ // mask n pending_queries a f i cs
|
||||
DUP
|
||||
8 PUSHINT // mask n pending_queries a f i cs cs _19=8
|
||||
SDSKIPFIRST // mask n pending_queries a f i cs _20
|
||||
s6 PUSH // mask n pending_queries a f i cs _20 n
|
||||
PLDUX // mask n pending_queries a f i cs cnt_bits
|
||||
s7 PUSH // mask n pending_queries a f i cs cnt_bits mask
|
||||
AND // mask n pending_queries a f i cs _22
|
||||
IF:<{ // mask n pending_queries a f i cs
|
||||
NEWC // mask n pending_queries a f i cs _24
|
||||
SWAP // mask n pending_queries a f i _24 cs
|
||||
STSLICER // mask n pending_queries a f i _25
|
||||
SWAP
|
||||
64 PUSHINT
|
||||
s1 s4 s4 PUXC2 // mask n pending_queries i f _25 i a _26=64
|
||||
DICTUSETB // mask n pending_queries i f a
|
||||
}>ELSE<{
|
||||
s1 s3 XCHG
|
||||
DROP // mask n pending_queries i f a
|
||||
}>
|
||||
}>ELSE<{
|
||||
s1 s3 XCHG
|
||||
DROP // mask n pending_queries i f a
|
||||
}>
|
||||
}>ELSE<{
|
||||
2SWAP
|
||||
DROP // mask n pending_queries i f a
|
||||
}>
|
||||
SWAP // mask n pending_queries i a f
|
||||
NOT // mask n pending_queries i a _28
|
||||
}> // mask n pending_queries i a
|
||||
s0 s4 XCHG
|
||||
4 BLKDROP // a
|
||||
}>
|
||||
get_messages_unsigned_by_id PROC:<{
|
||||
// id
|
||||
POW2 // _2
|
||||
messages_by_mask CALLDICT // _3
|
||||
}>
|
||||
get_messages_unsigned PROC:<{
|
||||
//
|
||||
0 PUSHINT // _0=0
|
||||
NOT // _1
|
||||
messages_by_mask CALLDICT // _2
|
||||
}>
|
||||
get_n_k PROC:<{
|
||||
//
|
||||
unpack_state INLINECALLDICT // _6 _7 _8 _9 _10
|
||||
3 BLKDROP // n k
|
||||
}>
|
||||
merge_inner_queries PROC:<{
|
||||
// a b
|
||||
SWAP // b a
|
||||
CTOS // b ca
|
||||
SWAP // ca b
|
||||
CTOS // ca cb
|
||||
SWAP // cb ca
|
||||
LDDICT // cb list_a ca
|
||||
s0 s2 XCHG // ca list_a cb
|
||||
LDDICT // ca list_a list_b cb
|
||||
s3 PUSH // ca list_a list_b cb ca
|
||||
HASHSU // ca list_a list_b cb _13
|
||||
SWAP // ca list_a list_b _13 cb
|
||||
HASHSU // ca list_a list_b _13 _14
|
||||
EQUAL // ca list_a list_b _15
|
||||
31 THROWIFNOT
|
||||
merge_list CALLDICT // ca _17
|
||||
NEWC // ca _17 _18
|
||||
STDICT // ca _19
|
||||
SWAP // _19 ca
|
||||
STSLICER // _20
|
||||
ENDC // _21
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("restricted-wallet", "te6ccgECDQEAAQgAART/APSkE/Sg8sgLAQIBIAIDAgFIBAUB+vKDCNcYINMf0x/4IxK78mPtRNDTH9P/0VMxuvKhA54xMjL4AKTIyx/L/8ntVOED+QFUEEL5EPKi+ACA8/gzIG6SMH+X0NcLH/gjvOJx+DPQ1wv/BJMg10qOldMH1H8kjoUwUxbbPN6TAvsAkjIw4ugxMwLRpMjLH8v/ye1UDAICzgYHAgEgCgsCASAICQEBSAwAAwwgACUgPP4MyBukjB/l9DXCx/4I7zigABG+ZL9qJoa4WPwAOby2BAefwZkDdJGD/L6GuFj/wR3nFIuEp8EzeIcUADIB0NMDAXiwklt/4PpAMfpAMPpEAcD/Arqw");
|
@ -0,0 +1,144 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/restricted-wallet-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC recv_internal
|
||||
DECLPROC restricted?
|
||||
DECLPROC check_destination
|
||||
DECLPROC recv_external
|
||||
85143 DECLMETHOD seqno
|
||||
104128 DECLMETHOD balance
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
restricted? PROC:<{
|
||||
//
|
||||
-13 PUSHINT // _1=-13
|
||||
CONFIGOPTPARAM // p
|
||||
DUP // p p
|
||||
ISNULL // p _3
|
||||
IF:<{ // p
|
||||
DROP //
|
||||
TRUE // _4
|
||||
}>ELSE<{ // p
|
||||
CTOS // _6
|
||||
32 PLDU // _8
|
||||
NOW // _8 _9
|
||||
GREATER // _4
|
||||
}>
|
||||
}>
|
||||
check_destination PROCREF:<{
|
||||
// msg dest
|
||||
SWAP // dest msg
|
||||
CTOS // dest cs
|
||||
4 LDU // dest flags cs
|
||||
SWAP
|
||||
8 PUSHINT // dest cs flags _8=8
|
||||
AND // dest cs _9
|
||||
IFJMP:<{ // dest cs
|
||||
2DROP //
|
||||
TRUE // _10
|
||||
}> // dest cs
|
||||
LDMSGADDR // dest _27 _26
|
||||
NIP // dest cs
|
||||
LDMSGADDR // dest _29 _28
|
||||
DROP // dest d_addr
|
||||
REWRITESTDADDR // dest dest_wc dest_addr
|
||||
SWAP // dest dest_addr dest_wc
|
||||
-1 EQINT // dest dest_addr _21
|
||||
s0 s2 XCHG // _21 dest_addr dest
|
||||
EQUAL // _21 _22
|
||||
AND // _23
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
9 PUSHPOW2 // in_msg _3=512
|
||||
LDSLICEX // signature in_msg
|
||||
DUP // signature in_msg cs
|
||||
32 LDU // signature in_msg _8 cs
|
||||
32 LDU // signature in_msg msg_seqno valid_until cs
|
||||
NOW // signature in_msg msg_seqno valid_until cs _15
|
||||
s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15
|
||||
LEQ // signature in_msg msg_seqno cs _16
|
||||
35 THROWIF
|
||||
c4 PUSH // signature in_msg msg_seqno cs _19
|
||||
CTOS // signature in_msg msg_seqno cs ds
|
||||
32 LDU // signature in_msg msg_seqno cs _23 ds
|
||||
256 LDU // signature in_msg msg_seqno cs stored_seqno public_key ds
|
||||
ENDS
|
||||
s3 s1 PUSH2 // signature in_msg msg_seqno cs stored_seqno public_key msg_seqno stored_seqno
|
||||
EQUAL // signature in_msg msg_seqno cs stored_seqno public_key _31
|
||||
33 THROWIFNOT
|
||||
s0 s3 XCHG // signature in_msg public_key cs stored_seqno msg_seqno
|
||||
IFNOTJMP:<{ // signature in_msg public_key cs stored_seqno
|
||||
NIP
|
||||
s2 POP
|
||||
s2 POP // public_key stored_seqno
|
||||
ACCEPT
|
||||
INC // public_key _35
|
||||
NEWC // public_key _35 _36
|
||||
32 STU // public_key _38
|
||||
256 STU // _40
|
||||
ENDC // _41
|
||||
c4 POP
|
||||
}> // signature in_msg public_key cs stored_seqno
|
||||
s0 s3 XCHG // signature stored_seqno public_key cs in_msg
|
||||
HASHSU // signature stored_seqno public_key cs _44
|
||||
s0 s4 s2 XC2PU // cs stored_seqno public_key _44 signature public_key
|
||||
CHKSIGNU // cs stored_seqno public_key _45
|
||||
34 THROWIFNOT
|
||||
ACCEPT
|
||||
restricted? INLINECALLDICT // cs stored_seqno public_key restrict
|
||||
1 PUSHINT // cs stored_seqno public_key restrict _51=1
|
||||
CONFIGOPTPARAM // cs stored_seqno public_key restrict _52
|
||||
CTOS // cs stored_seqno public_key restrict _53
|
||||
256 PLDU // cs stored_seqno public_key restrict elector
|
||||
s0 s4 XCHG // elector stored_seqno public_key restrict cs
|
||||
WHILE:<{
|
||||
DUP // elector stored_seqno public_key restrict cs cs
|
||||
SREFS // elector stored_seqno public_key restrict cs _58
|
||||
}>DO<{ // elector stored_seqno public_key restrict cs
|
||||
8 LDU // elector stored_seqno public_key restrict mode cs
|
||||
LDREF // elector stored_seqno public_key restrict mode msg cs
|
||||
TRUE // elector stored_seqno public_key restrict mode msg cs ok
|
||||
s4 PUSH // elector stored_seqno public_key restrict mode msg cs ok restrict
|
||||
IF:<{ // elector stored_seqno public_key restrict mode msg cs ok
|
||||
DROP // elector stored_seqno public_key restrict mode msg cs
|
||||
s1 s6 PUSH2 // elector stored_seqno public_key restrict mode msg cs msg elector
|
||||
check_destination INLINECALLDICT // elector stored_seqno public_key restrict mode msg cs ok
|
||||
}> // elector stored_seqno public_key restrict mode msg cs ok
|
||||
IF:<{ // elector stored_seqno public_key restrict mode msg cs
|
||||
s0 s2 XCHG // elector stored_seqno public_key restrict cs msg mode
|
||||
SENDRAWMSG
|
||||
}>ELSE<{
|
||||
s2 POP
|
||||
DROP // elector stored_seqno public_key restrict cs
|
||||
}>
|
||||
}> // elector stored_seqno public_key restrict cs
|
||||
NIP
|
||||
s3 POP // cs stored_seqno public_key
|
||||
s0 s2 XCHG // public_key stored_seqno cs
|
||||
ENDS
|
||||
INC // public_key _72
|
||||
NEWC // public_key _72 _73
|
||||
32 STU // public_key _75
|
||||
256 STU // _77
|
||||
ENDC // _78
|
||||
c4 POP
|
||||
}>
|
||||
seqno PROC:<{
|
||||
//
|
||||
c4 PUSH // _0
|
||||
CTOS // _1
|
||||
32 PLDU // _3
|
||||
}>
|
||||
balance PROC:<{
|
||||
//
|
||||
restricted? INLINECALLDICT // _0
|
||||
IF:<{ //
|
||||
0 PUSHINT // _1=0
|
||||
}>ELSE<{ //
|
||||
BALANCE // _3
|
||||
FIRST // _1
|
||||
}>
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("restricted-wallet2", "te6ccgECDAEAAR0AART/APSkE/Sg8sgLAQIBIAIDAgFIBAUBAvIKAgLPBgcCASAICQADDCAAMyA8/gzIG6SMH+e+CMB0NcLH6GCAVGAqQTigABG+ZL9qJoa4WPwAf7y2B2omhAgJBrkPoCaMB5/BmQN0kYP898EYDoa4WP0MEAqMBUgnF8EzeIAUAIej230LfQmMv9ABhQuFsEyJhxQB/oMI1xgg0x/TH/gjErvyY+1E0NMf0//0BNFTQrryoQSOEjIzM/gAAaTIyx8Sy//0AMntVOEE+QFUEFT5EPKi+ACA8/gzIG6SMH+e+CMB0NcLH6GCAVGAqQTiIoAQ9HtvoW+hMZb6ADBy+wKRMOKTINdKltMH1AL7AOjRAqTIyx8LAA7L//QAye1U");
|
@ -0,0 +1,140 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/restricted-wallet2-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC recv_internal
|
||||
DECLPROC days_passed
|
||||
DECLPROC recv_external
|
||||
85143 DECLMETHOD seqno
|
||||
104128 DECLMETHOD balance
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
days_passed PROC:<{
|
||||
//
|
||||
-13 PUSHINT // _1=-13
|
||||
CONFIGOPTPARAM // p
|
||||
DUP // p p
|
||||
ISNULL // p _3
|
||||
IF:<{ // p
|
||||
DROP //
|
||||
-1 PUSHINT // _4=-1
|
||||
}>ELSE<{ // p
|
||||
NOW // p _6
|
||||
SWAP // _6 p
|
||||
CTOS // _6 _7
|
||||
32 PLDU // _6 _9
|
||||
SUB // _10
|
||||
86400 PUSHINT // _10 _11=86400
|
||||
DIV // _4
|
||||
}>
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
9 PUSHPOW2 // in_msg _3=512
|
||||
LDSLICEX // signature in_msg
|
||||
DUP // signature in_msg cs
|
||||
32 LDU // signature in_msg _8 cs
|
||||
32 LDU // signature in_msg msg_seqno valid_until cs
|
||||
NOW // signature in_msg msg_seqno valid_until cs _15
|
||||
s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15
|
||||
LEQ // signature in_msg msg_seqno cs _16
|
||||
35 THROWIF
|
||||
c4 PUSH // signature in_msg msg_seqno cs _19
|
||||
CTOS // signature in_msg msg_seqno cs ds
|
||||
32 LDU // signature in_msg msg_seqno cs _24 ds
|
||||
256 LDU // signature in_msg msg_seqno cs _24 _27 ds
|
||||
LDDICT // signature in_msg msg_seqno cs stored_seqno public_key rdict ds
|
||||
ENDS
|
||||
s4 s2 PUSH2 // signature in_msg msg_seqno cs stored_seqno public_key rdict msg_seqno stored_seqno
|
||||
EQUAL // signature in_msg msg_seqno cs stored_seqno public_key rdict _34
|
||||
33 THROWIFNOT
|
||||
s0 s4 XCHG // signature in_msg rdict cs stored_seqno public_key msg_seqno
|
||||
IFNOTJMP:<{ // signature in_msg rdict cs stored_seqno public_key
|
||||
s2 POP
|
||||
s3 POP
|
||||
s3 POP // public_key stored_seqno rdict
|
||||
ACCEPT
|
||||
SWAP // public_key rdict stored_seqno
|
||||
INC // public_key rdict _38
|
||||
NEWC // public_key rdict _38 _39
|
||||
32 STU // public_key rdict _41
|
||||
s1 s2 XCHG // rdict public_key _41
|
||||
256 STU // rdict _43
|
||||
STDICT // _44
|
||||
ENDC // _45
|
||||
c4 POP
|
||||
}> // signature in_msg rdict cs stored_seqno public_key
|
||||
s0 s4 XCHG // signature public_key rdict cs stored_seqno in_msg
|
||||
HASHSU // signature public_key rdict cs stored_seqno _48
|
||||
s0 s5 s4 XC2PU // stored_seqno public_key rdict cs _48 signature public_key
|
||||
CHKSIGNU // stored_seqno public_key rdict cs _49
|
||||
34 THROWIFNOT
|
||||
ACCEPT
|
||||
days_passed INLINECALLDICT // stored_seqno public_key rdict cs ts
|
||||
s2 PUSH
|
||||
16 PUSHINT // stored_seqno public_key rdict cs ts rdict _57=16
|
||||
DICTIGETPREVEQ
|
||||
NULLSWAPIFNOT
|
||||
NULLSWAPIFNOT // stored_seqno public_key rdict cs _98 _97 _99
|
||||
NIP // stored_seqno public_key rdict cs value found
|
||||
IF:<{ // stored_seqno public_key rdict cs value
|
||||
LDGRAMS // stored_seqno public_key rdict cs _101 _100
|
||||
DROP // stored_seqno public_key rdict cs _59
|
||||
2 PUSHINT // stored_seqno public_key rdict cs _59 _61=2
|
||||
RAWRESERVE
|
||||
}>ELSE<{
|
||||
DROP // stored_seqno public_key rdict cs
|
||||
}> // stored_seqno public_key rdict cs
|
||||
WHILE:<{
|
||||
DUP // stored_seqno public_key rdict cs cs
|
||||
SREFS // stored_seqno public_key rdict cs _65
|
||||
}>DO<{ // stored_seqno public_key rdict cs
|
||||
8 LDU // stored_seqno public_key rdict mode cs
|
||||
LDREF // stored_seqno public_key rdict mode msg cs
|
||||
s0 s2 XCHG // stored_seqno public_key rdict cs msg mode
|
||||
SENDRAWMSG
|
||||
}> // stored_seqno public_key rdict cs
|
||||
ENDS
|
||||
s0 s2 XCHG // rdict public_key stored_seqno
|
||||
INC // rdict public_key _76
|
||||
NEWC // rdict public_key _76 _77
|
||||
32 STU // rdict public_key _79
|
||||
256 STU // rdict _81
|
||||
STDICT // _82
|
||||
ENDC // _83
|
||||
c4 POP
|
||||
}>
|
||||
seqno PROC:<{
|
||||
//
|
||||
c4 PUSH // _0
|
||||
CTOS // _1
|
||||
32 PLDU // _3
|
||||
}>
|
||||
balance PROC:<{
|
||||
//
|
||||
c4 PUSH // _1
|
||||
CTOS // _2
|
||||
288 PUSHINT // _2 _5
|
||||
SDSKIPFIRST // ds
|
||||
LDDICT // rdict ds
|
||||
ENDS
|
||||
days_passed INLINECALLDICT // rdict ts
|
||||
BALANCE // rdict ts _14
|
||||
FIRST // rdict ts balance
|
||||
s0 s2 XCHG
|
||||
16 PUSHINT // balance ts rdict _19=16
|
||||
DICTIGETPREVEQ
|
||||
NULLSWAPIFNOT
|
||||
NULLSWAPIFNOT // balance _29 _28 _30
|
||||
NIP // balance value found
|
||||
IF:<{ // balance value
|
||||
LDGRAMS // balance _32 _31
|
||||
DROP // balance _21
|
||||
SUB // _23
|
||||
0 PUSHINT // _23 _24=0
|
||||
MAX // balance
|
||||
}>ELSE<{
|
||||
DROP // balance
|
||||
}>
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9KDyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U");
|
@ -0,0 +1,45 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/simple-wallet-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC recv_internal
|
||||
DECLPROC recv_external
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
9 PUSHPOW2 // in_msg _3=512
|
||||
LDSLICEX // signature in_msg
|
||||
DUP // signature in_msg cs
|
||||
32 LDU // signature in_msg msg_seqno cs
|
||||
c4 PUSH // signature in_msg msg_seqno cs _11
|
||||
CTOS // signature in_msg msg_seqno cs cs2
|
||||
32 LDU // signature in_msg msg_seqno cs stored_seqno cs2
|
||||
256 LDU // signature in_msg msg_seqno cs stored_seqno public_key cs2
|
||||
ENDS
|
||||
s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno
|
||||
EQUAL // signature in_msg public_key cs stored_seqno _23
|
||||
33 THROWIFNOT
|
||||
s0 s3 XCHG // signature stored_seqno public_key cs in_msg
|
||||
HASHSU // signature stored_seqno public_key cs _26
|
||||
s0 s4 s2 XC2PU // cs stored_seqno public_key _26 signature public_key
|
||||
CHKSIGNU // cs stored_seqno public_key _27
|
||||
34 THROWIFNOT
|
||||
ACCEPT
|
||||
s2 s0 XCPU // public_key stored_seqno cs cs
|
||||
SREFS // public_key stored_seqno cs _32
|
||||
IF:<{ // public_key stored_seqno cs
|
||||
8 LDU // public_key stored_seqno mode cs
|
||||
LDREF // public_key stored_seqno mode _37 cs
|
||||
s0 s2 XCHG // public_key stored_seqno cs _37 mode
|
||||
SENDRAWMSG
|
||||
}> // public_key stored_seqno cs
|
||||
ENDS
|
||||
INC // public_key _42
|
||||
NEWC // public_key _42 _43
|
||||
32 STU // public_key _45
|
||||
256 STU // _47
|
||||
ENDC // _48
|
||||
c4 POP
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("simple-wallet-ext", "te6ccgEBFgEAzwABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQA08vACVDIS8AT4ACDXSpbTB9QC+wDe0aQB8AMCAs0GBwIBIA4PAgEgCAkAKdAUGEa4wQaY+CXXlQ/ICgCfyIeVFAIBIAoLAgEgDA0AAwwgAA8yBLLH8v/yYAARO1E0NMf0/8wgAAk8AHtVIAIBIBARAgEgFBUADbvtlwAfABgCASASEwARtZL9qJoa4WPwAA22l54AXgCQACG40BggFMl+1D2IIByODtQ9iAAVuI4MjLHxLLB8zJg=");
|
@ -0,0 +1,104 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/simple-wallet-ext-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC create_state
|
||||
DECLPROC load_state
|
||||
DECLPROC save_state
|
||||
DECLPROC recv_internal
|
||||
DECLPROC do_verify_message
|
||||
DECLPROC recv_external
|
||||
85143 DECLMETHOD seqno
|
||||
81625 DECLMETHOD create_init_state
|
||||
116960 DECLMETHOD prepare_send_message_with_seqno
|
||||
101633 DECLMETHOD prepare_send_message
|
||||
95420 DECLMETHOD verify_message
|
||||
create_state PROC:<{
|
||||
// seqno public_key
|
||||
NEWC // seqno public_key _2
|
||||
s1 s2 XCHG // public_key seqno _2
|
||||
32 STU // public_key _4
|
||||
256 STU // _6
|
||||
ENDC // _7
|
||||
}>
|
||||
load_state PROC:<{
|
||||
//
|
||||
c4 PUSH // _1
|
||||
CTOS // cs2
|
||||
32 LDU // _3 cs2
|
||||
256 LDU // _3 _12 _11
|
||||
DROP // _3 _6
|
||||
}>
|
||||
save_state PROC:<{
|
||||
// seqno public_key
|
||||
create_state CALLDICT // _2
|
||||
c4 POP
|
||||
}>
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
do_verify_message PROC:<{
|
||||
// in_msg seqno public_key
|
||||
s0 s2 XCHG
|
||||
9 PUSHPOW2 // public_key seqno in_msg _5=512
|
||||
LDSLICEX // public_key seqno signature in_msg
|
||||
DUP // public_key seqno signature in_msg cs
|
||||
32 LDU // public_key seqno signature in_msg msg_seqno cs
|
||||
s0 s4 XCHG // public_key cs signature in_msg msg_seqno seqno
|
||||
EQUAL // public_key cs signature in_msg _13
|
||||
33 THROWIFNOT
|
||||
HASHSU // public_key cs signature _16
|
||||
s0 s1 s3 XCHG3 // cs _16 signature public_key
|
||||
CHKSIGNU // cs _17
|
||||
34 THROWIFNOT
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
load_state CALLDICT // in_msg stored_seqno public_key
|
||||
s2 s1 s2 XCPU2 // public_key stored_seqno in_msg stored_seqno public_key
|
||||
do_verify_message CALLDICT // public_key stored_seqno cs
|
||||
ACCEPT // public_key stored_seqno cs
|
||||
DUP // public_key stored_seqno cs cs
|
||||
SREFS // public_key stored_seqno cs _9
|
||||
IF:<{ // public_key stored_seqno cs
|
||||
8 LDU // public_key stored_seqno mode cs
|
||||
LDREF // public_key stored_seqno mode _14 cs
|
||||
s0 s2 XCHG // public_key stored_seqno cs _14 mode
|
||||
SENDRAWMSG
|
||||
}> // public_key stored_seqno cs
|
||||
ENDS
|
||||
INC // public_key _19
|
||||
SWAP // _19 public_key
|
||||
save_state CALLDICT
|
||||
}>
|
||||
seqno PROC:<{
|
||||
//
|
||||
c4 PUSH // _0
|
||||
CTOS // _1
|
||||
32 PLDU // _3
|
||||
}>
|
||||
create_init_state PROC:<{
|
||||
// public_key
|
||||
0 PUSHINT // public_key _1=0
|
||||
SWAP // _1=0 public_key
|
||||
create_state CALLDICT // _2
|
||||
}>
|
||||
prepare_send_message_with_seqno PROC:<{
|
||||
// mode msg seqno
|
||||
NEWC // mode msg seqno _3
|
||||
32 STU // mode msg _5
|
||||
s1 s2 XCHG // msg mode _5
|
||||
8 STU // msg _7
|
||||
STREF // _8
|
||||
ENDC // _9
|
||||
}>
|
||||
prepare_send_message PROC:<{
|
||||
// mode msg
|
||||
seqno CALLDICT // mode msg _2
|
||||
prepare_send_message_with_seqno CALLDICT // _3
|
||||
}>
|
||||
verify_message PROC:<{
|
||||
// msg
|
||||
load_state CALLDICT // msg stored_seqno public_key
|
||||
do_verify_message CALLDICT // _4
|
||||
}>
|
||||
}END>c
|
@ -0,0 +1 @@
|
||||
with_tvm_code("wallet", "te6ccgEBBgEAaAABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQCA8oMI1xgg0x/TH/gjErvyY+1E0NMf0//RUTG68qED+QFUEEL5EPKi+AACkyDXSpbTB9QC+wDo0aTIyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==");
|
@ -0,0 +1,59 @@
|
||||
// automatically generated from `smartcont/stdlib.fc` `smartcont/wallet-code.fc`
|
||||
PROGRAM{
|
||||
DECLPROC recv_internal
|
||||
DECLPROC recv_external
|
||||
85143 DECLMETHOD seqno
|
||||
recv_internal PROC:<{
|
||||
// in_msg
|
||||
DROP //
|
||||
}>
|
||||
recv_external PROC:<{
|
||||
// in_msg
|
||||
9 PUSHPOW2 // in_msg _3=512
|
||||
LDSLICEX // signature in_msg
|
||||
DUP // signature in_msg cs
|
||||
32 LDU // signature in_msg _8 cs
|
||||
32 LDU // signature in_msg msg_seqno valid_until cs
|
||||
NOW // signature in_msg msg_seqno valid_until cs _15
|
||||
s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15
|
||||
LEQ // signature in_msg msg_seqno cs _16
|
||||
35 THROWIF
|
||||
c4 PUSH // signature in_msg msg_seqno cs _19
|
||||
CTOS // signature in_msg msg_seqno cs ds
|
||||
32 LDU // signature in_msg msg_seqno cs _23 ds
|
||||
256 LDU // signature in_msg msg_seqno cs stored_seqno public_key ds
|
||||
ENDS
|
||||
s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno
|
||||
EQUAL // signature in_msg public_key cs stored_seqno _31
|
||||
33 THROWIFNOT
|
||||
s0 s3 XCHG // signature stored_seqno public_key cs in_msg
|
||||
HASHSU // signature stored_seqno public_key cs _34
|
||||
s0 s4 s2 XC2PU // cs stored_seqno public_key _34 signature public_key
|
||||
CHKSIGNU // cs stored_seqno public_key _35
|
||||
34 THROWIFNOT
|
||||
ACCEPT
|
||||
s0 s2 XCHG // public_key stored_seqno cs
|
||||
WHILE:<{
|
||||
DUP // public_key stored_seqno cs cs
|
||||
SREFS // public_key stored_seqno cs _40
|
||||
}>DO<{ // public_key stored_seqno cs
|
||||
8 LDU // public_key stored_seqno mode cs
|
||||
LDREF // public_key stored_seqno mode _45 cs
|
||||
s0 s2 XCHG // public_key stored_seqno cs _45 mode
|
||||
SENDRAWMSG
|
||||
}> // public_key stored_seqno cs
|
||||
ENDS
|
||||
INC // public_key _50
|
||||
NEWC // public_key _50 _51
|
||||
32 STU // public_key _53
|
||||
256 STU // _55
|
||||
ENDC // _56
|
||||
c4 POP
|
||||
}>
|
||||
seqno PROC:<{
|
||||
//
|
||||
c4 PUSH // _0
|
||||
CTOS // _1
|
||||
32 PLDU // _3
|
||||
}>
|
||||
}END>c
|
@ -86,6 +86,39 @@
|
||||
.end_cell(), 0);
|
||||
}
|
||||
|
||||
() after_code_upgrade(slice param, cell old_code) impure method_id(1666) {
|
||||
}
|
||||
|
||||
_ perform_action(cfg_dict, public_key, action, cs) {
|
||||
if (action == 0x43665021) {
|
||||
;; change one configuration parameter
|
||||
var param_index = cs~load_uint(32);
|
||||
var param_value = cs~load_ref();
|
||||
cs.end_parse();
|
||||
cfg_dict~idict_set_ref(32, param_index, param_value);
|
||||
} elseif (action == 0x4e436f64) {
|
||||
;; change configuration smart contract code
|
||||
var new_code = cs~load_ref();
|
||||
set_code(new_code);
|
||||
ifnot(cs.slice_empty?()) {
|
||||
var old_code = get_c3();
|
||||
set_c3(new_code);
|
||||
after_code_upgrade(cs, old_code);
|
||||
set_c3(old_code);
|
||||
}
|
||||
} elseif (action == 0x50624b21) {
|
||||
;; change configuration master public key
|
||||
public_key = cs~load_uint(256);
|
||||
cs.end_parse();
|
||||
} elseif (action == 0x4e43ef05) {
|
||||
;; change election smart contract code
|
||||
change_elector_code(cs);
|
||||
} else {
|
||||
throw_if(32, action);
|
||||
}
|
||||
return (cfg_dict, public_key);
|
||||
}
|
||||
|
||||
() recv_external(slice in_msg) impure {
|
||||
var signature = in_msg~load_bits(512);
|
||||
var cs = in_msg;
|
||||
@ -101,27 +134,7 @@
|
||||
throw_unless(33, msg_seqno == stored_seqno);
|
||||
throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key));
|
||||
accept_message();
|
||||
if (action == 0x43665021) {
|
||||
;; change one configuration parameter
|
||||
var param_index = cs~load_uint(32);
|
||||
var param_value = cs~load_ref();
|
||||
cs.end_parse();
|
||||
cfg_dict~idict_set_ref(32, param_index, param_value);
|
||||
} elseif (action == 0x4e436f64) {
|
||||
;; change configuration smart contract code
|
||||
var new_code = cs~load_ref();
|
||||
cs.end_parse();
|
||||
set_code(new_code);
|
||||
} elseif (action == 0x50624b21) {
|
||||
;; change configuration master public key
|
||||
public_key = cs~load_uint(256);
|
||||
cs.end_parse();
|
||||
} elseif (action == 0x4e43ef05) {
|
||||
;; change election smart contract code
|
||||
change_elector_code(cs);
|
||||
} else {
|
||||
throw_if(32, action);
|
||||
}
|
||||
(cfg_dict, public_key) = perform_action(cfg_dict, public_key, action, cs);
|
||||
set_data(begin_cell().store_ref(cfg_dict).store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell());
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user