Update comment decryption UI

This commit is contained in:
Ali 2020-03-25 17:59:03 +04:00
parent 44b57ffcce
commit 5d55b67c3a
171 changed files with 5267 additions and 1448 deletions

View File

@ -384,7 +384,7 @@ project: check_env kill_xcode
bazel_app_debug_arm64:
APP_VERSION="${APP_VERSION}" \
build-system/prepare-build.sh distribution
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_DEBUG_FLAGS} \
-c dbg \
--ios_multi_cpus=arm64 \
@ -394,7 +394,7 @@ bazel_app_debug_arm64:
bazel_app_arm64:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
build-system/prepare-build.sh distribution
build-system/prepare-build.sh Telegram distribution
"${BAZEL}" build Telegram/Telegram ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=arm64 \
@ -408,7 +408,7 @@ bazel_app_arm64:
bazel_prepare_development_build:
APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
build-system/prepare-build.sh development
build-system/prepare-build.sh Telegram development
bazel_project: kill_xcode bazel_prepare_development_build
APP_VERSION="${APP_VERSION}" \

View File

@ -9,15 +9,11 @@ load("@build_bazel_rules_apple//apple:watchos.bzl",
"watchos_extension",
)
load("@build_bazel_rules_apple//apple:versioning.bzl",
"apple_bundle_version",
)
load("@build_bazel_rules_swift//swift:swift.bzl",
"swift_library",
)
load("//build-system:plist_fragment.bzl",
load("//build-system/bazel-utils:plist_fragment.bzl",
"plist_fragment",
)
@ -179,42 +175,42 @@ plist_fragment(
template =
"""
<key>CFBundleShortVersionString</key>
<string>{telegram_version}</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}</string>
<key>CFBundleURLSchemes</key>
<array>
<string>telegram</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}.ton</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ton</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}.compatibility</string>
<key>CFBundleURLSchemes</key>
<array>
<string>tg</string>
</array>
</dict>
</array>
<string>{telegram_version}</string>
<key>CFBundleVersion</key>
<string>{telegram_build_number}</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}</string>
<key>CFBundleURLSchemes</key>
<array>
<string>telegram</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}.ton</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ton</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>{telegram_bundle_id}.compatibility</string>
<key>CFBundleURLSchemes</key>
<array>
<string>tg</string>
</array>
</dict>
</array>
""".format(
telegram_version = telegram_version,
telegram_build_number = telegram_build_number,

View File

@ -1,5 +1,9 @@
include Utils.makefile
APP_VERSION="1.0"
CORE_COUNT=$(shell sysctl -n hw.logicalcpu)
CORE_COUNT_MINUS_ONE=$(shell expr ${CORE_COUNT} \- 1)
WALLET_BUCK_OPTIONS=\
--config custom.appVersion="1.0" \
--config custom.developmentCodeSignIdentity="${DEVELOPMENT_CODE_SIGN_IDENTITY}" \
@ -21,6 +25,23 @@ WALLET_BUCK_OPTIONS=\
BAZEL=$(shell which bazel)
ifneq ($(BAZEL_CACHE_DIR),)
export BAZEL_CACHE_FLAGS=\
--disk_cache="${BAZEL_CACHE_DIR}"
endif
BAZEL_COMMON_FLAGS=\
--announce_rc \
--features=swift.use_global_module_cache \
BAZEL_DEBUG_FLAGS=\
--features=swift.enable_batch_mode \
--swiftcopt=-j${CORE_COUNT_MINUS_ONE} \
BAZEL_OPT_FLAGS=\
--swiftcopt=-whole-module-optimization \
--swiftcopt='-num-threads' --swiftcopt='16' \
wallet_deps: check_env
$(BUCK) query "deps(//Wallet:AppPackage)" --output-attribute buck.type \
${WALLET_BUCK_OPTIONS} ${BUCK_RELEASE_OPTIONS}
@ -51,5 +72,30 @@ wallet_package:
wallet_app: build_wallet wallet_package
tulsi_project:
${HOME}/Applications/Tulsi.app/Contents/MacOS/Tulsi -- --genconfig Wallet/Wallet.tulsiproj:Default --bazel "${BAZEL}"
bazel_wallet_debug_arm64:
WALLET_APP_VERSION="${APP_VERSION}" \
build-system/prepare-build.sh Wallet distribution
"${BAZEL}" build Wallet/Wallet ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_DEBUG_FLAGS} \
-c dbg \
--ios_multi_cpus=arm64 \
--watchos_cpus=armv7k,arm64_32 \
--verbose_failures
bazel_wallet:
WALLET_APP_VERSION="${APP_VERSION}" \
build-system/prepare-build.sh Wallet distribution
"${BAZEL}" build Wallet/Wallet ${BAZEL_CACHE_FLAGS} ${BAZEL_COMMON_FLAGS} ${BAZEL_OPT_FLAGS} \
-c opt \
--ios_multi_cpus=armv7,arm64 \
--watchos_cpus=armv7k,arm64_32 \
--verbose_failures
bazel_wallet_prepare_development_build:
WALLET_APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
build-system/prepare-build.sh Wallet development
bazel_wallet_project: kill_xcode bazel_wallet_prepare_development_build
WALLET_APP_VERSION="${APP_VERSION}" \
BAZEL_CACHE_DIR="${BAZEL_CACHE_DIR}" \
build-system/generate-xcode-project.sh Wallet

View File

@ -1,25 +1,132 @@
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application", "ios_framework")
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
load("@build_bazel_rules_apple//apple:ios.bzl",
"ios_application",
"ios_extension",
"ios_framework",
)
version_info_plist_source = """
echo \
'<?xml version="1.0" encoding="UTF-8"?>' \
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' \
'<plist version="1.0">' \
'<dict>' \
' <key>CFBundleShortVersionString</key>' \
' <string>{}</string>' \
' <key>CFBundleVersion</key>' \
' <string>{}</string>' \
'</dict>' \
'</plist>' \
> "$@"
""".format("1.0", "30")
load("@build_bazel_rules_swift//swift:swift.bzl",
"swift_library",
)
load("//build-system/bazel-utils:plist_fragment.bzl",
"plist_fragment",
)
load(
"//build-input/data:variables.bzl",
"wallet_build_number",
"wallet_version",
"wallet_bundle_id",
"wallet_team_id",
)
config_setting(
name = "debug",
values = {
"compilation_mode": "dbg",
},
)
genrule(
name = "VersionInfoPlist",
outs = ["VersionInfo.plist"],
cmd = version_info_plist_source,
name = "empty",
outs = ["empty.swift"],
cmd = "touch $(OUTS)",
)
swift_library(
name = "_LocalDebugOptions",
srcs = [":empty"],
copts = [
"-Xfrontend",
"-serialize-debugging-options",
],
deps = [
],
module_name = "_LocalDebugOptions",
tags = ["no-remote"],
visibility = ["//visibility:public"],
)
debug_deps = select({
":debug": [":_LocalDebugOptions"],
"//conditions:default": [],
})
plist_fragment(
name = "WalletInfoPlist",
extension = "plist",
template =
"""
<key>CFBundleShortVersionString</key>
<string>{wallet_version}</string>
<key>CFBundleVersion</key>
<string>{wallet_build_number}</string>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>TON Wallet</string>
<key>CFBundleIdentifier</key>
<string>{wallet_bundle_id}</string>
<key>CFBundleName</key>
<string>TON Wallet</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string>Please allow TON Wallet access to your camera for scanning QR codes.</string>
<key>NSFaceIDUsageDescription</key>
<string>For better security, please allow TON Wallet to use your Face ID to authenticate payments.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Please allow TON Wallet access to your Photo Stream in case you need to scan a QR code from a picture.</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIFileSharingEnabled</key>
<false/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIRequiresPersistentWiFi</key>
<true/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIViewEdgeAntialiasing</key>
<false/>
<key>UIViewGroupOpacity</key>
<false/>
""".format(
wallet_version = wallet_version,
wallet_build_number = wallet_build_number,
wallet_bundle_id = wallet_bundle_id,
)
)
filegroup(
@ -29,6 +136,13 @@ filegroup(
], exclude = ["Strings/**/.*"]),
)
filegroup(
name = "Icons",
srcs = glob([
"Icons.xcassets/**/*",
], exclude = ["Icons.xcassets/**/.*"]),
)
objc_library(
name = "Main",
srcs = [
@ -36,73 +150,37 @@ objc_library(
],
)
ios_framework(
name = "AsyncDisplayKitFramework",
deps = ["//submodules/AsyncDisplayKit:AsyncDisplayKit"],
bundle_id = "org.telegram.Telegram.AsyncDisplayKit",
families = ["iphone", "ipad"],
minimum_os_version = "9.0",
infoplists = [
"Info.plist"
],
)
swift_library(
name = "Lib",
srcs = glob([
"Sources/**/*.swift",
]),
data = [
":Strings",
],
deps = [
"//submodules/GZip:GZip",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/SSignalKit/SSignalKit:SSignalKit",
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/ObjCRuntimeUtils:ObjCRuntimeUtils",
"//submodules/UIKitRuntimeUtils:UIKitRuntimeUtils",
"//submodules/Display:Display",
"//submodules/AlertUI:AlertUI",
"//submodules/ActivityIndicator:ActivityIndicator",
"//submodules/OverlayStatusController:OverlayStatusController",
"//submodules/openssl:openssl",
"//submodules/OpenSSLEncryptionProvider:OpenSSLEncryptionProvider",
"//submodules/WalletUI:WalletUI",
"//submodules/WalletCore:WalletCore",
"//submodules/BuildConfig:BuildConfig",
"//submodules/AppBundle:AppBundle",
"//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode",
"//submodules/Camera:Camera",
"//submodules/QrCode:QrCode",
"//submodules/MergeLists:MergeLists",
"//submodules/GlassButtonNode:GlassButtonNode",
"//submodules/UrlEscaping:UrlEscaping",
"//submodules/LocalAuth:LocalAuth",
"//submodules/ScreenCaptureDetection:ScreenCaptureDetection",
"//submodules/WalletUrl:WalletUrl",
"//submodules/ProgressNavigationButtonNode:ProgressNavigationButtonNode",
"//submodules/Markdown:Markdown",
"//submodules/StringPluralization:StringPluralization",
"//submodules/YuvConversion:YuvConversion",
"//submodules/rlottie:RLottieBinding",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/WalletUI:WalletUI",
"//submodules/FFMpegBinding:FFMpegBinding",
"//submodules/OverlayStatusController:OverlayStatusController",
],
)
ios_application(
name = "Wallet",
bundle_id = "{wallet_bundle_id}",
bundle_id = wallet_bundle_id,
families = ["iphone", "ipad"],
minimum_os_version = "9.0",
provisioning_profile = "Wallet.mobileprovision",
provisioning_profile = "//build-input/data/provisioning-profiles:Wallet.mobileprovision",
infoplists = [
":Info.plist",
":VersionInfoPlist",
":WalletInfoPlist.plist",
],
frameworks = [
":AsyncDisplayKitFramework",
app_icons = [
":Icons",
],
launch_storyboard = "LaunchScreen.xib",
strings = [
":Strings",
],
deps = [
":Main",

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
</dict>
</plist>

Binary file not shown.

View File

@ -1,4 +1,4 @@
load("//build-system:defines.bzl",
load("//build-system/bazel-utils:defines.bzl",
"string_value",
)

View File

@ -0,0 +1,104 @@
#!/bin/sh
copy_provisioning_profiles () {
if [ "$CODESIGNING_DATA_PATH" = "" ]; then
>&2 echo "CODESIGNING_DATA_PATH not defined"
exit 1
fi
PROFILES_TYPE="$1"
case "$PROFILES_TYPE" in
development)
EXPECTED_VARIABLES=(\
WALLET_DEVELOPMENT_PROVISIONING_PROFILE_APP \
)
;;
distribution)
EXPECTED_VARIABLES=(\
WALLET_DISTRIBUTION_PROVISIONING_PROFILE_APP \
)
;;
*)
echo "Unknown build provisioning type: $PROFILES_TYPE"
exit 1
;;
esac
EXPECTED_VARIABLE_NAMES=(\
Wallet \
)
local SEARCH_NAMES=()
local MISSING_VARIABLES="0"
for VARIABLE_NAME in ${EXPECTED_VARIABLES[@]}; do
if [ "${!VARIABLE_NAME}" = "" ]; then
echo "$VARIABLE_NAME not defined"
MISSING_VARIABLES="1"
fi
done
if [ "$MISSING_VARIABLES" == "1" ]; then
exit 1
fi
local VARIABLE_COUNT=${#EXPECTED_VARIABLES[@]}
for (( i=0; i<$VARIABLE_COUNT; i=i+1 )); do
VARIABLE_NAME="${EXPECTED_VARIABLES[$(($i))]}"
SEARCH_NAMES=("${SEARCH_NAMES[@]}" "${EXPECTED_VARIABLE_NAMES[$i]}" "${!VARIABLE_NAME}")
done
local DATA_PATH="build-input/data"
local OUTPUT_DIRECTORY="$DATA_PATH/provisioning-profiles"
rm -rf "$OUTPUT_DIRECTORY"
mkdir -p "$OUTPUT_DIRECTORY"
local BUILD_PATH="$OUTPUT_DIRECTORY/BUILD"
touch "$BUILD_PATH"
echo "exports_files([" >> "$BUILD_PATH"
local ELEMENT_COUNT=${#SEARCH_NAMES[@]}
local REMAINDER=$(($ELEMENT_COUNT % 2))
if [ $REMAINDER != 0 ]; then
>&2 echo "Expecting key-value pairs"
exit 1
fi
for PROFILE in `find "$CODESIGNING_DATA_PATH" -type f -name "*.mobileprovision"`; do
PROFILE_DATA=$(security cms -D -i "$PROFILE")
PROFILE_NAME=$(/usr/libexec/PlistBuddy -c "Print :Name" /dev/stdin <<< $(echo $PROFILE_DATA))
for (( i=0; i<$ELEMENT_COUNT; i=i+2 )); do
ID=${SEARCH_NAMES[$i]}
SEARCH_NAME=${SEARCH_NAMES[$(($i + 1))]}
if [ "$PROFILE_NAME" = "$SEARCH_NAME" ]; then
VARIABLE_NAME="FOUND_PROFILE_$ID"
if [ "${!VARIABLE_NAME}" = "" ]; then
eval "FOUND_PROFILE_$ID=\"$PROFILE\""
else
>&2 echo "Found multiple profiles with name \"$SEARCH_NAME\""
exit 1
fi
fi
done
done
for (( i=0; i<$ELEMENT_COUNT; i=i+2 )); do
ID=${SEARCH_NAMES[$i]}
SEARCH_NAME=${SEARCH_NAMES[$(($i + 1))]}
VARIABLE_NAME="FOUND_PROFILE_$ID"
FOUND_PROFILE="${!VARIABLE_NAME}"
if [ "$FOUND_PROFILE" = "" ]; then
>&2 echo "Profile \"$SEARCH_NAME\" not found"
exit 1
fi
cp "$FOUND_PROFILE" "$OUTPUT_DIRECTORY/$ID.mobileprovision"
echo " \"$ID.mobileprovision\"," >> $BUILD_PATH
done
echo "])" >> "$BUILD_PATH"
}

View File

@ -4,7 +4,7 @@ set -e
APP_TARGET="$1"
if [ "$APP_TARGET" == "" ]; then
echo "Usage: sh generate-xcode-project.sh app_target"
echo "Usage: sh generate-xcode-project.sh app_target_folder"
exit 1
fi
@ -22,31 +22,6 @@ if [ "$INSTALLED_XCODE_VERSION" != "$XCODE_VERSION" ]; then
exit 1
fi
EXPECTED_VARIABLES=(\
BUILD_NUMBER \
APP_VERSION \
BUNDLE_ID \
DEVELOPMENT_TEAM \
API_ID \
API_HASH \
APP_CENTER_ID \
IS_INTERNAL_BUILD \
IS_APPSTORE_BUILD \
APPSTORE_ID \
APP_SPECIFIC_URL_SCHEME \
)
MISSING_VARIABLES="0"
for VARIABLE_NAME in ${EXPECTED_VARIABLES[@]}; do
if [ "${!VARIABLE_NAME}" = "" ]; then
echo "$VARIABLE_NAME not defined"
MISSING_VARIABLES="1"
fi
done
if [ "$MISSING_VARIABLES" == "1" ]; then
exit 1
fi
GEN_DIRECTORY="build-input/gen/project"
rm -rf "$GEN_DIRECTORY"
mkdir -p "$GEN_DIRECTORY"
@ -84,18 +59,16 @@ fi
--bazel "$BAZEL" \
--outputfolder "$GEN_DIRECTORY" \
--target "$APP_TARGET":"$APP_TARGET" \
--target "$APP_TARGET":Main \
--target "$APP_TARGET":Lib \
PATCH_OPTIONS="BazelBuildOptionsDebug BazelBuildOptionsRelease"
for NAME in $PATCH_OPTIONS; do
sed -i "" -e '1h;2,$H;$!d;g' -e 's/\("'"$NAME"'" : {\n[ ]*"p" : "$(inherited)\)/\1'" ${BAZEL_OPTIONS[*]}"'/' "$GEN_DIRECTORY/$APP_TARGET.tulsiproj/Configs/$APP_TARGET.tulsigen"
sed -i "" -e '1h;2,$H;$!d;g' -e 's/\("'"$NAME"'" : {\n[ ]*"p" : "$(inherited)\)/\1'" ${BAZEL_OPTIONS[*]}"'/' "$GEN_DIRECTORY/${APP_TARGET}.tulsiproj/Configs/${APP_TARGET}.tulsigen"
done
sed -i "" -e '1h;2,$H;$!d;g' -e 's/\("sourceFilters" : \[\n[ ]*\)"\.\/\.\.\."/\1"$APP_TARGET\/...", "submodules\/..."/' "$GEN_DIRECTORY/$APP_TARGET.tulsiproj/Configs/$APP_TARGET.tulsigen"
sed -i "" -e '1h;2,$H;$!d;g' -e 's/\("sourceFilters" : \[\n[ ]*\)"\.\/\.\.\."/\1"'"${APP_TARGET}"'\/...", "submodules\/..."/' "$GEN_DIRECTORY/${APP_TARGET}.tulsiproj/Configs/${APP_TARGET}.tulsigen"
"$TULSI" -- \
--verbose \
--genconfig "$GEN_DIRECTORY/$APP_TARGET.tulsiproj:$APP_TARGET" \
--genconfig "$GEN_DIRECTORY/${APP_TARGET}.tulsiproj:${APP_TARGET}" \
--bazel "$BAZEL" \
--outputfolder "$GEN_DIRECTORY" \

View File

@ -0,0 +1,63 @@
#!/bin/sh
set -e
prepare_build_variables () {
BUILD_TYPE="$1"
case "$BUILD_TYPE" in
development)
APS_ENVIRONMENT="development"
;;
distribution)
APS_ENVIRONMENT="production"
;;
*)
echo "Unknown build provisioning type: $BUILD_TYPE"
exit 1
;;
esac
local BAZEL="$(which bazel)"
if [ "$BAZEL" = "" ]; then
echo "bazel not found in PATH"
exit 1
fi
local EXPECTED_VARIABLES=(\
BUILD_NUMBER \
WALLET_APP_VERSION \
WALLET_BUNDLE_ID \
WALLET_DEVELOPMENT_TEAM \
)
local MISSING_VARIABLES="0"
for VARIABLE_NAME in ${EXPECTED_VARIABLES[@]}; do
if [ "${!VARIABLE_NAME}" = "" ]; then
echo "$VARIABLE_NAME not defined"
MISSING_VARIABLES="1"
fi
done
if [ "$MISSING_VARIABLES" == "1" ]; then
exit 1
fi
local VARIABLES_DIRECTORY="build-input/data"
mkdir -p "$VARIABLES_DIRECTORY"
local VARIABLES_PATH="$VARIABLES_DIRECTORY/variables.bzl"
rm -f "$VARIABLES_PATH"
echo "wallet_build_number = \"$BUILD_NUMBER\"" >> "$VARIABLES_PATH"
echo "wallet_version = \"$WALLET_APP_VERSION\"" >> "$VARIABLES_PATH"
echo "wallet_bundle_id = \"$WALLET_BUNDLE_ID\"" >> "$VARIABLES_PATH"
echo "wallet_api_id = \"$WALLET_API_ID\"" >> "$VARIABLES_PATH"
echo "wallet_team_id = \"$WALLET_DEVELOPMENT_TEAM\"" >> "$VARIABLES_PATH"
echo "telegram_api_id = \"1\"" >> "$VARIABLES_PATH"
echo "telegram_api_hash = \"1\"" >> "$VARIABLES_PATH"
echo "telegram_app_center_id = \"1\"" >> "$VARIABLES_PATH"
echo "telegram_appstore_id = \"1\"" >> "$VARIABLES_PATH"
echo "telegram_is_internal_build = \"false\"" >> "$VARIABLES_PATH"
echo "telegram_is_appstore_build = \"true\"" >> "$VARIABLES_PATH"
echo "telegram_app_specific_url_scheme = \"\"" >> "$VARIABLES_PATH"
}

View File

@ -2,7 +2,13 @@
set -e
BUILD_TYPE="$1"
APP_TARGET="$1"
if [ "$APP_TARGET" == "" ]; then
echo "Usage: sh prepare-build.sh app_target development|distribution"
exit 1
fi
BUILD_TYPE="$2"
case "$BUILD_TYPE" in
development)
PROFILES_TYPE="development"
@ -18,13 +24,26 @@ esac
BASE_PATH=$(dirname $0)
COPY_PROVISIONING_PROFILES_SCRIPT="$BASE_PATH/copy-provisioning-profiles-$APP_TARGET.sh"
PREPARE_BUILD_VARIABLES_SCRIPT="$BASE_PATH/prepare-build-variables-$APP_TARGET.sh"
if [ ! -f "$COPY_PROVISIONING_PROFILES_SCRIPT" ]; then
echo "$COPY_PROVISIONING_PROFILES_SCRIPT not found"
exit 1
fi
if [ ! -f "$PREPARE_BUILD_VARIABLES_SCRIPT" ]; then
echo "$PREPARE_BUILD_VARIABLES_SCRIPT not found"
exit 1
fi
DATA_DIRECTORY="build-input/data"
rm -rf "$DATA_DIRECTORY"
mkdir -p "$DATA_DIRECTORY"
touch "$DATA_DIRECTORY/BUILD"
source "$BASE_PATH/copy-provisioning-profiles.sh"
source "$BASE_PATH/prepare-build-variables.sh"
source "$COPY_PROVISIONING_PROFILES_SCRIPT"
source "$PREPARE_BUILD_VARIABLES_SCRIPT"
echo "Copying provisioning profiles..."
copy_provisioning_profiles "$PROFILES_TYPE"

View File

@ -1 +1 @@
11.3.1
11.4

View File

@ -543,7 +543,7 @@ public final class AnimatedStickerNode: ASDisplayNode {
let frameSourceHolder = self.frameSource
self.queue.async { [weak self] in
var maybeFrameSource: AnimatedStickerFrameSource?
var notifyUpdated: (() -> Void)?
let notifyUpdated: (() -> Void)? = nil
if let directData = directData {
maybeFrameSource = AnimatedStickerDirectFrameSource(queue: queue, data: directData.0, width: directData.2, height: directData.3)
} else if let (cachedData, cachedDataComplete) = cachedData {

View File

@ -42,7 +42,6 @@ public class ActionSheetSwitchNode: ActionSheetItemNode {
override public init(theme: ActionSheetControllerTheme) {
self.theme = theme
let defaultFont = Font.regular(floor(theme.baseFontSize * 20.0 / 17.0))
self.button = HighlightTrackingButton()
self.button.isAccessibilityElement = false

View File

@ -152,8 +152,7 @@ public extension ContainedViewLayoutTransition {
if let completion = completion {
completion(true)
}
case let .animated(duration, curve):
let previousBounds = node.bounds
case .animated:
let previousCenter = node.frame.center
node.position = frame.center
node.bounds = CGRect(origin: node.bounds.origin, size: frame.size)

View File

@ -1,6 +1,5 @@
import Foundation
import AsyncDisplayKit
import Display
public final class ContextContentContainerNode: ASDisplayNode {
public var contentNode: ContextContentNode?

View File

@ -1,6 +1,5 @@
import Foundation
import AsyncDisplayKit
import Display
public final class ContextExtractedContentContainingNode: ASDisplayNode {
public let contentNode: ContextExtractedContentNode

View File

@ -1,6 +1,5 @@
import Foundation
import AsyncDisplayKit
import Display
public final class ContextControllerSourceNode: ASDisplayNode {
private var contextGesture: ContextGesture?

View File

@ -1,7 +1,6 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
public enum ContextGestureTransition {
case begin
@ -207,7 +206,7 @@ public final class ContextGesture: UIGestureRecognizer, UIGestureRecognizerDeleg
override public func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesCancelled(touches, with: event)
if let touch = touches.first, !self.currentProgress.isZero, self.isValidated {
if let _ = touches.first, !self.currentProgress.isZero, self.isValidated {
let previousProgress = self.currentProgress
self.currentProgress = 0.0
self.activationProgress?(0.0, .ended(previousProgress))

View File

@ -34,7 +34,7 @@ public struct Font {
public static func with(size: CGFloat, design: Design = .regular, traits: Traits = []) -> UIFont {
if #available(iOS 13.0, *) {
var descriptor = UIFont.systemFont(ofSize: size).fontDescriptor
let descriptor = UIFont.systemFont(ofSize: size).fontDescriptor
var symbolicTraits = descriptor.symbolicTraits
if traits.contains(.bold) {
symbolicTraits.insert(.traitBold)

View File

@ -179,13 +179,13 @@ private struct WrappedGridSection: Equatable, Hashable {
self.section = section
}
var hashValue: Int {
return self.section.hashValue
}
static func ==(lhs: WrappedGridSection, rhs: WrappedGridSection) -> Bool {
return lhs.section.isEqual(to: rhs.section)
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.section.hashValue)
}
}
public struct GridNodeVisibleItems {
@ -200,10 +200,6 @@ public struct GridNodeVisibleItems {
private struct WrappedGridItemNode: Hashable {
let node: ASDisplayNode
var hashValue: Int {
return node.hashValue
}
static func ==(lhs: WrappedGridItemNode, rhs: WrappedGridItemNode) -> Bool {
return lhs.node === rhs.node
}

View File

@ -6,79 +6,24 @@ import SwiftSignalKit
private enum Corner: Hashable {
case TopLeft(Int), TopRight(Int), BottomLeft(Int), BottomRight(Int)
var hashValue: Int {
switch self {
case let .TopLeft(radius):
return radius | (1 << 24)
case let .TopRight(radius):
return radius | (2 << 24)
case let .BottomLeft(radius):
return radius | (3 << 24)
case let .BottomRight(radius):
return radius | (4 << 24)
}
}
var radius: Int {
switch self {
case let .TopLeft(radius):
return radius
case let .TopRight(radius):
return radius
case let .BottomLeft(radius):
return radius
case let .BottomRight(radius):
return radius
case let .TopLeft(radius):
return radius
case let .TopRight(radius):
return radius
case let .BottomLeft(radius):
return radius
case let .BottomRight(radius):
return radius
}
}
}
private func ==(lhs: Corner, rhs: Corner) -> Bool {
switch lhs {
case let .TopLeft(lhsRadius):
switch rhs {
case let .TopLeft(rhsRadius) where rhsRadius == lhsRadius:
return true
default:
return false
}
case let .TopRight(lhsRadius):
switch rhs {
case let .TopRight(rhsRadius) where rhsRadius == lhsRadius:
return true
default:
return false
}
case let .BottomLeft(lhsRadius):
switch rhs {
case let .BottomLeft(rhsRadius) where rhsRadius == lhsRadius:
return true
default:
return false
}
case let .BottomRight(lhsRadius):
switch rhs {
case let .BottomRight(rhsRadius) where rhsRadius == lhsRadius:
return true
default:
return false
}
}
}
private enum Tail: Hashable {
case BottomLeft(Int)
case BottomRight(Int)
var hashValue: Int {
switch self {
case let .BottomLeft(radius):
return radius | (1 << 24)
case let .BottomRight(radius):
return radius | (2 << 24)
}
}
var radius: Int {
switch self {
case let .BottomLeft(radius):
@ -89,25 +34,6 @@ private enum Tail: Hashable {
}
}
private func ==(lhs: Tail, rhs: Tail) -> Bool {
switch lhs {
case let .BottomLeft(lhsRadius):
switch rhs {
case let .BottomLeft(rhsRadius) where rhsRadius == lhsRadius:
return true
default:
return false
}
case let .BottomRight(lhsRadius):
switch rhs {
case let .BottomRight(rhsRadius) where rhsRadius == lhsRadius:
return true
default:
return false
}
}
}
private var cachedCorners = Atomic<[Corner: DrawingContext]>(value: [:])
private func cornerContext(_ corner: Corner) -> DrawingContext {

View File

@ -13,8 +13,9 @@ public struct KeyShortcut: Hashable {
self.action = action
}
public var hashValue: Int {
return input.hashValue ^ modifiers.hashValue
public func hash(into hasher: inout Hasher) {
hasher.combine(self.input)
hasher.combine(self.modifiers)
}
public static func ==(lhs: KeyShortcut, rhs: KeyShortcut) -> Bool {

View File

@ -882,8 +882,6 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
var completeHeight: CGFloat = 0.0
var topItemFound = false
var bottomItemFound = false
var topItemEdge: CGFloat = 0.0
var bottomItemEdge: CGFloat = 0.0
for i in 0 ..< self.itemNodes.count {
if let index = itemNodes[i].index {
@ -900,25 +898,15 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
effectiveInsets.top = max(effectiveInsets.top, self.visibleSize.height - additionalInverseTopInset)
}
if topItemFound {
topItemEdge = itemNodes[0].apparentFrame.origin.y
}
var bottomItemNode: ListViewItemNode?
for i in (0 ..< self.itemNodes.count).reversed() {
if let index = itemNodes[i].index {
if index == self.items.count - 1 {
bottomItemNode = itemNodes[i]
bottomItemFound = true
}
break
}
}
if bottomItemFound {
bottomItemEdge = itemNodes[itemNodes.count - 1].apparentFrame.maxY
}
if topItemFound && bottomItemFound {
for itemNode in self.itemNodes {
completeHeight += itemNode.apparentBounds.height
@ -1119,7 +1107,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
if topItemIndexAndMinY.0 == 0 {
var offsetValue: CGFloat = -(topItemIndexAndMinY.1 - self.insets.top)
let offsetValue: CGFloat = -(topItemIndexAndMinY.1 - self.insets.top)
offset = .known(offsetValue)
} else if topItemIndexAndMinY.0 == -1 {
offset = .none
@ -1950,7 +1938,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
private func fillMissingNodes(synchronous: Bool, synchronousLoads: Bool, animated: Bool, inputAnimatedInsertIndices: Set<Int>, insertDirectionHints: [Int: ListViewItemOperationDirectionHint], inputState: ListViewState, inputPreviousNodes: [Int: QueueLocalObject<ListViewItemNode>], inputOperations: [ListViewStateOperation], inputCompletion: @escaping (ListViewState, [ListViewStateOperation]) -> Void) {
let animatedInsertIndices = inputAnimatedInsertIndices
var state = inputState
var previousNodes = inputPreviousNodes
let previousNodes = inputPreviousNodes
var operations = inputOperations
let completion = inputCompletion
let updateAnimation: ListViewItemUpdateAnimation = animated ? .System(duration: insertionAnimationDuration) : .None
@ -2680,7 +2668,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
self.visibleSize = updateSizeAndInsets.size
var offsetFix: CGFloat
var insetDeltaOffsetFix: CGFloat = 0.0
let insetDeltaOffsetFix: CGFloat = 0.0
if self.isTracking || isExperimentalSnapToScrollToItem {
offsetFix = 0.0
} else if self.snapToBottomInsetUntilFirstInteraction {
@ -4009,7 +3997,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
public func cancelSelection() {
if let selectionTouchLocation = self.selectionTouchLocation {
if let _ = self.selectionTouchLocation {
self.clearHighlightAnimated(true)
self.selectionTouchLocation = nil
}

View File

@ -23,6 +23,8 @@ public enum WindowUserInterfaceStyle {
self = .light
case .dark:
self = .dark
@unknown default:
self = .dark
}
}
}
@ -188,33 +190,6 @@ private final class WindowRootViewController: UIViewController, UIViewController
private var previewingContext: AnyObject?
private func updatePreviewingRegistration() {
var shouldRegister = false
var isVoiceOverRunning = false
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
isVoiceOverRunning = UIAccessibility.isVoiceOverRunning
}
if !isVoiceOverRunning {
shouldRegister = true
}
shouldRegister = false
if shouldRegister != self.registeredForPreviewing {
self.registeredForPreviewing = shouldRegister
if shouldRegister {
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
self.previewingContext = self.registerForPreviewing(with: self, sourceView: self.view)
}
} else if let previewingContext = self.previewingContext {
self.previewingContext = nil
if let previewingContext = previewingContext as? UIViewControllerPreviewing {
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
self.unregisterForPreviewing(withContext: previewingContext)
}
}
}
}
}
private weak var previousPreviewingHostView: (UIView & PreviewingHostView)?

View File

@ -41,7 +41,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
update(strongSelf)
}
}))
if let localIsReady = localIsReady {
if let _ = localIsReady {
self.isReady = true
} else {
localIsReady = false
@ -170,12 +170,9 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
let topController = self.controllers[self.controllers.count - 1]
let bottomController = self.controllers[self.controllers.count - 2]
if let topController = topController as? ViewController {
if !topController.attemptNavigation({ [weak self] in
//let _ = self?.popViewController(animated: true)
}) {
return
}
if !topController.attemptNavigation({
}) {
return
}
topController.viewWillDisappear(true)
@ -221,12 +218,11 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
if velocity > 1000 || navigationTransitionCoordinator.progress > 0.2 {
navigationTransitionCoordinator.animateCompletion(velocity, completion: { [weak self] in
guard let strongSelf = self, let layout = strongSelf.state.layout, let transition = strongSelf.state.transition, let top = strongSelf.state.top else {
guard let strongSelf = self, let _ = strongSelf.state.layout, let _ = strongSelf.state.transition, let top = strongSelf.state.top else {
return
}
let topController = top.value
let bottomController = transition.previous.value
if viewTreeContainsFirstResponder(view: top.value.view) {
strongSelf.ignoreInputHeight = true
@ -349,7 +345,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
var updatedStatusBarStyle = self.statusBarStyle
if let top = self.state.top {
var updatedLayout = layout
if let topTransition = self.state.transition, top.value.view.disableAutomaticKeyboardHandling.isEmpty {
if let _ = self.state.transition, top.value.view.disableAutomaticKeyboardHandling.isEmpty {
if !viewTreeContainsFirstResponder(view: top.value.view) {
updatedLayout = updatedLayout.withUpdatedInputHeight(nil)
}

View File

@ -155,7 +155,7 @@ open class NavigationController: UINavigationController, ContainableController,
private var _viewControllers: [ViewController] = []
override open var viewControllers: [UIViewController] {
get {
return self._viewControllers.map { $0 as! ViewController }
return self._viewControllers.map { $0 as UIViewController }
} set(value) {
self.setViewControllers(value, animated: false)
}
@ -287,7 +287,6 @@ open class NavigationController: UINavigationController, ContainableController,
}
public func updateTheme(_ theme: NavigationControllerTheme) {
let statusBarStyleUpdated = self.theme.statusBar != theme.statusBar
self.theme = theme
if let rootContainer = self.rootContainer {
switch rootContainer {
@ -790,7 +789,7 @@ open class NavigationController: UINavigationController, ContainableController,
}
let rootModalFrame: NavigationModalFrame
var modalFrameTransition: ContainedViewLayoutTransition = transition
let modalFrameTransition: ContainedViewLayoutTransition = transition
var forceStatusBarAnimation = false
if let current = self.rootModalFrame {
rootModalFrame = current
@ -1165,7 +1164,7 @@ open class NavigationController: UINavigationController, ContainableController,
self.overlayContainers.append(container)
}
container.isReadyUpdated = { [weak self, weak container] in
guard let strongSelf = self, let container = container else {
guard let strongSelf = self, let _ = container else {
return
}
strongSelf.updateContainersNonReentrant(transition: .immediate)
@ -1245,7 +1244,7 @@ open class NavigationController: UINavigationController, ContainableController,
self.view.setNeedsLayout()
}
private func requestLayout(transition: ContainedViewLayoutTransition) {
public func requestLayout(transition: ContainedViewLayoutTransition) {
if self.isViewLoaded, let validLayout = self.validLayout {
self.containerLayoutUpdated(validLayout, transition: transition)
}

View File

@ -69,7 +69,7 @@ public class NavigationBackButtonNode: ASControlNode {
}
public override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
self.label.updateLayout(CGSize(width: max(0.0, constrainedSize.width - self.arrow.frame.size.width - self.arrowSpacing), height: constrainedSize.height))
let _ = self.label.updateLayout(CGSize(width: max(0.0, constrainedSize.width - self.arrow.frame.size.width - self.arrowSpacing), height: constrainedSize.height))
return CGSize(width: self.arrow.frame.size.width + self.arrowSpacing + self.label.calculatedSize.width, height: max(self.arrow.frame.size.height, self.label.calculatedSize.height))
}

View File

@ -1059,7 +1059,7 @@ open class NavigationBar: ASDisplayNode {
node.updateManualText(self.backButtonNode.manualText)
node.color = accentColor
if let (size, defaultHeight, _, _, _, _) = self.validLayout {
node.updateLayout(constrainedSize: CGSize(width: size.width, height: defaultHeight))
let _ = node.updateLayout(constrainedSize: CGSize(width: size.width, height: defaultHeight))
node.frame = self.backButtonNode.frame
}
return node
@ -1082,7 +1082,7 @@ open class NavigationBar: ASDisplayNode {
node.updateItems(items)
node.color = accentColor
if let (size, defaultHeight, _, _, _, _) = self.validLayout {
node.updateLayout(constrainedSize: CGSize(width: size.width, height: defaultHeight))
let _ = node.updateLayout(constrainedSize: CGSize(width: size.width, height: defaultHeight))
node.frame = self.backButtonNode.frame
}
return node

View File

@ -62,22 +62,15 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
} set(value) {
_image = value
if let value = value {
if let _ = value {
if self.imageNode == nil {
let imageNode = ASImageNode()
imageNode.displayWithoutProcessing = true
imageNode.displaysAsynchronously = false
self.imageNode = imageNode
if false, value.size == CGSize(width: 30.0, height: 30.0) {
if self.imageRippleNode.supernode == nil {
self.addSubnode(self.imageRippleNode)
self.imageRippleNode.image = generateFilledCircleImage(diameter: 30.0, color: self.rippleColor)
}
} else {
if self.imageRippleNode.supernode != nil {
self.imageRippleNode.image = nil
self.imageRippleNode.removeFromSupernode()
}
if self.imageRippleNode.supernode != nil {
self.imageRippleNode.image = nil
self.imageRippleNode.removeFromSupernode()
}
self.addSubnode(imageNode)

View File

@ -48,7 +48,7 @@ public class NavigationTitleNode: ASDisplayNode {
}
public override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
self.label.updateLayout(constrainedSize)
let _ = self.label.updateLayout(constrainedSize)
return self.label.calculatedSize
}

View File

@ -54,7 +54,7 @@ public struct TransformImageArguments: Equatable {
}
public static func ==(lhs: TransformImageArguments, rhs: TransformImageArguments) -> Bool {
var result = lhs.imageSize == rhs.imageSize && lhs.boundingSize == rhs.boundingSize && lhs.corners == rhs.corners && lhs.emptyColor == rhs.emptyColor
let result = lhs.imageSize == rhs.imageSize && lhs.boundingSize == rhs.boundingSize && lhs.corners == rhs.corners && lhs.emptyColor == rhs.emptyColor
if result {
if let lhsCustom = lhs.custom, let rhsCustom = rhs.custom {
return lhsCustom.serialized().isEqual(rhsCustom.serialized())

View File

@ -316,7 +316,7 @@ public func assertNotOnMainThread(_ file: String = #file, line: Int = #line) {
}
public extension UIImage {
public func precomposed() -> UIImage {
func precomposed() -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
self.draw(at: CGPoint())
let result = UIGraphicsGetImageFromCurrentImageContext()!

View File

@ -562,18 +562,6 @@ public enum TabBarItemContextActionType {
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
open func registerForPreviewing(with delegate: UIViewControllerPreviewingDelegate, sourceView: UIView, theme: PeekControllerTheme, onlyNative: Bool) {
if false, self.traitCollection.forceTouchCapability == .available {
let _ = super.registerForPreviewing(with: delegate, sourceView: sourceView)
} else if !onlyNative {
if self.previewingContext == nil {
let previewingContext = SimulatedViewControllerPreviewing(theme: theme, delegate: delegate, sourceView: sourceView, node: self.displayNode, present: { [weak self] c, a in
self?.presentInGlobalOverlay(c, with: a)
}, customPresent: { [weak self] c, n in
return self?.customPresentPreviewingController?(c, n)
})
self.previewingContext = previewingContext
}
}
}
@available(iOSApplicationExtension 9.0, iOS 9.0, *)

View File

@ -42,7 +42,6 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
public var rotation: CGFloat = 0.0 {
didSet {
let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)
var fromValue: CGFloat = 0.0
if let value = (self.layer.value(forKeyPath: "transform.rotation.z") as? NSNumber)?.floatValue {
fromValue = CGFloat(value)

View File

@ -338,10 +338,10 @@ public class Window1 {
}
strongSelf._rootController?.displayNode.accessibilityElementsHidden = strongSelf.presentationContext.hasOpaqueOverlay || strongSelf.topPresentationContext.hasOpaqueOverlay
}
self.presentationContext.updateHasOpaqueOverlay = { [weak self] value in
self.presentationContext.updateHasOpaqueOverlay = { value in
updateOpaqueOverlays()
}
self.topPresentationContext.updateHasOpaqueOverlay = { [weak self] value in
self.topPresentationContext.updateHasOpaqueOverlay = { value in
updateOpaqueOverlays()
}
@ -846,7 +846,7 @@ public class Window1 {
}
private func layoutSubviews(force: Bool) {
if self.tracingStatusBarsInvalidated, let keyboardManager = keyboardManager {
if self.tracingStatusBarsInvalidated, let _ = keyboardManager {
self.tracingStatusBarsInvalidated = false
var supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .all)
@ -1226,11 +1226,11 @@ public class Window1 {
if let navigationController = self._rootController as? NavigationController {
if !excludeNavigationSubControllers {
for case let controller as ContainableController in navigationController.viewControllers {
!f(controller)
let _ = f(controller)
}
}
if let controller = navigationController.topOverlayController {
!f(controller)
let _ = f(controller)
}
}
for (controller, _) in self.presentationContext.controllers {

View File

@ -13,12 +13,14 @@ public struct LocalAuth {
if context.canEvaluatePolicy(LAPolicy(rawValue: Int(kLAPolicyDeviceOwnerAuthenticationWithBiometrics))!, error: nil) {
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
switch context.biometryType {
case .faceID:
return .faceId
case .touchID:
return .touchId
case .none:
return nil
case .faceID:
return .faceId
case .touchID:
return .touchId
case .none:
return nil
@unknown default:
return nil
}
} else {
return .touchId

View File

@ -13,12 +13,12 @@ public enum QrCodeIcon {
}
private func floorToContextPixels(_ value: CGFloat, scale: CGFloat? = UIScreenScale) -> CGFloat {
var scale = scale ?? UIScreenScale
let scale = scale ?? UIScreenScale
return floor(value * scale) / scale
}
private func roundToContextPixels(_ value: CGFloat, scale: CGFloat? = UIScreenScale) -> CGFloat {
var scale = scale ?? UIScreenScale
let scale = scale ?? UIScreenScale
return round(value * scale) / scale
}

View File

@ -1,4 +1,4 @@
load("//build-system:unique_directories.bzl", "unique_directories")
load("//build-system/bazel-utils:unique_directories.bzl", "unique_directories")
private_headers = glob([
"Sources/**/*.h",

View File

@ -152,7 +152,7 @@ public final class DisposableSet : Disposable {
public func remove(_ disposable: Disposable) {
pthread_mutex_lock(&self.lock)
if let index = self.disposables.index(where: { $0 === disposable }) {
if let index = self.disposables.firstIndex(where: { $0 === disposable }) {
self.disposables.remove(at: index)
}
pthread_mutex_unlock(&self.lock)

View File

@ -30,19 +30,19 @@ public func deliverOn<T, E>(_ threadPool: ThreadPool) -> (Signal<T, E>) -> Signa
let queue = threadPool.nextQueue()
return signal.start(next: { next in
queue.addTask(ThreadPoolTask { state in
if !state.cancelled.with { $0 } {
if !state.cancelled.with({ $0 }) {
subscriber.putNext(next)
}
})
}, error: { error in
queue.addTask(ThreadPoolTask { state in
if !state.cancelled.with { $0 } {
if !state.cancelled.with({ $0 }) {
subscriber.putError(error)
}
})
}, completed: {
queue.addTask(ThreadPoolTask { state in
if !state.cancelled.with { $0 } {
if !state.cancelled.with({ $0 }) {
subscriber.putCompletion()
}
})
@ -97,7 +97,7 @@ public func runOn<T, E>(_ threadPool: ThreadPool) -> (Signal<T, E>) -> Signal<T,
let disposable = MetaDisposable()
let task = ThreadPoolTask { state in
if cancelled || state.cancelled.with { $0 } {
if cancelled || state.cancelled.with({ $0 }) {
return
}

View File

@ -13,7 +13,7 @@ public final class ThreadPoolTask {
}
func execute() {
if !state.cancelled.with { $0 } {
if !state.cancelled.with({ $0 }) {
self.action(self.state)
}
}
@ -74,7 +74,7 @@ public func ==(lhs: ThreadPoolQueue, rhs: ThreadPoolQueue) -> Bool {
pthread_mutex_lock(&threadPool.mutex);
if queue != nil {
if let index = threadPool.takenQueues.index(of: queue) {
if let index = threadPool.takenQueues.firstIndex(of: queue) {
threadPool.takenQueues.remove(at: index)
}
@ -97,7 +97,7 @@ public func ==(lhs: ThreadPoolQueue, rhs: ThreadPoolQueue) -> Bool {
task = queue.popFirstTask()
threadPool.takenQueues.append(queue)
if let index = threadPool.queues.index(of: queue) {
if let index = threadPool.queues.firstIndex(of: queue) {
threadPool.queues.remove(at: index)
}

View File

@ -83,10 +83,10 @@ public final class ScreenCaptureDetectionManager {
public init(check: @escaping () -> Bool) {
self.observer = NotificationCenter.default.addObserver(forName: UIApplication.userDidTakeScreenshotNotification, object: nil, queue: .main, using: { [weak self] _ in
guard let strongSelf = self else {
guard let _ = self else {
return
}
check()
let _ = check()
})
self.screenRecordingDisposable = screenRecordingActive().start(next: { [weak self] value in
@ -116,7 +116,9 @@ public final class ScreenCaptureDetectionManager {
}
deinit {
NotificationCenter.default.removeObserver(self.observer)
if let observer = self.observer {
NotificationCenter.default.removeObserver(observer)
}
self.screenRecordingDisposable?.dispose()
self.screenRecordingCheckTimer?.invalidate()
self.screenRecordingCheckTimer = nil

View File

@ -154,7 +154,7 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
}
let spacingOffset: CGFloat = 9.0
var verticalInset: CGFloat = self.subtitle == nil ? floor((buttonFrame.height - titleSize.height) / 2.0) : floor((buttonFrame.height - titleSize.height) / 2.0) - spacingOffset
let verticalInset: CGFloat = self.subtitle == nil ? floor((buttonFrame.height - titleSize.height) / 2.0) : floor((buttonFrame.height - titleSize.height) / 2.0) - spacingOffset
let titleFrame = CGRect(origin: CGPoint(x: buttonFrame.minX + nextContentOrigin, y: buttonFrame.minY + verticalInset), size: titleSize)
transition.updateFrame(node: self.titleNode, frame: titleFrame)

View File

@ -59,11 +59,20 @@ NS_ASSUME_NONNULL_BEGIN
@end
@interface TONTransactionMessageContentsEncryptedText : NSObject <TONTransactionMessageContents>
@interface TONEncryptedData : NSObject
@property (nonatomic, strong, readonly) NSString * _Nonnull sourceAddress;
@property (nonatomic, strong, readonly) NSData * _Nonnull data;
- (instancetype)initWithData:(NSData * _Nonnull)data;
- (instancetype)initWithSourceAddress:(NSString * _Nonnull)sourceAddress data:(NSData * _Nonnull)data;
@end
@interface TONTransactionMessageContentsEncryptedText : NSObject <TONTransactionMessageContents>
@property (nonatomic, strong, readonly) TONEncryptedData * _Nonnull encryptedData;
- (instancetype)initWithEncryptedData:(TONEncryptedData * _Nonnull)encryptedData;
@end
@ -168,7 +177,7 @@ NS_ASSUME_NONNULL_BEGIN
- (SSignal *)deleteKey:(TONKey *)key;
- (SSignal *)deleteAllKeys;
- (SSignal *)getTransactionListWithAddress:(NSString * _Nonnull)address lt:(int64_t)lt hash:(NSData * _Nonnull)hash;
- (SSignal *)decryptMessagesWithKey:(TONKey * _Nonnull)key localPassword:(NSData * _Nonnull)localPassword messages:(NSArray<NSData *> * _Nonnull)messages;
- (SSignal *)decryptMessagesWithKey:(TONKey * _Nonnull)key localPassword:(NSData * _Nonnull)localPassword messages:(NSArray<TONEncryptedData *> * _Nonnull)messages;
- (NSData *)encrypt:(NSData *)decryptedData secret:(NSData *)data;
- (NSData * __nullable)decrypt:(NSData *)encryptedData secret:(NSData *)data;

View File

@ -46,8 +46,8 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
if (message == nullptr) {
return nil;
}
NSString *source = readString(message->source_);
NSString *destination = readString(message->destination_);
NSString *source = readString(message->source_->account_address_);
NSString *destination = readString(message->destination_->account_address_);
id<TONTransactionMessageContents> contents = nil;
if (message->msg_data_->get_id() == tonlib_api::msg_dataRaw::ID) {
@ -71,7 +71,8 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
}
} else if (message->msg_data_->get_id() == tonlib_api::msg_dataEncryptedText::ID) {
auto msgData = tonlib_api::move_object_as<tonlib_api::msg_dataEncryptedText>(message->msg_data_);
contents = [[TONTransactionMessageContentsEncryptedText alloc] initWithData:makeData(msgData->text_)];
TONEncryptedData *encryptedData = [[TONEncryptedData alloc] initWithSourceAddress:source data:makeData(msgData->text_)];
contents = [[TONTransactionMessageContentsEncryptedText alloc] initWithEncryptedData:encryptedData];
} else {
contents = [[TONTransactionMessageContentsRawData alloc] initWithData:[NSData data]];
}
@ -150,10 +151,10 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
@implementation TONTransactionMessageContentsEncryptedText
- (instancetype)initWithData:(NSData * _Nonnull)data {
- (instancetype)initWithEncryptedData:(TONEncryptedData * _Nonnull)encryptedData {
self = [super init];
if (self != nil) {
_data = data;
_encryptedData = encryptedData;
}
return self;
}
@ -274,6 +275,19 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
@end
@implementation TONEncryptedData
- (instancetype)initWithSourceAddress:(NSString * _Nonnull)sourceAddress data:(NSData * _Nonnull)data {
self = [super init];
if (self != nil) {
_sourceAddress = sourceAddress;
_data = data;
}
return self;
}
@end
using tonlib_api::make_object;
@interface TONReceiveThreadParams : NSObject
@ -752,6 +766,7 @@ typedef enum {
std::vector<tonlib_api::object_ptr<tonlib_api::msg_message> > inputMessages;
inputMessages.push_back(make_object<tonlib_api::msg_message>(
make_object<tonlib_api::accountAddress>(address.UTF8String),
makeString([NSData data]),
amount,
tonlib_api::move_object_as<tonlib_api::msg_Data>(inputMessageData)
));
@ -812,6 +827,7 @@ typedef enum {
std::vector<tonlib_api::object_ptr<tonlib_api::msg_message> > inputMessages;
inputMessages.push_back(make_object<tonlib_api::msg_message>(
make_object<tonlib_api::accountAddress>(address.UTF8String),
makeString([NSData data]),
amount,
tonlib_api::move_object_as<tonlib_api::msg_Data>(inputMessageData)
));
@ -1093,7 +1109,7 @@ typedef enum {
}] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]];
}
- (SSignal *)decryptMessagesWithKey:(TONKey * _Nonnull)key localPassword:(NSData * _Nonnull)localPassword messages:(NSArray<NSData *> * _Nonnull)messages {
- (SSignal *)decryptMessagesWithKey:(TONKey * _Nonnull)key localPassword:(NSData * _Nonnull)localPassword messages:(NSArray<TONEncryptedData *> * _Nonnull)messages {
return [[[[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) {
NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding];
if (publicKeyData == nil) {
@ -1108,24 +1124,24 @@ typedef enum {
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::msg_dataArray::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::msg_dataArray>(object);
} else if (object->get_id() == tonlib_api::msg_dataDecryptedArray::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::msg_dataDecryptedArray>(object);
if (result->elements_.size() != messages.count) {
[subscriber putError:[[TONError alloc] initWithText:@"API interaction error"]];
} else {
NSMutableArray<id<TONTransactionMessageContents> > *resultMessages = [[NSMutableArray alloc] init];
int index = 0;
for (auto &it : result->elements_) {
if (it->get_id() == tonlib_api::msg_dataDecryptedText::ID) {
auto dataDecryptedText = tonlib_api::move_object_as<tonlib_api::msg_dataDecryptedText>(it);
if (it->data_->get_id() == tonlib_api::msg_dataDecryptedText::ID) {
auto dataDecryptedText = tonlib_api::move_object_as<tonlib_api::msg_dataDecryptedText>(it->data_);
NSString *decryptedString = readString(dataDecryptedText->text_);
if (decryptedString != nil) {
[resultMessages addObject:[[TONTransactionMessageContentsPlainText alloc] initWithText:decryptedString]];
} else {
[resultMessages addObject:[[TONTransactionMessageContentsEncryptedText alloc] initWithData:messages[index]]];
[resultMessages addObject:[[TONTransactionMessageContentsEncryptedText alloc] initWithEncryptedData:messages[index]]];
}
} else {
[resultMessages addObject:[[TONTransactionMessageContentsEncryptedText alloc] initWithData:messages[index]]];
[resultMessages addObject:[[TONTransactionMessageContentsEncryptedText alloc] initWithEncryptedData:messages[index]]];
}
index++;
}
@ -1137,10 +1153,20 @@ typedef enum {
}
}];
std::vector<tonlib_api::object_ptr<tonlib_api::msg_Data>> inputData;
for (NSData *message in messages) {
inputData.push_back(make_object<tonlib_api::msg_dataEncryptedText>(
makeString(message)
std::vector<tonlib_api::object_ptr<tonlib_api::msg_dataEncrypted>> inputData;
for (TONEncryptedData *message in messages) {
NSData *sourceAddressData = [message.sourceAddress dataUsingEncoding:NSUTF8StringEncoding];
if (sourceAddressData == nil) {
continue;
}
inputData.push_back(make_object<tonlib_api::msg_dataEncrypted>(
make_object<tonlib_api::accountAddress>(
makeString(sourceAddressData)
),
make_object<tonlib_api::msg_dataEncryptedText>(
makeString(message.data)
)
));
}
@ -1152,7 +1178,7 @@ typedef enum {
),
makeSecureString(localPassword)
),
make_object<tonlib_api::msg_dataArray>(
make_object<tonlib_api::msg_dataEncryptedArray>(
std::move(inputData)
)
);

View File

@ -196,7 +196,7 @@ public final class TonInstance {
assertionFailure()
return
}
let cancel = keychain.encrypt(key.secret).start(next: { encryptedSecretData in
let _ = keychain.encrypt(key.secret).start(next: { encryptedSecretData in
let _ = self.exportKey(key: key, localPassword: localPassword).start(next: { wordList in
subscriber.putNext((WalletInfo(publicKey: WalletPublicKey(rawValue: key.publicKey), encryptedSecret: encryptedSecretData), wordList))
subscriber.putCompletion()
@ -231,7 +231,7 @@ public final class TonInstance {
subscriber.putError(.generic)
return
}
let cancel = keychain.encrypt(key.secret).start(next: { encryptedSecretData in
let _ = keychain.encrypt(key.secret).start(next: { encryptedSecretData in
subscriber.putNext(WalletInfo(publicKey: WalletPublicKey(rawValue: key.publicKey), encryptedSecret: encryptedSecretData))
subscriber.putCompletion()
}, error: { _ in
@ -427,20 +427,22 @@ public final class TonInstance {
}
}
fileprivate func decryptWalletTransactions(decryptionKey: WalletTransactionDecryptionKey, encryptedMessages: [Data]) -> Signal<[WalletTransactionMessageContents], DecryptWalletTransactionsError> {
fileprivate func decryptWalletTransactions(decryptionKey: WalletTransactionDecryptionKey, encryptedMessages: [WalletTransactionEncryptedMessageData]) -> Signal<[WalletTransactionMessageContents], DecryptWalletTransactionsError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
impl.withInstance { ton in
let cancel = ton.decryptMessages(with: TONKey(publicKey: decryptionKey.walletInfo.publicKey.rawValue, secret: decryptionKey.decryptedSecret), localPassword: decryptionKey.localPassword, messages: encryptedMessages).start(next: { result in
let cancel = ton.decryptMessages(with: TONKey(publicKey: decryptionKey.walletInfo.publicKey.rawValue, secret: decryptionKey.decryptedSecret), localPassword: decryptionKey.localPassword, messages: encryptedMessages.map { data in
TONEncryptedData(sourceAddress: data.sourceAddress, data: data.data)
}).start(next: { result in
guard let result = result as? [TONTransactionMessageContents] else {
subscriber.putError(.generic)
return
}
subscriber.putNext(result.map(WalletTransactionMessageContents.init(tonTransactionMessageContents:)))
}, error: { error in
if let error = error as? TONError {
if let _ = error as? TONError {
subscriber.putError(.generic)
} else {
subscriber.putError(.generic)
@ -735,7 +737,7 @@ public struct CombinedWalletState: Codable, Equatable {
return CombinedWalletState(
walletState: self.walletState,
timestamp: self.timestamp,
topTransactions: self.topTransactions,
topTransactions: topTransactions,
pendingTransactions: self.pendingTransactions
)
}
@ -1093,7 +1095,6 @@ public func sendGramsFromWallet(storage: WalletStorageInterface, tonInstance: To
}
})
|> 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: comment)))
|> mapToSignal { result in
@ -1134,16 +1135,26 @@ public enum WalletTransactionMessageContentsDecodingError: Error {
case generic
}
public struct WalletTransactionEncryptedMessageData: Codable, Equatable {
public let sourceAddress: String
public let data: Data
public init(sourceAddress: String, data: Data) {
self.sourceAddress = sourceAddress
self.data = data
}
}
public enum WalletTransactionMessageContents: Codable, Equatable {
enum Key: CodingKey {
case raw
case plainText
case encryptedText
case encryptedData
}
case raw(Data)
case plainText(String)
case encryptedText(Data)
case encryptedText(WalletTransactionEncryptedMessageData)
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Key.self)
@ -1151,22 +1162,22 @@ public enum WalletTransactionMessageContents: Codable, Equatable {
self = .raw(data)
} else if let plainText = try? container.decode(String.self, forKey: .plainText) {
self = .plainText(plainText)
} else if let encryptedText = try? container.decode(Data.self, forKey: .encryptedText) {
self = .encryptedText(encryptedText)
} else if let encryptedData = try? container.decode(WalletTransactionEncryptedMessageData.self, forKey: .encryptedData) {
self = .encryptedText(encryptedData)
} else {
throw WalletTransactionMessageContentsDecodingError.generic
}
}
public func encode(to encoder: Encoder) throws {
var container = try encoder.container(keyedBy: Key.self)
var container = encoder.container(keyedBy: Key.self)
switch self {
case let .raw(data):
try container.encode(data, forKey: .raw)
case let .plainText(text):
try container.encode(text, forKey: .plainText)
case let .encryptedText(data):
try container.encode(data, forKey: .encryptedText)
try container.encode(data, forKey: .encryptedData)
}
}
}
@ -1178,7 +1189,7 @@ private extension WalletTransactionMessageContents {
} else if let plainText = tonTransactionMessageContents as? TONTransactionMessageContentsPlainText {
self = .plainText(plainText.text)
} else if let encryptedText = tonTransactionMessageContents as? TONTransactionMessageContentsEncryptedText {
self = .encryptedText(encryptedText.data)
self = .encryptedText(WalletTransactionEncryptedMessageData(sourceAddress: encryptedText.encryptedData.sourceAddress, data: encryptedText.encryptedData.data))
} else {
self = .raw(Data())
}
@ -1383,7 +1394,7 @@ public func decryptWalletTransactions(decryptionKey: WalletTransactionDecryption
case inMessage
case outMessage(Int)
}
var encryptedMessages: [(Int, EncryptedMessagePath, Data)] = []
var encryptedMessages: [(Int, EncryptedMessagePath, WalletTransactionEncryptedMessageData)] = []
for i in 0 ..< transactions.count {
if let inMessage = transactions[i].inMessage {
switch inMessage.contents {
@ -1506,7 +1517,7 @@ private func getWalletTransactionsOnce(address: String, previousId: WalletTransa
case inMessage
case outMessage(Int)
}
var encryptedMessages: [(Int, EncryptedMessagePath, Data)] = []
var encryptedMessages: [(Int, EncryptedMessagePath, WalletTransactionEncryptedMessageData)] = []
for i in 0 ..< transactions.count {
if let inMessage = transactions[i].inMessage {
switch inMessage.contents {
@ -1591,7 +1602,7 @@ public enum LocalWalletConfigurationSource: Codable, Equatable {
}
public func encode(to encoder: Encoder) throws {
var container = try encoder.container(keyedBy: Key.self)
var container = encoder.container(keyedBy: Key.self)
switch self {
case let .url(url):
try container.encode(url, forKey: .url)

View File

@ -20,6 +20,10 @@ swift_library(
srcs = glob([
"Sources/**/*.swift",
]),
data = [
":WalletUIResources",
":WalletUIAssets",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",

View File

@ -182,16 +182,8 @@ class ItemListMultilineTextItemNode: ListViewItemNode {
}
var baseFont = titleFont
var linkFont = titleFont
var boldFont = titleBoldFont
var italicFont = titleItalicFont
var boldItalicFont = titleBoldItalicFont
if case .monospace = item.font {
baseFont = Font.monospace(17.0)
linkFont = Font.monospace(17.0)
boldFont = Font.semiboldMonospace(17.0)
italicFont = Font.italicMonospace(17.0)
boldItalicFont = Font.semiboldItalicMonospace(17.0)
}
let string = NSAttributedString(string: item.text, font: baseFont, textColor: textColor)
@ -365,7 +357,7 @@ class ItemListMultilineTextItemNode: ListViewItemNode {
private func linkItemAtPoint(_ point: CGPoint) -> String? {
let textNodeFrame = self.textNode.frame
if let (_, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
if let (_, _) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
return nil
}
return nil

View File

@ -182,7 +182,6 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
}
let leftInset: CGFloat = 16.0 + params.leftInset
var rightInset: CGFloat = 16.0 + params.rightInset
let separatorHeight = UIScreenPixel

View File

@ -108,7 +108,7 @@ private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
})
case let .modeInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
case let .configUrl(theme, strings, placeholder, text):
case let .configUrl(theme, _, placeholder, text):
return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: nil, sectionId: self.section, style: .blocks, capitalization: false, autocorrection: false, returnKeyType: .done, minimalHeight: nil, textUpdated: { value in
arguments.updateState { state in
var state = state
@ -211,12 +211,9 @@ func walletConfigurationScreen(context: WalletContext, currentConfiguration: Loc
}
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushImpl: ((ViewController) -> Void)?
var dismissImpl: (() -> Void)?
var dismissInputImpl: (() -> Void)?
var ensureItemVisibleImpl: ((WalletConfigurationScreenEntryTag, Bool) -> Void)?
weak var currentStatusController: ViewController?
let arguments = WalletConfigurationScreenArguments(updateState: { f in
updateState(f)
}, dismissInput: {
@ -237,9 +234,6 @@ func walletConfigurationScreen(context: WalletContext, currentConfiguration: Loc
let signal = combineLatest(queue: .mainQueue(), .single(context.presentationData), statePromise.get())
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Wallet_Navigation_Cancel), style: .regular, enabled: true, action: {
dismissImpl?()
})
let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Wallet_Configuration_Apply), style: .bold, enabled: !state.isEmpty, action: {
let state = stateValue.with { $0 }
let source: LocalWalletConfigurationSource
@ -346,9 +340,6 @@ func walletConfigurationScreen(context: WalletContext, currentConfiguration: Loc
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}
pushImpl = { [weak controller] c in
controller?.push(c)
}
dismissImpl = { [weak controller] in
controller?.view.endEditing(true)
let _ = controller?.dismiss()
@ -356,26 +347,5 @@ func walletConfigurationScreen(context: WalletContext, currentConfiguration: Loc
dismissInputImpl = { [weak controller] in
controller?.view.endEditing(true)
}
ensureItemVisibleImpl = { [weak controller] targetTag, animated in
controller?.afterLayout({
guard let controller = controller else {
return
}
var resultItemNode: ListViewItemNode?
let state = stateValue.with({ $0 })
let _ = controller.frameForItemNode({ itemNode in
if let itemNode = itemNode as? ItemListItemNode {
if let tag = itemNode.tag, tag.isEqual(to: targetTag) {
resultItemNode = itemNode as? ListViewItemNode
return true
}
}
return false
})
if let resultItemNode = resultItemNode {
controller.ensureItemNodeVisible(resultItemNode, animated: animated)
}
})
}
return controller
}

View File

@ -142,7 +142,7 @@ private enum WalletCreateInvoiceScreenEntry: ItemListNodeEntry {
arguments.updateText(WalletCreateInvoiceScreenEntryTag.comment, text)
}, shouldUpdateText: { text in
let textLength: Int = text.data(using: .utf8, allowLossyConversion: true)?.count ?? 0
return text.count <= walletTextLimit
return textLength <= walletTextLimit
}, updatedFocus: { focus in
arguments.updateState { state in
var state = state
@ -171,7 +171,7 @@ private struct WalletCreateInvoiceScreenState: Equatable {
private func walletCreateInvoiceScreenEntries(presentationData: WalletPresentationData, address: String, state: WalletCreateInvoiceScreenState) -> [WalletCreateInvoiceScreenEntry] {
var entries: [WalletCreateInvoiceScreenEntry] = []
entries.append(.amount(presentationData.theme, state.amount ?? ""))
entries.append(.amount(presentationData.theme, state.amount))
entries.append(.amountInfo(presentationData.theme, presentationData.strings.Wallet_Receive_CreateInvoiceInfo))
entries.append(.commentHeader(presentationData.theme, presentationData.strings.Wallet_Receive_CommentHeader))
entries.append(.comment(presentationData.theme, presentationData.strings.Wallet_Receive_CommentInfo, state.comment))
@ -196,13 +196,10 @@ func walletCreateInvoiceScreen(context: WalletContext, address: String) -> ViewC
statePromise.set(stateValue.modify { f($0) })
}
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushImpl: ((ViewController) -> Void)?
var dismissImpl: (() -> Void)?
var dismissInputImpl: (() -> Void)?
var ensureItemVisibleImpl: ((WalletCreateInvoiceScreenEntryTag, Bool) -> Void)?
weak var currentStatusController: ViewController?
let arguments = WalletCreateInvoiceScreenArguments(context: context, updateState: { f in
updateState(f)
}, updateText: { tag, value in
@ -250,16 +247,9 @@ func walletCreateInvoiceScreen(context: WalletContext, address: String) -> ViewC
return state
}
}
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}
pushImpl = { [weak controller] c in
controller?.push(c)
}
dismissImpl = { [weak controller] in
controller?.view.endEditing(true)
let _ = controller?.dismiss()
}
dismissInputImpl = { [weak controller] in
controller?.view.endEditing(true)
}
@ -269,7 +259,6 @@ func walletCreateInvoiceScreen(context: WalletContext, address: String) -> ViewC
return
}
var resultItemNode: ListViewItemNode?
let state = stateValue.with({ $0 })
let _ = controller.frameForItemNode({ itemNode in
if let itemNode = itemNode as? ItemListItemNode {
if let tag = itemNode.tag, tag.isEqual(to: targetTag) {

View File

@ -89,7 +89,7 @@ final class WalletInfoEmptyItemNode: ListViewItemNode {
super.didLoad()
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
recognizer.tapActionAtPoint = { [weak self] point in
recognizer.tapActionAtPoint = { point in
return .waitForSingleTap
}
self.addressNode.view.addGestureRecognizer(recognizer)
@ -98,7 +98,7 @@ final class WalletInfoEmptyItemNode: ListViewItemNode {
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
switch recognizer.state {
case .ended:
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation {
switch gesture {
case .longTap:
self.item?.displayAddressContextMenu(self, self.addressNode.frame)
@ -129,7 +129,7 @@ final class WalletInfoEmptyItemNode: ListViewItemNode {
let contentVerticalOrigin: CGFloat = 10.0
let sideInset: CGFloat = 16.0
var iconOffset = CGPoint()
let iconOffset = CGPoint()
let title = item.strings.Wallet_Info_WalletCreated
let text = item.strings.Wallet_Info_Address

View File

@ -122,7 +122,7 @@ public final class WalletInfoScreen: ViewController {
strongSelf.push(walletSendScreen(context: strongSelf.context, randomId: randomId, walletInfo: walletInfo))
}
}, receiveAction: { [weak self] in
guard let strongSelf = self, let walletInfo = strongSelf.walletInfo else {
guard let strongSelf = self, let _ = strongSelf.walletInfo else {
return
}
strongSelf.push(WalletReceiveScreen(context: strongSelf.context, mode: .receive(address: strongSelf.address)))
@ -221,7 +221,6 @@ final class WalletInfoBalanceNode: ASDisplayNode {
let balanceIntegralTextFrame = CGRect(origin: balanceOrigin, size: balanceIntegralTextSize)
let apparentBalanceIntegralTextFrame = CGRect(origin: balanceIntegralTextFrame.origin, size: CGSize(width: balanceIntegralTextFrame.width * integralScale, height: balanceIntegralTextFrame.height * integralScale))
var balanceFractionalTextFrame = CGRect(origin: CGPoint(x: balanceIntegralTextFrame.maxX, y: balanceIntegralTextFrame.maxY - balanceFractionalTextSize.height), size: balanceFractionalTextSize)
let apparentBalanceFractionalTextFrame = CGRect(origin: balanceFractionalTextFrame.origin, size: CGSize(width: balanceFractionalTextFrame.width * fractionalScale, height: balanceFractionalTextFrame.height * fractionalScale))
balanceFractionalTextFrame.origin.x -= (balanceFractionalTextFrame.width / 4.0) * scaleTransition + 0.25 * (balanceFractionalTextFrame.width / 2.0) * (1.0 - scaleTransition)
balanceFractionalTextFrame.origin.y += balanceFractionalTextFrame.height * 0.5 * (0.8 - fractionalScale)
@ -332,21 +331,9 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
func update(size: CGSize, navigationHeight: CGFloat, offset: CGFloat, transition: ContainedViewLayoutTransition, isScrolling: Bool) {
let sideInset: CGFloat = 16.0
let buttonSideInset: CGFloat = 48.0
let titleSpacing: CGFloat = 10.0
let termsSpacing: CGFloat = 10.0
let buttonHeight: CGFloat = 50.0
let balanceSubtitleSpacing: CGFloat = 0.0
let alphaTransition: ContainedViewLayoutTransition
if transition.isAnimated {
alphaTransition = transition
} else if isScrolling {
alphaTransition = .animated(duration: 0.2, curve: .easeInOut)
} else {
alphaTransition = transition
}
let minOffset = navigationHeight
let maxOffset = size.height
@ -438,11 +425,11 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
transition.updateAlpha(node: self.receiveGramsButtonNode, alpha: buttonAlpha, beginWithCurrentState: true)
transition.updateFrame(node: self.receiveButtonNode, frame: leftButtonFrame)
transition.updateAlpha(node: self.receiveButtonNode, alpha: buttonAlpha, beginWithCurrentState: true)
self.receiveGramsButtonNode.updateLayout(width: fullButtonFrame.width, transition: transition)
self.receiveButtonNode.updateLayout(width: leftButtonFrame.width, transition: transition)
let _ = self.receiveGramsButtonNode.updateLayout(width: fullButtonFrame.width, transition: transition)
let _ = self.receiveButtonNode.updateLayout(width: leftButtonFrame.width, transition: transition)
transition.updateFrame(node: self.sendButtonNode, frame: sendButtonFrame)
transition.updateAlpha(node: self.sendButtonNode, alpha: buttonAlpha, beginWithCurrentState: true)
self.sendButtonNode.updateLayout(width: sendButtonFrame.width, transition: transition)
let _ = self.sendButtonNode.updateLayout(width: sendButtonFrame.width, transition: transition)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
@ -610,6 +597,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
self.listNode.isHidden = false
self.listNode.view.disablesInteractiveModalDismiss = true
//self.listNode.keepMinimalScrollHeightWithTopInset = 0.0
super.init()
@ -628,7 +616,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
}
self.listNode.updateFloatingHeaderOffset = { [weak self] offset, listTransition in
guard let strongSelf = self, let (layout, navigationHeight) = strongSelf.validLayout else {
guard let strongSelf = self, let (_, navigationHeight) = strongSelf.validLayout else {
return
}
@ -662,7 +650,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.listNode.didEndScrolling = { [weak self] in
canBeginRefresh = true
guard let strongSelf = self, let (_, navigationHeight) = strongSelf.validLayout else {
guard let strongSelf = self, let (_, _) = strongSelf.validLayout else {
return
}
switch strongSelf.listNode.visibleContentOffset() {
@ -765,7 +753,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
return
}
strongSelf.headerNode.refreshNode.refreshProgress = progress
if strongSelf.headerNode.isRefreshing, strongSelf.isReady, let (layout, navigationHeight) = strongSelf.validLayout {
if strongSelf.headerNode.isRefreshing, strongSelf.isReady, let (_, _) = strongSelf.validLayout {
strongSelf.headerNode.refreshNode.update(state: .refreshing)
}
})
@ -951,7 +939,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
strongSelf.headerNode.timestamp = Int32(clamping: combinedState.timestamp)
}
if strongSelf.isReady, let (layout, navigationHeight) = strongSelf.validLayout {
if strongSelf.isReady, let (_, navigationHeight) = strongSelf.validLayout {
strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: strongSelf.listOffset ?? 0.0, transition: .immediate, isScrolling: false)
}
@ -960,7 +948,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
strongSelf.headerNode.isRefreshing = false
if strongSelf.isReady, let (layout, navigationHeight) = strongSelf.validLayout {
if strongSelf.isReady, let (_, navigationHeight) = strongSelf.validLayout {
strongSelf.headerNode.update(size: strongSelf.headerNode.bounds.size, navigationHeight: navigationHeight, offset: strongSelf.listOffset ?? 0.0, transition: .animated(duration: 0.2, curve: .easeInOut), isScrolling: false)
}
@ -999,7 +987,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.headerNode.timestamp = Int32(clamping: combinedState.timestamp)
if self.isReady, let (layout, navigationHeight) = self.validLayout {
if self.isReady, let (_, navigationHeight) = self.validLayout {
self.headerNode.update(size: self.headerNode.bounds.size, navigationHeight: navigationHeight, offset: self.listOffset ?? 0.0, transition: .immediate, isScrolling: false)
}
@ -1033,7 +1021,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.headerNode.isRefreshing = false
}
if self.isReady, let (layout, navigationHeight) = self.validLayout {
if self.isReady, let (_, navigationHeight) = self.validLayout {
self.headerNode.update(size: self.headerNode.bounds.size, navigationHeight: navigationHeight, offset: self.listOffset ?? 0.0, transition: .animated(duration: 0.2, curve: .easeInOut), isScrolling: false)
}
} else {
@ -1090,10 +1078,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
return
}
strongSelf.transactionsLoaded(isReload: false, isEmpty: false, transactions: transactions, pendingTransactions: [])
}, error: { [weak self] _ in
guard let strongSelf = self else {
return
}
}, error: { _ in
}))
}
@ -1133,7 +1118,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
var existingIds = Set<WalletInfoListEntryId>()
for entry in updatedEntries {
switch entry {
case let .transaction(_, transaction):
case .transaction:
existingIds.insert(entry.stableId)
case .empty:
break
@ -1152,7 +1137,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
self.replaceEntries(updatedEntries)
if !self.transactionDecryptionKeyRequested {
if !self.transactionDecryptionKeyRequested && false {
var encryptedTransactions: [WalletTransactionId: WalletTransaction] = [:]
for entry in updatedEntries {
switch entry {
@ -1233,7 +1218,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
}
private func dequeueTransaction() {
guard let layout = self.validLayout, let transaction = self.enqueuedTransactions.first else {
guard let _ = self.validLayout, let transaction = self.enqueuedTransactions.first else {
return
}

View File

@ -98,6 +98,7 @@ class WalletInfoTransactionItem: ListViewItem {
private let titleFont = Font.medium(17.0)
private let textFont = Font.monospace(15.0)
private let descriptionFont = Font.regular(15.0)
private let descriptionMonospaceFont = Font.monospace(15.0)
private let dateFont = Font.regular(14.0)
private let directionFont = Font.regular(15.0)
@ -222,6 +223,7 @@ class WalletInfoTransactionItemNode: ListViewItemNode {
}
var text: String = ""
var description: String = ""
var descriptionIsMonospace = false
if transferredValue <= 0 {
sign = ""
title = "\(formatBalanceText(-transferredValue, decimalSeparator: item.dateTimeFormat.decimalSeparator))"
@ -246,7 +248,8 @@ class WalletInfoTransactionItemNode: ListViewItemNode {
case .raw:
break
case .encryptedText:
description.append("<encrypted>")
description.append("Encrypted Comment")
descriptionIsMonospace = true
case let .plainText(text):
description.append(text)
}
@ -279,7 +282,8 @@ class WalletInfoTransactionItemNode: ListViewItemNode {
case .raw:
description = ""
case .encryptedText:
description = "<encrypted>"
description = "Encrypted Comment"
descriptionIsMonospace = true
case let .plainText(text):
description = text
}
@ -326,7 +330,7 @@ class WalletInfoTransactionItemNode: ListViewItemNode {
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: textFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (descriptionLayout, descriptionApply) = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: description, font: descriptionFont, textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (descriptionLayout, descriptionApply) = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: description, font: descriptionIsMonospace ? descriptionMonospaceFont : descriptionFont, textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (feesLayout, feesApply) = makeFeesLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: feeText, font: descriptionFont, textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))

View File

@ -18,7 +18,7 @@ private func generateFrameImage() -> UIImage? {
context.setLineWidth(4.0)
context.setLineCap(.round)
var path = CGMutablePath();
let path = CGMutablePath()
path.move(to: CGPoint(x: 2.0, y: 2.0 + 26.0))
path.addArc(tangent1End: CGPoint(x: 2.0, y: 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: 2.0), radius: 6.0)
path.addLine(to: CGPoint(x: 2.0 + 26.0, y: 2.0))

View File

@ -232,15 +232,14 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
}
let textFont = Font.regular(16.0)
let textColor = self.presentationData.theme.list.itemPrimaryTextColor
let secondaryTextColor = self.presentationData.theme.list.itemSecondaryTextColor
let url = urlForMode(self.mode)
switch self.mode {
case let .receive(address):
case .receive:
self.textNode.attributedText = NSAttributedString(string: self.presentationData.strings.Wallet_Receive_ShareUrlInfo, font: textFont, textColor: secondaryTextColor)
self.buttonNode.title = self.presentationData.strings.Wallet_Receive_ShareAddress
self.secondaryButtonNode.setTitle(self.presentationData.strings.Wallet_Receive_CreateInvoice, with: Font.regular(17.0), with: self.presentationData.theme.list.itemAccentColor, for: .normal)
case let .invoice(address, amount, comment):
case .invoice:
self.textNode.attributedText = NSAttributedString(string: self.presentationData.strings.Wallet_Receive_ShareUrlInfo, font: textFont, textColor: secondaryTextColor, paragraphAlignment: .center)
self.buttonNode.title = self.presentationData.strings.Wallet_Receive_ShareInvoiceUrl
}
@ -255,7 +254,7 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
super.didLoad()
let addressGestureRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapAddressGesture(_:)))
addressGestureRecognizer.tapActionAtPoint = { [weak self] point in
addressGestureRecognizer.tapActionAtPoint = { point in
return .waitForSingleTap
}
self.urlTextNode.view.addGestureRecognizer(addressGestureRecognizer)
@ -264,7 +263,7 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
@objc func tapLongTapOrDoubleTapAddressGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
switch recognizer.state {
case .ended:
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation {
switch gesture {
case .longTap:
self.displayCopyContextMenu?(self, self.urlTextNode.frame, urlForMode(self.mode))
@ -299,7 +298,7 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
let makeImageLayout = self.qrImageNode.asyncLayout()
let imageSide: CGFloat = 215.0
var imageSize = CGSize(width: imageSide, height: imageSide)
let imageSize = CGSize(width: imageSide, height: imageSide)
let imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: nil))
let _ = imageApply()
@ -353,6 +352,6 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
let buttonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonWidth) / 2.0), y: layout.size.height - bottomInset - buttonHeight + buttonOffset), size: CGSize(width: buttonWidth, height: buttonHeight))
transition.updateFrame(node: self.buttonNode, frame: buttonFrame)
self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
let _ = self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
}
}

View File

@ -93,12 +93,7 @@ private func lastUpdateTimestampString(strings: WalletStrings, dateTimeFormat: W
if dayDifference == 0 || dayDifference == -1 {
let day: RelativeTimestampFormatDay
if dayDifference == 0 {
if expanded {
day = .today
} else {
let minutes = difference / (60 * 60)
return strings.Wallet_Updated_HoursAgo(minutes)
}
day = .today
} else {
day = .yesterday
}
@ -226,13 +221,10 @@ final class WalletRefreshNode: ASDisplayNode {
let previousState = self.state
self.state = state
var pullProgress: CGFloat = 0.0
let title: String
switch state {
case let .pullToRefresh(ts, progress):
case let .pullToRefresh(ts, _):
title = lastUpdateTimestampString(strings: self.strings, dateTimeFormat: dateTimeFormat, statusTimestamp: ts, relativeTo: Int32(Date().timeIntervalSince1970))
pullProgress = progress
case .refreshing:
if ignoreProgressValue {
title = self.strings.Wallet_Info_Updating

View File

@ -64,7 +64,7 @@ private enum WalletSendScreenEntry: ItemListNodeEntry {
case addressInfo(WalletTheme, String)
case commentHeader(WalletTheme, String)
case comment(WalletTheme, String, String, Bool)
case commendEncryption(WalletTheme, String, Bool)
case commentEncryption(WalletTheme, String, Bool)
var section: ItemListSectionId {
switch self {
@ -72,7 +72,7 @@ private enum WalletSendScreenEntry: ItemListNodeEntry {
return WalletSendScreenSection.amount.rawValue
case .addressHeader, .address, .addressInfo:
return WalletSendScreenSection.address.rawValue
case .commentHeader, .comment, .commendEncryption:
case .commentHeader, .comment, .commentEncryption:
return WalletSendScreenSection.comment.rawValue
}
}
@ -93,7 +93,7 @@ private enum WalletSendScreenEntry: ItemListNodeEntry {
return 5
case .comment:
return 6
case .commendEncryption:
case .commentEncryption:
return 7
}
}
@ -142,8 +142,8 @@ private enum WalletSendScreenEntry: ItemListNodeEntry {
} else {
return false
}
case let .commendEncryption(lhsTheme, lhsText, lhsValue):
if case let .commendEncryption(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsText == rhsText {
case let .commentEncryption(lhsTheme, lhsText, lhsValue):
if case let .commentEncryption(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
@ -268,7 +268,7 @@ private enum WalletSendScreenEntry: ItemListNodeEntry {
arguments.proceed()
}
})
case let .commendEncryption(theme, text, value):
case let .commentEncryption(theme, text, value):
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
arguments.updateIsEncrypted(value)
})
@ -291,7 +291,7 @@ private func walletSendScreenEntries(presentationData: WalletPresentationData, b
let amount = amountValue(state.amount)
let balance = max(0, balance ?? 0)
entries.append(.amount(presentationData.theme, state.amount ?? ""))
entries.append(.amount(presentationData.theme, state.amount))
entries.append(.balance(presentationData.theme, presentationData.strings.Wallet_Send_Balance("").0, formatBalanceText(balance, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator), balance == 0 || (amount > 0 && balance < amount)))
entries.append(.addressHeader(presentationData.theme, presentationData.strings.Wallet_Send_AddressHeader))
@ -300,7 +300,7 @@ private func walletSendScreenEntries(presentationData: WalletPresentationData, b
entries.append(.commentHeader(presentationData.theme, presentationData.strings.Wallet_Receive_CommentHeader))
entries.append(.comment(presentationData.theme, presentationData.strings.Wallet_Receive_CommentInfo, state.comment, sendEnabled))
entries.append(.commendEncryption(presentationData.theme, presentationData.strings.Wallet_Send_EncryptComment, state.isCommentEncrypted))
entries.append(.commentEncryption(presentationData.theme, presentationData.strings.Wallet_Send_EncryptComment, state.isCommentEncrypted))
return entries
}
@ -478,7 +478,7 @@ public func walletSendScreen(context: WalletContext, randomId: Int64, walletInfo
|> deliverOnMainQueue).start(next: { serverSalt in
if let serverSalt = serverSalt {
if let commentData = state.comment.data(using: .utf8) {
pushImpl?(WalletSplashScreen(context: context, mode: .sending(walletInfo: walletInfo, address: state.address, amount: amount, comment: commentData, encryptComment: state.isCommentEncrypted && !verificationResult.canNotEncryptComment, randomId: randomId, serverSalt: serverSalt), walletCreatedPreloadState: nil))
pushImpl?(WalletSplashScreen(context: context, mode: .sending(WalletSplashModeSending(walletInfo: walletInfo, address: state.address, amount: amount, comment: commentData, encryptComment: state.isCommentEncrypted && !verificationResult.canNotEncryptComment, randomId: randomId, serverSalt: serverSalt)), walletCreatedPreloadState: nil))
}
}
})
@ -624,7 +624,7 @@ public func walletSendScreen(context: WalletContext, randomId: Int64, walletInfo
controller?.push(c)
}
popImpl = { [weak controller] in
(controller?.navigationController as? NavigationController)?.popViewController(animated: true)
let _ = (controller?.navigationController as? NavigationController)?.popViewController(animated: true)
}
dismissImpl = { [weak controller] in
controller?.view.endEditing(true)
@ -658,7 +658,6 @@ public func walletSendScreen(context: WalletContext, randomId: Int64, walletInfo
}
var resultItemNode: ListViewItemNode?
let state = stateValue.with({ $0 })
let _ = controller.frameForItemNode({ itemNode in
if let itemNode = itemNode as? ItemListItemNode {
if let tag = itemNode.tag, tag.isEqual(to: targetTag) {

View File

@ -105,12 +105,7 @@ private func walletSettingsControllerEntries(presentationData: WalletPresentatio
public func walletSettingsController(context: WalletContext, walletInfo: WalletInfo) -> ViewController {
let statePromise = ValuePromise(WalletSettingsControllerState(), ignoreRepeated: true)
let stateValue = Atomic(value: WalletSettingsControllerState())
let updateState: ((WalletSettingsControllerState) -> WalletSettingsControllerState) -> Void = { f in
statePromise.set(stateValue.modify { f($0) })
}
var dismissImpl: (() -> Void)?
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
@ -181,10 +176,6 @@ public func walletSettingsController(context: WalletContext, walletInfo: WalletI
let controller = ItemListController(theme: context.presentationData.theme, strings: context.presentationData.strings, updatedPresentationData: .single((context.presentationData.theme, context.presentationData.strings)), state: signal, tabBarItem: nil)
controller.navigationPresentation = .modal
controller.enableInteractiveDismiss = true
dismissImpl = { [weak controller] in
controller?.view.endEditing(true)
controller?.dismiss()
}
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}

View File

@ -17,12 +17,40 @@ public enum WalletSecureStorageResetReason {
case changed
}
public struct WalletSplashModeSending {
public let walletInfo: WalletInfo
public let address: String
public let amount: Int64
public let comment: Data
public let encryptComment: Bool
public let randomId: Int64
public let serverSalt: Data
public init(
walletInfo: WalletInfo,
address: String,
amount: Int64,
comment: Data,
encryptComment: Bool,
randomId: Int64,
serverSalt: Data
) {
self.walletInfo = walletInfo
self.address = address
self.amount = amount
self.comment = comment
self.encryptComment = encryptComment
self.randomId = randomId
self.serverSalt = serverSalt
}
}
public enum WalletSplashMode {
case intro
case created(walletInfo: WalletInfo, words: [String]?)
case success(walletInfo: WalletInfo)
case restoreFailed
case sending(walletInfo: WalletInfo, address: String, amount: Int64, comment: Data, encryptComment: Bool, randomId: Int64, serverSalt: Data)
case sending(WalletSplashModeSending)
case sent(walletInfo: WalletInfo, amount: Int64)
case secureStorageNotAvailable
case secureStorageReset(WalletSecureStorageResetReason)
@ -81,15 +109,16 @@ public final class WalletSplashScreen: ViewController {
self.navigationBar?.intrinsicCanTransitionInline = false
switch self.mode {
case let .intro: self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Wallet_Intro_ImportExisting, style: .plain, target: self, action: #selector(self.importPressed)), animated: false)
case let .sending(walletInfo, address, amount, comment, encryptComment, randomId, serverSalt):
case .intro:
self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Wallet_Intro_ImportExisting, style: .plain, target: self, action: #selector(self.importPressed)), animated: false)
case let .sending(sending):
self.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: ASDisplayNode())!, animated: false)
let _ = (self.context.keychain.decrypt(walletInfo.encryptedSecret)
let _ = (self.context.keychain.decrypt(sending.walletInfo.encryptedSecret)
|> deliverOnMainQueue).start(next: { [weak self] decryptedSecret in
guard let strongSelf = self else {
return
}
strongSelf.sendGrams(walletInfo: walletInfo, decryptedSecret: decryptedSecret, address: address, amount: amount, comment: comment, encryptComment: encryptComment, forceIfDestinationNotInitialized: true, randomId: randomId, serverSalt: serverSalt)
strongSelf.sendGrams(walletInfo: sending.walletInfo, decryptedSecret: decryptedSecret, address: sending.address, amount: sending.amount, comment: sending.comment, encryptComment: sending.encryptComment, forceIfDestinationNotInitialized: true, randomId: sending.randomId, serverSalt: sending.serverSalt)
}, error: { [weak self] error in
guard let strongSelf = self else {
return
@ -242,7 +271,7 @@ public final class WalletSplashScreen: ViewController {
let controller = textAlertController(alertContext: AlertControllerContext(theme: theme.alert, themeSignal: .single(theme.alert)), title: strongSelf.presentationData.strings.Wallet_Send_UninitializedTitle, text: text, actions: [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Wallet_Navigation_Cancel, action: {
if let navigationController = strongSelf.navigationController as? NavigationController {
navigationController.popViewController(animated: true)
let _ = navigationController.popViewController(animated: true)
}
}),
TextAlertAction(type: .defaultAction, title: "Send Anyway", action: {
@ -258,7 +287,7 @@ public final class WalletSplashScreen: ViewController {
let theme = strongSelf.presentationData.theme
let controller = textAlertController(alertContext: AlertControllerContext(theme: theme.alert, themeSignal: .single(theme.alert)), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Wallet_Alert_OK, action: {
if let navigationController = strongSelf.navigationController as? NavigationController {
navigationController.popViewController(animated: true)
let _ = navigationController.popViewController(animated: true)
}
})])
strongSelf.present(controller, in: .window(.root))
@ -286,14 +315,14 @@ public final class WalletSplashScreen: ViewController {
return true
}
let _ = (walletAddress(publicKey: sending.0.publicKey, tonInstance: self.context.tonInstance)
let _ = (walletAddress(publicKey: sending.walletInfo.publicKey, tonInstance: self.context.tonInstance)
|> deliverOnMainQueue).start(next: { [weak self] address in
guard let strongSelf = self else {
return
}
if !controllers.contains(where: { $0 is WalletInfoScreen }) {
let infoScreen = WalletInfoScreen(context: strongSelf.context, walletInfo: sending.0, address: address, enableDebugActions: false)
let infoScreen = WalletInfoScreen(context: strongSelf.context, walletInfo: sending.walletInfo, address: address, enableDebugActions: false)
infoScreen.navigationPresentation = .modal
controllers.append(infoScreen)
}
@ -498,14 +527,14 @@ public final class WalletSplashScreen: ViewController {
return true
}
let _ = (walletAddress(publicKey: sending.0.publicKey, tonInstance: strongSelf.context.tonInstance)
let _ = (walletAddress(publicKey: sending.walletInfo.publicKey, tonInstance: strongSelf.context.tonInstance)
|> deliverOnMainQueue).start(next: { [weak self] address in
guard let strongSelf = self else {
return
}
if !controllers.contains(where: { $0 is WalletInfoScreen }) {
let infoScreen = WalletInfoScreen(context: strongSelf.context, walletInfo: sending.0, address: address, enableDebugActions: false)
let infoScreen = WalletInfoScreen(context: strongSelf.context, walletInfo: sending.walletInfo, address: address, enableDebugActions: false)
infoScreen.navigationPresentation = .modal
controllers.append(infoScreen)
}
@ -891,7 +920,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
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)
let _ = self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
var maxContentVerticalOrigin = buttonFrame.minY - 12.0 - contentHeight

View File

@ -69,6 +69,33 @@ private func stringForAddress(strings: WalletStrings, address: WalletTransaction
}
}
private extension WalletInfoTransaction {
var isEncrypted: Bool {
switch self {
case .pending:
return false
case let .completed(transaction):
if let inMessage = transaction.inMessage {
switch inMessage.contents {
case .encryptedText:
return true
default:
break
}
}
for message in transaction.outMessages {
switch message.contents {
case .encryptedText:
return true
default:
break
}
}
return false
}
}
}
private func extractAddress(_ walletTransaction: WalletInfoTransaction) -> WalletTransactionAddress {
switch walletTransaction {
case let .completed(walletTransaction):
@ -90,17 +117,17 @@ private func extractAddress(_ walletTransaction: WalletInfoTransaction) -> Walle
return .unknown
}
}
return .none
case let .pending(pending):
return .list([pending.address])
}
}
private func extractDescription(_ walletTransaction: WalletInfoTransaction) -> String {
private func extractDescription(_ walletTransaction: WalletInfoTransaction) -> (string: String, isEncrypted: Bool) {
switch walletTransaction {
case let .completed(walletTransaction):
let transferredValue = walletTransaction.transferredValueWithoutFees
var text = ""
var isEncrypted = false
if transferredValue <= 0 {
for message in walletTransaction.outMessages {
if !text.isEmpty {
@ -110,7 +137,8 @@ private func extractDescription(_ walletTransaction: WalletInfoTransaction) -> S
case .raw:
break
case .encryptedText:
text.append("<encrypted>")
text.append("Encrypted Comment")
isEncrypted = true
case let .plainText(plainText):
text.append(plainText)
}
@ -121,15 +149,16 @@ private func extractDescription(_ walletTransaction: WalletInfoTransaction) -> S
case .raw:
text = ""
case .encryptedText:
text = "<encrypted>"
text = "Encrypted Comment"
isEncrypted = true
case let .plainText(plainText):
text = plainText
}
}
}
return text
return (text, isEncrypted)
case let .pending(pending):
return String(data: pending.comment, encoding: .utf8) ?? ""
return (String(data: pending.comment, encoding: .utf8) ?? "", false)
}
}
@ -160,7 +189,7 @@ private func messageBubbleImage(incoming: Bool, fillColor: UIColor, strokeColor:
final class WalletTransactionInfoScreen: ViewController {
private let context: WalletContext
private let walletInfo: WalletInfo?
private let walletTransaction: WalletInfoTransaction
private var walletTransaction: WalletInfoTransaction
private let walletState: Signal<(CombinedWalletState, Bool), NoError>
private var presentationData: WalletPresentationData
@ -234,6 +263,39 @@ final class WalletTransactionInfoScreen: ViewController {
}
}
}
(self.displayNode as! WalletTransactionInfoScreenNode).requestDecryption = { [weak self] in
guard let strongSelf = self, let walletInfo = strongSelf.walletInfo, case let .completed(walletTransaction) = strongSelf.walletTransaction else {
return
}
let keychain = strongSelf.context.keychain
let _ = (strongSelf.context.getServerSalt()
|> map(Optional.init)
|> `catch` { _ -> Signal<Data?, NoError> in
return .single(nil)
}
|> mapToSignal { serverSalt -> Signal<WalletTransactionDecryptionKey?, NoError> in
guard let serverSalt = serverSalt else {
return .single(nil)
}
return walletTransactionDecryptionKey(keychain: keychain, walletInfo: walletInfo, localPassword: serverSalt)
}
|> deliverOnMainQueue).start(next: { decryptionKey in
guard let strongSelf = self else {
return
}
if let decryptionKey = decryptionKey {
let _ = (decryptWalletTransactions(decryptionKey: decryptionKey, transactions: [walletTransaction], tonInstance: strongSelf.context.tonInstance)
|> deliverOnMainQueue).start(next: { result in
guard let strongSelf = self, let updatedTransaction = result.first else {
return
}
strongSelf.walletTransaction = .completed(updatedTransaction)
(strongSelf.displayNode as! WalletTransactionInfoScreenNode).updateTransaction(strongSelf.walletTransaction)
(strongSelf.navigationController as? NavigationController)?.requestLayout(transition: .immediate)
})
}
})
}
(self.displayNode as! WalletTransactionInfoScreenNode).displayFeesTooltip = { [weak self] node, rect in
guard let strongSelf = self else {
return
@ -255,7 +317,7 @@ final class WalletTransactionInfoScreen: ViewController {
}
}
strongSelf.present(controller, in: .window(.root), with: TooltipControllerPresentationArguments(sourceViewAndRect: {
if let strongSelf = self {
if let _ = self {
return (node.view, rect.insetBy(dx: 0.0, dy: -4.0))
}
return nil
@ -286,7 +348,8 @@ final class WalletTransactionInfoScreen: ViewController {
let minHeight: CGFloat = 424.0
let maxHeight: CGFloat = min(596.0, layout.size.height)
let text = NSAttributedString(string: extractDescription(self.walletTransaction), font: Font.regular(17.0), textColor: .black)
let (plainText, textIsEncrypted) = extractDescription(self.walletTransaction)
let text = NSAttributedString(string: plainText, font: textIsEncrypted ? Font.monospace(17.0) : Font.regular(17.0), textColor: .black)
let makeTextLayout = TextNode.asyncLayout(self.measureTextNode)
let (textLayout, _) = makeTextLayout(TextNodeLayoutArguments(attributedString: text, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: layout.size.width - 36.0 * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@ -296,7 +359,13 @@ final class WalletTransactionInfoScreen: ViewController {
let minOverscroll: CGFloat = 42.0
let maxOverscroll: CGFloat = 148.0
let contentHeight = minHeight + textHeight
var contentHeight = minHeight + textHeight
if textIsEncrypted {
let (decryptTextLayout, _) = TextNode.asyncLayout(nil)(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "Decrypt", font: Font.regular(17.0), textColor: presentationData.theme.list.itemAccentColor), maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: layout.size.width - 40.0, height: .greatestFiniteMagnitude), alignment: .center, insets: UIEdgeInsets()))
contentHeight += 10.0 + decryptTextLayout.size.height + 10.0
}
let difference = contentHeight - maxHeight
if difference < 0.0 {
resultHeight = contentHeight
@ -329,7 +398,7 @@ private let fractionalFont = Font.medium(24.0)
private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate {
private let context: WalletContext
private var presentationData: WalletPresentationData
private let walletTransaction: WalletInfoTransaction
private var walletTransaction: WalletInfoTransaction
private let incoming: Bool
private let titleNode: ImmediateTextNode
@ -345,12 +414,15 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
private let commentBackgroundNode: ASImageNode
private let commentTextNode: ImmediateTextNode
private let commentSeparatorNode: ASDisplayNode
private let commentDecryptButtonTitle: ImmediateTextNode
private let commentDecryptButton: HighlightableButtonNode
private let addressTextNode: ImmediateTextNode
private let buttonNode: SolidRoundedButtonNode
private var validLayout: (ContainerViewLayout, CGFloat)?
var send: ((String) -> Void)?
var requestDecryption: (() -> Void)?
var displayFeesTooltip: ((ASDisplayNode, CGRect) -> Void)?
var displayCopyContextMenu: ((ASDisplayNode, CGRect, String) -> Void)?
@ -401,6 +473,15 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
self.commentSeparatorNode = ASDisplayNode()
self.commentSeparatorNode.backgroundColor = self.presentationData.theme.list.itemPlainSeparatorColor
self.commentDecryptButtonTitle = ImmediateTextNode()
self.commentDecryptButtonTitle.attributedText = NSAttributedString(string: "Decrypt", font: Font.regular(17.0), textColor: presentationData.theme.list.itemAccentColor)
self.commentDecryptButtonTitle.textAlignment = .natural
self.commentDecryptButtonTitle.maximumNumberOfLines = 0
self.commentDecryptButtonTitle.isUserInteractionEnabled = false
self.commentDecryptButton = HighlightableButtonNode()
self.commentDecryptButton.hitTestSlop = UIEdgeInsets(top: -10.0, left: -10.0, bottom: -10.0, right: -10.0)
self.addressTextNode = ImmediateTextNode()
self.addressTextNode.maximumNumberOfLines = 4
self.addressTextNode.textAlignment = .justified
@ -438,8 +519,12 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
self.addSubnode(self.timeNode)
self.addSubnode(self.amountNode)
self.addSubnode(self.commentSeparatorNode)
self.commentDecryptButton.addSubnode(self.commentDecryptButtonTitle)
self.scrollNode.addSubnode(self.commentDecryptButton)
self.addSubnode(self.addressTextNode)
self.addSubnode(self.buttonNode)
self.commentDecryptButton.isHidden = !walletTransaction.isEncrypted
let titleFont = Font.semibold(17.0)
let subtitleFont = Font.regular(13.0)
@ -485,7 +570,8 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
commentBackgroundColor = UIColor(rgb: 0xf1f1f4)
}
self.commentBackgroundNode.image = messageBubbleImage(incoming: transferredValue > 0, fillColor: commentBackgroundColor, strokeColor: presentationData.theme.transaction.descriptionBackgroundColor)
self.commentTextNode.attributedText = NSAttributedString(string: extractDescription(walletTransaction), font: Font.regular(17.0), textColor: presentationData.theme.transaction.descriptionTextColor)
let (plainText, textIsEncrypted) = extractDescription(walletTransaction)
self.commentTextNode.attributedText = NSAttributedString(string: plainText, font: textIsEncrypted ? Font.monospace(17.0) : Font.regular(17.0), textColor: presentationData.theme.transaction.descriptionTextColor)
let address = extractAddress(walletTransaction)
var singleAddress: String?
@ -501,6 +587,21 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
self?.send?(address)
}
}
self.commentDecryptButton.addTarget(self, action: #selector(self.decryptCommentPressed), forControlEvents: .touchUpInside)
}
@objc private func decryptCommentPressed() {
self.requestDecryption?()
}
func updateTransaction(_ walletTransaction: WalletInfoTransaction) {
self.walletTransaction = walletTransaction
let (plainText, textIsEncrypted) = extractDescription(walletTransaction)
self.commentTextNode.attributedText = NSAttributedString(string: plainText, font: textIsEncrypted ? Font.monospace(17.0) : Font.regular(17.0), textColor: presentationData.theme.transaction.descriptionTextColor)
self.commentDecryptButton.isHidden = !walletTransaction.isEncrypted
}
override func didLoad() {
@ -509,15 +610,17 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
self.scrollNode.view.delegate = self
self.scrollNode.view.alwaysBounceVertical = true
self.scrollNode.view.showsVerticalScrollIndicator = false
self.scrollNode.view.delaysContentTouches = false
self.scrollNode.view.canCancelContentTouches = true
let commentGestureRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapCommentGesture(_:)))
commentGestureRecognizer.tapActionAtPoint = { [weak self] point in
commentGestureRecognizer.tapActionAtPoint = { point in
return .waitForSingleTap
}
self.commentBackgroundNode.view.addGestureRecognizer(commentGestureRecognizer)
let addressGestureRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapAddressGesture(_:)))
addressGestureRecognizer.tapActionAtPoint = { [weak self] point in
addressGestureRecognizer.tapActionAtPoint = { point in
return .waitForSingleTap
}
self.addressTextNode.view.addGestureRecognizer(addressGestureRecognizer)
@ -526,10 +629,10 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
@objc func tapLongTapOrDoubleTapCommentGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
switch recognizer.state {
case .ended:
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation {
switch gesture {
case .longTap:
let description = extractDescription(self.walletTransaction)
let (description, _) = extractDescription(self.walletTransaction)
if !description.isEmpty {
self.displayCopyContextMenu?(self, self.commentBackgroundNode.convert(self.commentBackgroundNode.bounds, to: self), description)
}
@ -545,7 +648,7 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
@objc func tapLongTapOrDoubleTapAddressGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
switch recognizer.state {
case .ended:
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation {
switch gesture {
case .longTap:
let address = extractAddress(self.walletTransaction)
@ -668,7 +771,7 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
let buttonHeight: CGFloat = 50.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)
let _ = self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
let addressSize = self.addressTextNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
let addressFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - addressSize.width) / 2.0), y: buttonFrame.minY - addressSize.height - 34.0), size: addressSize)
@ -695,7 +798,18 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
}
transition.updateFrame(node: self.commentBackgroundNode, frame: commentBackgroundFrame)
let contentHeight = commentOrigin.y + commentBackgroundFrame.height
var commentMaxY = commentOrigin.y + commentBackgroundFrame.height
let decryptSize = self.commentDecryptButtonTitle.updateLayout(CGSize(width: layout.size.width - 40.0, height: .greatestFiniteMagnitude))
let decryptButtonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - decryptSize.width) / 2.0), y: commentMaxY + 10.0), size: decryptSize)
transition.updateFrame(node: self.commentDecryptButton, frame: decryptButtonFrame)
transition.updateFrame(node: self.commentDecryptButtonTitle, frame: CGRect(origin: CGPoint(), size: decryptSize))
if self.walletTransaction.isEncrypted {
commentMaxY = decryptButtonFrame.maxY + 10.0
}
let contentHeight = commentMaxY
self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight)
let isScrollEnabled = contentHeight - scrollFrame.height > 20.0

View File

@ -82,7 +82,6 @@ func isValidAmount(_ amount: String) -> Bool {
return false
}
var hasDecimalSeparator = false
var hasLeadingZero = false
var index = 0
for c in amount {
if c == "." || c == "," {

View File

@ -321,11 +321,8 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc
contentHeight = textFrame.maxY + textSpacing
let rowWidth = layout.size.width - buttonSideInset * 2.0
let rowCount = self.wordNodes.count / 2
let indexWidth: CGFloat = 16.0
var wordSizes: [(CGSize, CGSize)] = []
var columnIndexWidth: [CGFloat] = [0.0, 0.0]
var columnWordWidth: [CGFloat] = [0.0, 0.0]
@ -371,16 +368,14 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc
}
}
let minimalFullscreenBottomInset: CGFloat = 74.0
let minimalScrollBottomInset: CGFloat = 30.0
let fullscreenBottomInset = layout.intrinsicInsets.bottom + minimalFullscreenBottomInset
let scrollBottomInset = layout.intrinsicInsets.bottom + minimalScrollBottomInset
let buttonWidth = layout.size.width - buttonSideInset * 2.0
let buttonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonWidth) / 2.0), y: max(contentHeight + buttonSpacing, layout.size.height - scrollBottomInset - buttonHeight)), size: CGSize(width: buttonWidth, height: buttonHeight))
transition.updateFrame(node: self.buttonNode, frame: buttonFrame)
self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
let _ = self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: max(layout.size.height, buttonFrame.maxY + scrollBottomInset))
@ -395,7 +390,7 @@ private final class WalletWordDisplayScreenNode: ViewControllerTracingNode, UISc
if let path = getAppBundle().path(forResource: "WalletApologiesAccepted", ofType: "tgs") {
let toastNode = ToastNode(theme: self.presentationData.theme, animationPath: path, text: self.presentationData.strings.Wallet_Words_NotDoneResponse)
self.toastNode = toastNode
if let (layout, navigationHeight) = self.validLayout {
if let (layout, _) = self.validLayout {
toastNode.update(layout: layout, transition: .immediate)
}
self.addSubnode(toastNode)

View File

@ -1,4 +1,4 @@
load("//build-system:unique_directories.bzl", "unique_directories")
load("//build-system/bazel-utils:unique_directories.bzl", "unique_directories")
private_headers = glob([
"lottie-ios/**/*.h",

View File

@ -48,6 +48,7 @@ set(TON_CRYPTO_SOURCE
common/refint.h
common/bigexp.h
common/util.h
common/linalloc.hpp
ellcurve/Ed25519.h
ellcurve/Fp25519.h
@ -390,7 +391,7 @@ endif()
add_executable(create-state block/create-state.cpp)
target_include_directories(create-state PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block)
target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib)
if (WINGETOPT_FOUND)
target_link_libraries_system(create-state wingetopt)
endif()

View File

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "crypto/Ed25519.h"
@ -310,6 +310,10 @@ Result<SecureString> Ed25519::compute_shared_secret(const PublicKey &public_key,
return std::move(result);
}
int Ed25519::version() {
return OPENSSL_VERSION_NUMBER;
}
#else
Result<Ed25519::PrivateKey> Ed25519::generate_private_key() {
@ -387,6 +391,10 @@ Result<SecureString> Ed25519::compute_shared_secret(const PublicKey &public_key,
return std::move(shared_secret);
}
int Ed25519::version() {
return 0;
}
#endif
} // namespace td

View File

@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
@ -65,6 +65,8 @@ class Ed25519 {
static Result<PrivateKey> generate_private_key();
static Result<SecureString> compute_shared_secret(const PublicKey &public_key, const PrivateKey &private_key);
static int version();
};
} // namespace td

View File

@ -14,6 +14,7 @@
// uses built-in type `uint`
// uses built-in type `bits`
// uses built-in type `int8`
// uses built-in type `uint8`
// uses built-in type `uint13`
// uses built-in type `uint15`
// uses built-in type `int16`
@ -23,6 +24,7 @@
// uses built-in type `uint63`
// uses built-in type `int64`
// uses built-in type `uint64`
// uses built-in type `uint256`
// uses built-in type `int257`
// uses built-in type `bits256`
@ -10686,38 +10688,42 @@ int BlockInfo::check_tag(const vm::CellSlice& cs) const {
}
bool BlockInfo::skip(vm::CellSlice& cs) const {
int not_master, after_merge, vert_seqno_incr, seq_no, vert_seq_no, prev_seq_no;
int not_master, after_merge, vert_seqno_incr, flags, seq_no, vert_seq_no, prev_seq_no;
return cs.advance(64)
&& cs.fetch_bool_to(not_master)
&& cs.fetch_bool_to(after_merge)
&& cs.advance(5)
&& cs.fetch_bool_to(vert_seqno_incr)
&& cs.advance(8)
&& cs.fetch_uint_to(8, flags)
&& flags <= 1
&& cs.fetch_uint_to(32, seq_no)
&& cs.fetch_uint_to(32, vert_seq_no)
&& vert_seqno_incr <= vert_seq_no
&& add_r1(prev_seq_no, 1, seq_no)
&& cs.advance(392)
&& (!(flags & 1) || cs.advance(104))
&& (!not_master || cs.advance_refs(1))
&& cs.advance_refs(1)
&& (!vert_seqno_incr || cs.advance_refs(1));
}
bool BlockInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int not_master, after_merge, vert_seqno_incr, seq_no, vert_seq_no, prev_seq_no;
int not_master, after_merge, vert_seqno_incr, flags, seq_no, vert_seq_no, prev_seq_no;
return cs.fetch_ulong(32) == 0x9bc7a987U
&& cs.advance(32)
&& cs.fetch_bool_to(not_master)
&& cs.fetch_bool_to(after_merge)
&& cs.advance(5)
&& cs.fetch_bool_to(vert_seqno_incr)
&& cs.advance(8)
&& cs.fetch_uint_to(8, flags)
&& flags <= 1
&& cs.fetch_uint_to(32, seq_no)
&& cs.fetch_uint_to(32, vert_seq_no)
&& vert_seqno_incr <= vert_seq_no
&& add_r1(prev_seq_no, 1, seq_no)
&& t_ShardIdent.validate_skip(ops, cs, weak)
&& cs.advance(288)
&& (!(flags & 1) || t_GlobalVersion.validate_skip(ops, cs, weak))
&& (!not_master || t_BlkMasterInfo.validate_skip_ref(ops, cs, weak))
&& BlkPrevInfo{after_merge}.validate_skip_ref(ops, cs, weak)
&& (!vert_seqno_incr || t_BlkPrevInfo_0.validate_skip_ref(ops, cs, weak));
@ -10736,6 +10742,7 @@ bool BlockInfo::unpack(vm::CellSlice& cs, BlockInfo::Record& data) const {
&& cs.fetch_bool_to(data.key_block)
&& cs.fetch_bool_to(data.vert_seqno_incr)
&& cs.fetch_uint_to(8, data.flags)
&& data.flags <= 1
&& cs.fetch_uint_to(32, data.seq_no)
&& cs.fetch_uint_to(32, data.vert_seq_no)
&& data.vert_seqno_incr <= data.vert_seq_no
@ -10748,6 +10755,7 @@ bool BlockInfo::unpack(vm::CellSlice& cs, BlockInfo::Record& data) const {
&& cs.fetch_uint_to(32, data.gen_catchain_seqno)
&& cs.fetch_uint_to(32, data.min_ref_mc_seqno)
&& cs.fetch_uint_to(32, data.prev_key_block_seqno)
&& (!(data.flags & 1) || cs.fetch_subslice_to(104, data.gen_software))
&& (!data.not_master || cs.fetch_ref_to(data.master_ref))
&& cs.fetch_ref_to(data.prev_ref)
&& (!data.vert_seqno_incr || cs.fetch_ref_to(data.prev_vert_ref));
@ -10772,6 +10780,7 @@ bool BlockInfo::pack(vm::CellBuilder& cb, const BlockInfo::Record& data) const {
&& cb.store_ulong_rchk_bool(data.key_block, 1)
&& cb.store_ulong_rchk_bool(data.vert_seqno_incr, 1)
&& cb.store_ulong_rchk_bool(data.flags, 8)
&& data.flags <= 1
&& cb.store_ulong_rchk_bool(data.seq_no, 32)
&& cb.store_ulong_rchk_bool(data.vert_seq_no, 32)
&& data.vert_seqno_incr <= data.vert_seq_no
@ -10784,6 +10793,7 @@ bool BlockInfo::pack(vm::CellBuilder& cb, const BlockInfo::Record& data) const {
&& cb.store_ulong_rchk_bool(data.gen_catchain_seqno, 32)
&& cb.store_ulong_rchk_bool(data.min_ref_mc_seqno, 32)
&& cb.store_ulong_rchk_bool(data.prev_key_block_seqno, 32)
&& (!(data.flags & 1) || cb.append_cellslice_chk(data.gen_software, 104))
&& (!data.not_master || cb.store_ref_bool(data.master_ref))
&& cb.store_ref_bool(data.prev_ref)
&& (!data.vert_seqno_incr || cb.store_ref_bool(data.prev_vert_ref));
@ -10814,6 +10824,7 @@ bool BlockInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
&& pp.field_int(vert_seqno_incr, "vert_seqno_incr")
&& cs.fetch_uint_to(8, flags)
&& pp.field_int(flags, "flags")
&& flags <= 1
&& cs.fetch_uint_to(32, seq_no)
&& pp.field_int(seq_no, "seq_no")
&& cs.fetch_uint_to(32, vert_seq_no)
@ -10829,6 +10840,7 @@ bool BlockInfo::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
&& pp.fetch_uint_field(cs, 32, "gen_catchain_seqno")
&& pp.fetch_uint_field(cs, 32, "min_ref_mc_seqno")
&& pp.fetch_uint_field(cs, 32, "prev_key_block_seqno")
&& (!(flags & 1) || (pp.field("gen_software") && t_GlobalVersion.print_skip(pp, cs)))
&& (!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())
@ -14057,6 +14069,309 @@ bool GlobalVersion::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
const GlobalVersion t_GlobalVersion;
//
// code for type `ConfigProposalSetup`
//
constexpr unsigned char ConfigProposalSetup::cons_tag[1];
int ConfigProposalSetup::check_tag(const vm::CellSlice& cs) const {
return cs.prefetch_ulong(8) == 0x36 ? cfg_vote_cfg : -1;
}
bool ConfigProposalSetup::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(8) == 0x36
&& cs.advance(160);
}
bool ConfigProposalSetup::unpack(vm::CellSlice& cs, ConfigProposalSetup::Record& data) const {
return cs.fetch_ulong(8) == 0x36
&& cs.fetch_uint_to(8, data.min_tot_rounds)
&& cs.fetch_uint_to(8, data.max_tot_rounds)
&& cs.fetch_uint_to(8, data.min_wins)
&& cs.fetch_uint_to(8, data.max_losses)
&& cs.fetch_uint_to(32, data.min_store_sec)
&& cs.fetch_uint_to(32, data.max_store_sec)
&& cs.fetch_uint_to(32, data.bit_price)
&& cs.fetch_uint_to(32, data.cell_price);
}
bool ConfigProposalSetup::cell_unpack(Ref<vm::Cell> cell_ref, ConfigProposalSetup::Record& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ConfigProposalSetup::pack(vm::CellBuilder& cb, const ConfigProposalSetup::Record& data) const {
return cb.store_long_bool(0x36, 8)
&& cb.store_ulong_rchk_bool(data.min_tot_rounds, 8)
&& cb.store_ulong_rchk_bool(data.max_tot_rounds, 8)
&& cb.store_ulong_rchk_bool(data.min_wins, 8)
&& cb.store_ulong_rchk_bool(data.max_losses, 8)
&& cb.store_ulong_rchk_bool(data.min_store_sec, 32)
&& cb.store_ulong_rchk_bool(data.max_store_sec, 32)
&& cb.store_ulong_rchk_bool(data.bit_price, 32)
&& cb.store_ulong_rchk_bool(data.cell_price, 32);
}
bool ConfigProposalSetup::cell_pack(Ref<vm::Cell>& cell_ref, const ConfigProposalSetup::Record& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigProposalSetup::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
return cs.fetch_ulong(8) == 0x36
&& pp.open("cfg_vote_cfg")
&& pp.fetch_uint_field(cs, 8, "min_tot_rounds")
&& pp.fetch_uint_field(cs, 8, "max_tot_rounds")
&& pp.fetch_uint_field(cs, 8, "min_wins")
&& pp.fetch_uint_field(cs, 8, "max_losses")
&& pp.fetch_uint_field(cs, 32, "min_store_sec")
&& pp.fetch_uint_field(cs, 32, "max_store_sec")
&& pp.fetch_uint_field(cs, 32, "bit_price")
&& pp.fetch_uint_field(cs, 32, "cell_price")
&& pp.close();
}
const ConfigProposalSetup t_ConfigProposalSetup;
//
// code for type `ConfigVotingSetup`
//
constexpr unsigned char ConfigVotingSetup::cons_tag[1];
int ConfigVotingSetup::check_tag(const vm::CellSlice& cs) const {
return cs.prefetch_ulong(8) == 0x91 ? cfg_vote_setup : -1;
}
bool ConfigVotingSetup::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(8) == 0x91
&& t_ConfigProposalSetup.validate_skip_ref(ops, cs, weak)
&& t_ConfigProposalSetup.validate_skip_ref(ops, cs, weak);
}
bool ConfigVotingSetup::unpack(vm::CellSlice& cs, ConfigVotingSetup::Record& data) const {
return cs.fetch_ulong(8) == 0x91
&& cs.fetch_ref_to(data.normal_params)
&& cs.fetch_ref_to(data.critical_params);
}
bool ConfigVotingSetup::unpack_cfg_vote_setup(vm::CellSlice& cs, Ref<Cell>& normal_params, Ref<Cell>& critical_params) const {
return cs.fetch_ulong(8) == 0x91
&& cs.fetch_ref_to(normal_params)
&& cs.fetch_ref_to(critical_params);
}
bool ConfigVotingSetup::cell_unpack(Ref<vm::Cell> cell_ref, ConfigVotingSetup::Record& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ConfigVotingSetup::cell_unpack_cfg_vote_setup(Ref<vm::Cell> cell_ref, Ref<Cell>& normal_params, Ref<Cell>& critical_params) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack_cfg_vote_setup(cs, normal_params, critical_params) && cs.empty_ext();
}
bool ConfigVotingSetup::pack(vm::CellBuilder& cb, const ConfigVotingSetup::Record& data) const {
return cb.store_long_bool(0x91, 8)
&& cb.store_ref_bool(data.normal_params)
&& cb.store_ref_bool(data.critical_params);
}
bool ConfigVotingSetup::pack_cfg_vote_setup(vm::CellBuilder& cb, Ref<Cell> normal_params, Ref<Cell> critical_params) const {
return cb.store_long_bool(0x91, 8)
&& cb.store_ref_bool(normal_params)
&& cb.store_ref_bool(critical_params);
}
bool ConfigVotingSetup::cell_pack(Ref<vm::Cell>& cell_ref, const ConfigVotingSetup::Record& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigVotingSetup::cell_pack_cfg_vote_setup(Ref<vm::Cell>& cell_ref, Ref<Cell> normal_params, Ref<Cell> critical_params) const {
vm::CellBuilder cb;
return pack_cfg_vote_setup(cb, std::move(normal_params), std::move(critical_params)) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigVotingSetup::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
return cs.fetch_ulong(8) == 0x91
&& pp.open("cfg_vote_setup")
&& pp.field("normal_params")
&& t_ConfigProposalSetup.print_ref(pp, cs.fetch_ref())
&& pp.field("critical_params")
&& t_ConfigProposalSetup.print_ref(pp, cs.fetch_ref())
&& pp.close();
}
const ConfigVotingSetup t_ConfigVotingSetup;
//
// code for type `ConfigProposal`
//
constexpr unsigned char ConfigProposal::cons_tag[1];
int ConfigProposal::check_tag(const vm::CellSlice& cs) const {
return cs.prefetch_ulong(8) == 0xf3 ? cfg_proposal : -1;
}
bool ConfigProposal::skip(vm::CellSlice& cs) const {
return cs.advance(40)
&& t_Maybe_Ref_Cell.skip(cs)
&& t_Maybe_uint256.skip(cs);
}
bool ConfigProposal::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(8) == 0xf3
&& cs.advance(32)
&& t_Maybe_Ref_Cell.validate_skip(ops, cs, weak)
&& t_Maybe_uint256.validate_skip(ops, cs, weak);
}
bool ConfigProposal::unpack(vm::CellSlice& cs, ConfigProposal::Record& data) const {
return cs.fetch_ulong(8) == 0xf3
&& cs.fetch_int_to(32, data.param_id)
&& t_Maybe_Ref_Cell.fetch_to(cs, data.param_value)
&& t_Maybe_uint256.fetch_to(cs, data.if_hash_equal);
}
bool ConfigProposal::unpack_cfg_proposal(vm::CellSlice& cs, int& param_id, Ref<CellSlice>& param_value, Ref<CellSlice>& if_hash_equal) const {
return cs.fetch_ulong(8) == 0xf3
&& cs.fetch_int_to(32, param_id)
&& t_Maybe_Ref_Cell.fetch_to(cs, param_value)
&& t_Maybe_uint256.fetch_to(cs, if_hash_equal);
}
bool ConfigProposal::cell_unpack(Ref<vm::Cell> cell_ref, ConfigProposal::Record& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ConfigProposal::cell_unpack_cfg_proposal(Ref<vm::Cell> cell_ref, int& param_id, Ref<CellSlice>& param_value, Ref<CellSlice>& if_hash_equal) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack_cfg_proposal(cs, param_id, param_value, if_hash_equal) && cs.empty_ext();
}
bool ConfigProposal::pack(vm::CellBuilder& cb, const ConfigProposal::Record& data) const {
return cb.store_long_bool(0xf3, 8)
&& cb.store_long_rchk_bool(data.param_id, 32)
&& t_Maybe_Ref_Cell.store_from(cb, data.param_value)
&& t_Maybe_uint256.store_from(cb, data.if_hash_equal);
}
bool ConfigProposal::pack_cfg_proposal(vm::CellBuilder& cb, int param_id, Ref<CellSlice> param_value, Ref<CellSlice> if_hash_equal) const {
return cb.store_long_bool(0xf3, 8)
&& cb.store_long_rchk_bool(param_id, 32)
&& t_Maybe_Ref_Cell.store_from(cb, param_value)
&& t_Maybe_uint256.store_from(cb, if_hash_equal);
}
bool ConfigProposal::cell_pack(Ref<vm::Cell>& cell_ref, const ConfigProposal::Record& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigProposal::cell_pack_cfg_proposal(Ref<vm::Cell>& cell_ref, int param_id, Ref<CellSlice> param_value, Ref<CellSlice> if_hash_equal) const {
vm::CellBuilder cb;
return pack_cfg_proposal(cb, param_id, std::move(param_value), std::move(if_hash_equal)) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigProposal::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
return cs.fetch_ulong(8) == 0xf3
&& pp.open("cfg_proposal")
&& pp.fetch_int_field(cs, 32, "param_id")
&& pp.field("param_value")
&& t_Maybe_Ref_Cell.print_skip(pp, cs)
&& pp.field("if_hash_equal")
&& t_Maybe_uint256.print_skip(pp, cs)
&& pp.close();
}
const ConfigProposal t_ConfigProposal;
//
// code for type `ConfigProposalStatus`
//
constexpr unsigned char ConfigProposalStatus::cons_tag[1];
int ConfigProposalStatus::check_tag(const vm::CellSlice& cs) const {
return cs.prefetch_ulong(8) == 0xce ? cfg_proposal_status : -1;
}
bool ConfigProposalStatus::skip(vm::CellSlice& cs) const {
return cs.advance_ext(0x10029)
&& t_HashmapE_16_True.skip(cs)
&& cs.advance(344);
}
bool ConfigProposalStatus::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(8) == 0xce
&& cs.advance(32)
&& t_ConfigProposal.validate_skip_ref(ops, cs, weak)
&& cs.advance(1)
&& t_HashmapE_16_True.validate_skip(ops, cs, weak)
&& cs.advance(344);
}
bool ConfigProposalStatus::unpack(vm::CellSlice& cs, ConfigProposalStatus::Record& data) const {
return cs.fetch_ulong(8) == 0xce
&& cs.fetch_uint_to(32, data.expires)
&& cs.fetch_ref_to(data.proposal)
&& cs.fetch_bool_to(data.is_critical)
&& t_HashmapE_16_True.fetch_to(cs, data.voters)
&& cs.fetch_int_to(64, data.remaining_weight)
&& cs.fetch_uint256_to(256, data.validator_set_id)
&& cs.fetch_uint_to(8, data.rounds_remaining)
&& cs.fetch_uint_to(8, data.wins)
&& cs.fetch_uint_to(8, data.losses);
}
bool ConfigProposalStatus::cell_unpack(Ref<vm::Cell> cell_ref, ConfigProposalStatus::Record& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ConfigProposalStatus::pack(vm::CellBuilder& cb, const ConfigProposalStatus::Record& data) const {
return cb.store_long_bool(0xce, 8)
&& cb.store_ulong_rchk_bool(data.expires, 32)
&& cb.store_ref_bool(data.proposal)
&& cb.store_ulong_rchk_bool(data.is_critical, 1)
&& t_HashmapE_16_True.store_from(cb, data.voters)
&& cb.store_long_rchk_bool(data.remaining_weight, 64)
&& cb.store_int256_bool(data.validator_set_id, 256, false)
&& cb.store_ulong_rchk_bool(data.rounds_remaining, 8)
&& cb.store_ulong_rchk_bool(data.wins, 8)
&& cb.store_ulong_rchk_bool(data.losses, 8);
}
bool ConfigProposalStatus::cell_pack(Ref<vm::Cell>& cell_ref, const ConfigProposalStatus::Record& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigProposalStatus::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
return cs.fetch_ulong(8) == 0xce
&& pp.open("cfg_proposal_status")
&& pp.fetch_uint_field(cs, 32, "expires")
&& pp.field("proposal")
&& t_ConfigProposal.print_ref(pp, cs.fetch_ref())
&& pp.fetch_uint_field(cs, 1, "is_critical")
&& pp.field("voters")
&& t_HashmapE_16_True.print_skip(pp, cs)
&& pp.fetch_int_field(cs, 64, "remaining_weight")
&& pp.fetch_uint256_field(cs, 256, "validator_set_id")
&& pp.fetch_uint_field(cs, 8, "rounds_remaining")
&& pp.fetch_uint_field(cs, 8, "wins")
&& pp.fetch_uint_field(cs, 8, "losses")
&& pp.close();
}
const ConfigProposalStatus t_ConfigProposalStatus;
//
// code for type `WorkchainFormat`
//
@ -15219,6 +15534,10 @@ int ConfigParam::get_tag(const vm::CellSlice& cs) const {
return cons8;
case 9:
return cons9;
case 10:
return cons10;
case 11:
return cons11;
case 12:
return cons12;
case 14:
@ -15288,6 +15607,10 @@ int ConfigParam::check_tag(const vm::CellSlice& cs) const {
return cons8;
case cons9:
return cons9;
case cons10:
return cons10;
case cons11:
return cons11;
case cons12:
return cons12;
case cons14:
@ -15366,6 +15689,12 @@ bool ConfigParam::skip(vm::CellSlice& cs) const {
case cons9:
return t_Hashmap_32_True.skip(cs)
&& m_ == 9;
case cons10:
return t_Hashmap_32_True.skip(cs)
&& m_ == 10;
case cons11:
return cs.advance_ext(0x20008)
&& m_ == 11;
case cons12:
return t_HashmapE_32_WorkchainDescr.skip(cs)
&& m_ == 12;
@ -15476,6 +15805,12 @@ bool ConfigParam::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
case cons9:
return t_Hashmap_32_True.validate_skip(ops, cs, weak)
&& m_ == 9;
case cons10:
return t_Hashmap_32_True.validate_skip(ops, cs, weak)
&& m_ == 10;
case cons11:
return t_ConfigVotingSetup.validate_skip(ops, cs, weak)
&& m_ == 11;
case cons12:
return t_HashmapE_32_WorkchainDescr.validate_skip(ops, cs, weak)
&& m_ == 12;
@ -15756,6 +16091,50 @@ bool ConfigParam::cell_unpack_cons9(Ref<vm::Cell> cell_ref, Ref<CellSlice>& mand
return unpack_cons9(cs, mandatory_params) && cs.empty_ext();
}
bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons10& data) const {
return t_Hashmap_32_True.fetch_to(cs, data.critical_params)
&& m_ == 10;
}
bool ConfigParam::unpack_cons10(vm::CellSlice& cs, Ref<CellSlice>& critical_params) const {
return t_Hashmap_32_True.fetch_to(cs, critical_params)
&& m_ == 10;
}
bool ConfigParam::cell_unpack(Ref<vm::Cell> cell_ref, ConfigParam::Record_cons10& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ConfigParam::cell_unpack_cons10(Ref<vm::Cell> cell_ref, Ref<CellSlice>& critical_params) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack_cons10(cs, critical_params) && cs.empty_ext();
}
bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons11& data) const {
return cs.fetch_subslice_ext_to(0x20008, data.x)
&& m_ == 11;
}
bool ConfigParam::unpack_cons11(vm::CellSlice& cs, Ref<CellSlice>& x) const {
return cs.fetch_subslice_ext_to(0x20008, x)
&& m_ == 11;
}
bool ConfigParam::cell_unpack(Ref<vm::Cell> cell_ref, ConfigParam::Record_cons11& data) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack(cs, data) && cs.empty_ext();
}
bool ConfigParam::cell_unpack_cons11(Ref<vm::Cell> cell_ref, Ref<CellSlice>& x) const {
if (cell_ref.is_null()) { return false; }
auto cs = load_cell_slice(std::move(cell_ref));
return unpack_cons11(cs, x) && cs.empty_ext();
}
bool ConfigParam::unpack(vm::CellSlice& cs, ConfigParam::Record_cons12& data) const {
return t_HashmapE_32_WorkchainDescr.fetch_to(cs, data.workchains)
&& m_ == 12;
@ -16416,6 +16795,46 @@ bool ConfigParam::cell_pack_cons9(Ref<vm::Cell>& cell_ref, Ref<CellSlice> mandat
return pack_cons9(cb, std::move(mandatory_params)) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons10& data) const {
return t_Hashmap_32_True.store_from(cb, data.critical_params)
&& m_ == 10;
}
bool ConfigParam::pack_cons10(vm::CellBuilder& cb, Ref<CellSlice> critical_params) const {
return t_Hashmap_32_True.store_from(cb, critical_params)
&& m_ == 10;
}
bool ConfigParam::cell_pack(Ref<vm::Cell>& cell_ref, const ConfigParam::Record_cons10& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigParam::cell_pack_cons10(Ref<vm::Cell>& cell_ref, Ref<CellSlice> critical_params) const {
vm::CellBuilder cb;
return pack_cons10(cb, std::move(critical_params)) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons11& data) const {
return cb.append_cellslice_chk(data.x, 0x20008)
&& m_ == 11;
}
bool ConfigParam::pack_cons11(vm::CellBuilder& cb, Ref<CellSlice> x) const {
return cb.append_cellslice_chk(x, 0x20008)
&& m_ == 11;
}
bool ConfigParam::cell_pack(Ref<vm::Cell>& cell_ref, const ConfigParam::Record_cons11& data) const {
vm::CellBuilder cb;
return pack(cb, data) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigParam::cell_pack_cons11(Ref<vm::Cell>& cell_ref, Ref<CellSlice> x) const {
vm::CellBuilder cb;
return pack_cons11(cb, std::move(x)) && std::move(cb).finalize_to(cell_ref);
}
bool ConfigParam::pack(vm::CellBuilder& cb, const ConfigParam::Record_cons12& data) const {
return t_HashmapE_32_WorkchainDescr.store_from(cb, data.workchains)
&& m_ == 12;
@ -16905,6 +17324,18 @@ bool ConfigParam::print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const {
&& t_Hashmap_32_True.print_skip(pp, cs)
&& m_ == 9
&& pp.close();
case cons10:
return pp.open()
&& pp.field("critical_params")
&& t_Hashmap_32_True.print_skip(pp, cs)
&& m_ == 10
&& pp.close();
case cons11:
return pp.open()
&& pp.field()
&& t_ConfigVotingSetup.print_skip(pp, cs)
&& m_ == 11
&& pp.close();
case cons12:
return pp.open()
&& pp.field("workchains")
@ -21128,8 +21559,8 @@ const RefT t_Ref_OutMsgDescr{t_OutMsgDescr};
const RefT t_Ref_ShardAccountBlocks{t_ShardAccountBlocks};
const RefT t_Ref_McBlockExtra{t_McBlockExtra};
const Maybe t_Maybe_Ref_McBlockExtra{t_Ref_McBlockExtra};
const RefT t_Ref_TYPE_1648{t_ValueFlow_aux};
const RefT t_Ref_TYPE_1649{t_ValueFlow_aux1};
const RefT t_Ref_TYPE_1649{t_ValueFlow_aux};
const RefT t_Ref_TYPE_1650{t_ValueFlow_aux1};
const NatWidth t_natwidth_3{3};
const BinTree t_BinTree_ShardDescr{t_ShardDescr};
const RefT t_Ref_BinTree_ShardDescr{t_BinTree_ShardDescr};
@ -21142,14 +21573,21 @@ const HashmapE t_HashmapE_256_CreatorStats{256, t_CreatorStats};
const HashmapAugE t_HashmapAugE_256_CreatorStats_uint32{256, t_CreatorStats, t_uint32};
const NatWidth t_natwidth_16{16};
const Maybe t_Maybe_ExtBlkRef{t_ExtBlkRef};
const RefT t_Ref_TYPE_1666{t_McStateExtra_aux};
const RefT t_Ref_TYPE_1667{t_McStateExtra_aux};
const RefT t_Ref_SignedCertificate{t_SignedCertificate};
const HashmapE t_HashmapE_16_CryptoSignaturePair{16, t_CryptoSignaturePair};
const Maybe t_Maybe_Ref_InMsg{t_Ref_InMsg};
const RefT t_Ref_TYPE_1674{t_McBlockExtra_aux};
const RefT t_Ref_TYPE_1675{t_McBlockExtra_aux};
const Hashmap t_Hashmap_16_ValidatorDescr{16, t_ValidatorDescr};
const HashmapE t_HashmapE_16_ValidatorDescr{16, t_ValidatorDescr};
const Hashmap t_Hashmap_32_True{32, t_True};
const UInt t_uint8{8};
const RefT t_Ref_ConfigProposalSetup{t_ConfigProposalSetup};
const UInt t_uint256{256};
const Maybe t_Maybe_uint256{t_uint256};
const RefT t_Ref_ConfigProposal{t_ConfigProposal};
const HashmapE t_HashmapE_16_True{16, t_True};
const Int t_int64{64};
const NatWidth t_natwidth_12{12};
const NatWidth t_natwidth_32{32};
const NatWidth t_natwidth_13{13};
@ -21162,14 +21600,13 @@ const RefT t_Ref_BlockSignatures{t_BlockSignatures};
const Maybe t_Maybe_Ref_BlockSignatures{t_Ref_BlockSignatures};
const RefT t_Ref_TopBlockDescr{t_TopBlockDescr};
const HashmapE t_HashmapE_96_Ref_TopBlockDescr{96, t_Ref_TopBlockDescr};
const Int t_int64{64};
const Int t_int257{257};
const NatWidth t_natwidth_10{10};
const NatLeq t_natleq_4{4};
const RefT t_Ref_VmStackValue{t_VmStackValue};
const NatWidth t_natwidth_24{24};
const HashmapE t_HashmapE_4_VmStackValue{4, t_VmStackValue};
const RefT t_Ref_TYPE_1705{t_VmGasLimits_aux};
const RefT t_Ref_TYPE_1709{t_VmGasLimits_aux};
const HashmapE t_HashmapE_256_Ref_Cell{256, t_RefCell};
const UInt t_uint13{13};
const Maybe t_Maybe_uint13{t_uint13};
@ -21250,6 +21687,7 @@ bool register_simple_types(std::function<bool(const char*, const TLB*)> func) {
&& func("McStateExtra", &t_McStateExtra)
&& func("ShardStateUnsplit", &t_ShardStateUnsplit)
&& func("ShardState", &t_ShardState)
&& func("GlobalVersion", &t_GlobalVersion)
&& func("BlockInfo", &t_BlockInfo)
&& func("ValueFlow", &t_ValueFlow)
&& func("BlockExtra", &t_BlockExtra)
@ -21278,7 +21716,10 @@ bool register_simple_types(std::function<bool(const char*, const TLB*)> func) {
&& func("SignedCertificate", &t_SignedCertificate)
&& func("ValidatorDescr", &t_ValidatorDescr)
&& func("ValidatorSet", &t_ValidatorSet)
&& func("GlobalVersion", &t_GlobalVersion)
&& func("ConfigProposalSetup", &t_ConfigProposalSetup)
&& func("ConfigVotingSetup", &t_ConfigVotingSetup)
&& func("ConfigProposal", &t_ConfigProposal)
&& func("ConfigProposalStatus", &t_ConfigProposalStatus)
&& func("WorkchainDescr", &t_WorkchainDescr)
&& func("BlockCreateFees", &t_BlockCreateFees)
&& func("StoragePrices", &t_StoragePrices)

View File

@ -15,6 +15,7 @@
// uses built-in type `uint`
// uses built-in type `bits`
// uses built-in type `int8`
// uses built-in type `uint8`
// uses built-in type `uint13`
// uses built-in type `uint15`
// uses built-in type `int16`
@ -24,6 +25,7 @@
// uses built-in type `uint63`
// uses built-in type `int64`
// uses built-in type `uint64`
// uses built-in type `uint256`
// uses built-in type `int257`
// uses built-in type `bits256`
@ -4533,11 +4535,12 @@ struct BlockInfo::Record {
unsigned gen_catchain_seqno; // gen_catchain_seqno : uint32
unsigned min_ref_mc_seqno; // min_ref_mc_seqno : uint32
unsigned prev_key_block_seqno; // prev_key_block_seqno : uint32
Ref<CellSlice> gen_software; // gen_software : flags.0?GlobalVersion
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_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)) {}
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<CellSlice> _gen_software, 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), gen_software(std::move(_gen_software)), master_ref(std::move(_master_ref)), prev_ref(std::move(_prev_ref)), prev_vert_ref(std::move(_prev_vert_ref)) {}
};
extern const BlockInfo t_BlockInfo;
@ -6085,6 +6088,176 @@ struct GlobalVersion final : TLB_Complex {
extern const GlobalVersion t_GlobalVersion;
//
// headers for type `ConfigProposalSetup`
//
struct ConfigProposalSetup final : TLB_Complex {
enum { cfg_vote_cfg };
static constexpr int cons_len_exact = 8;
static constexpr unsigned char cons_tag[1] = { 0x36 };
struct Record;
int get_size(const vm::CellSlice& cs) const override {
return 168;
}
bool skip(vm::CellSlice& cs) const override {
return cs.advance(168);
}
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, Record& data) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record& data) const;
bool pack(vm::CellBuilder& cb, const Record& data) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record& data) const;
bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "ConfigProposalSetup";
}
int check_tag(const vm::CellSlice& cs) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
};
struct ConfigProposalSetup::Record {
typedef ConfigProposalSetup type_class;
int min_tot_rounds; // min_tot_rounds : uint8
int max_tot_rounds; // max_tot_rounds : uint8
int min_wins; // min_wins : uint8
int max_losses; // max_losses : uint8
unsigned min_store_sec; // min_store_sec : uint32
unsigned max_store_sec; // max_store_sec : uint32
unsigned bit_price; // bit_price : uint32
unsigned cell_price; // cell_price : uint32
Record() = default;
Record(int _min_tot_rounds, int _max_tot_rounds, int _min_wins, int _max_losses, unsigned _min_store_sec, unsigned _max_store_sec, unsigned _bit_price, unsigned _cell_price) : min_tot_rounds(_min_tot_rounds), max_tot_rounds(_max_tot_rounds), min_wins(_min_wins), max_losses(_max_losses), min_store_sec(_min_store_sec), max_store_sec(_max_store_sec), bit_price(_bit_price), cell_price(_cell_price) {}
};
extern const ConfigProposalSetup t_ConfigProposalSetup;
//
// headers for type `ConfigVotingSetup`
//
struct ConfigVotingSetup final : TLB_Complex {
enum { cfg_vote_setup };
static constexpr int cons_len_exact = 8;
static constexpr unsigned char cons_tag[1] = { 0x91 };
struct Record {
typedef ConfigVotingSetup type_class;
Ref<Cell> normal_params; // normal_params : ^ConfigProposalSetup
Ref<Cell> critical_params; // critical_params : ^ConfigProposalSetup
Record() = default;
Record(Ref<Cell> _normal_params, Ref<Cell> _critical_params) : normal_params(std::move(_normal_params)), critical_params(std::move(_critical_params)) {}
};
int get_size(const vm::CellSlice& cs) const override {
return 0x20008;
}
bool skip(vm::CellSlice& cs) const override {
return cs.advance_ext(0x20008);
}
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, Record& data) const;
bool unpack_cfg_vote_setup(vm::CellSlice& cs, Ref<Cell>& normal_params, Ref<Cell>& critical_params) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record& data) const;
bool cell_unpack_cfg_vote_setup(Ref<vm::Cell> cell_ref, Ref<Cell>& normal_params, Ref<Cell>& critical_params) const;
bool pack(vm::CellBuilder& cb, const Record& data) const;
bool pack_cfg_vote_setup(vm::CellBuilder& cb, Ref<Cell> normal_params, Ref<Cell> critical_params) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record& data) const;
bool cell_pack_cfg_vote_setup(Ref<vm::Cell>& cell_ref, Ref<Cell> normal_params, Ref<Cell> critical_params) const;
bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "ConfigVotingSetup";
}
int check_tag(const vm::CellSlice& cs) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
};
extern const ConfigVotingSetup t_ConfigVotingSetup;
//
// headers for type `ConfigProposal`
//
struct ConfigProposal final : TLB_Complex {
enum { cfg_proposal };
static constexpr int cons_len_exact = 8;
static constexpr unsigned char cons_tag[1] = { 0xf3 };
struct Record;
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, Record& data) const;
bool unpack_cfg_proposal(vm::CellSlice& cs, int& param_id, Ref<CellSlice>& param_value, Ref<CellSlice>& if_hash_equal) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record& data) const;
bool cell_unpack_cfg_proposal(Ref<vm::Cell> cell_ref, int& param_id, Ref<CellSlice>& param_value, Ref<CellSlice>& if_hash_equal) const;
bool pack(vm::CellBuilder& cb, const Record& data) const;
bool pack_cfg_proposal(vm::CellBuilder& cb, int param_id, Ref<CellSlice> param_value, Ref<CellSlice> if_hash_equal) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record& data) const;
bool cell_pack_cfg_proposal(Ref<vm::Cell>& cell_ref, int param_id, Ref<CellSlice> param_value, Ref<CellSlice> if_hash_equal) const;
bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "ConfigProposal";
}
int check_tag(const vm::CellSlice& cs) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
};
struct ConfigProposal::Record {
typedef ConfigProposal type_class;
int param_id; // param_id : int32
Ref<CellSlice> param_value; // param_value : Maybe ^Cell
Ref<CellSlice> if_hash_equal; // if_hash_equal : Maybe uint256
Record() = default;
Record(int _param_id, Ref<CellSlice> _param_value, Ref<CellSlice> _if_hash_equal) : param_id(_param_id), param_value(std::move(_param_value)), if_hash_equal(std::move(_if_hash_equal)) {}
};
extern const ConfigProposal t_ConfigProposal;
//
// headers for type `ConfigProposalStatus`
//
struct ConfigProposalStatus final : TLB_Complex {
enum { cfg_proposal_status };
static constexpr int cons_len_exact = 8;
static constexpr unsigned char cons_tag[1] = { 0xce };
struct Record;
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, Record& data) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record& data) const;
bool pack(vm::CellBuilder& cb, const Record& data) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record& data) const;
bool print_skip(PrettyPrinter& pp, vm::CellSlice& cs) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "ConfigProposalStatus";
}
int check_tag(const vm::CellSlice& cs) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
};
struct ConfigProposalStatus::Record {
typedef ConfigProposalStatus type_class;
unsigned expires; // expires : uint32
Ref<Cell> proposal; // proposal : ^ConfigProposal
bool is_critical; // is_critical : Bool
Ref<CellSlice> voters; // voters : HashmapE 16 True
long long remaining_weight; // remaining_weight : int64
RefInt256 validator_set_id; // validator_set_id : uint256
int rounds_remaining; // rounds_remaining : uint8
int wins; // wins : uint8
int losses; // losses : uint8
Record() = default;
Record(unsigned _expires, Ref<Cell> _proposal, bool _is_critical, Ref<CellSlice> _voters, long long _remaining_weight, RefInt256 _validator_set_id, int _rounds_remaining, int _wins, int _losses) : expires(_expires), proposal(std::move(_proposal)), is_critical(_is_critical), voters(std::move(_voters)), remaining_weight(_remaining_weight), validator_set_id(std::move(_validator_set_id)), rounds_remaining(_rounds_remaining), wins(_wins), losses(_losses) {}
};
extern const ConfigProposalStatus t_ConfigProposalStatus;
//
// headers for type `WorkchainFormat`
//
@ -6640,7 +6813,7 @@ extern const ValidatorSignedTempKey t_ValidatorSignedTempKey;
//
struct ConfigParam final : TLB_Complex {
enum { cons32, cons33, cons34, cons35, cons36, cons37, config_mc_block_limits, config_block_limits, cons14, cons0, cons1, cons2, cons3, cons4, cons6, cons7, cons9, cons12, cons15, cons16, cons17, cons18, cons31, cons39, cons28, cons8, config_mc_gas_prices, config_gas_prices, cons29, config_mc_fwd_prices, config_fwd_prices };
enum { cons32, cons33, cons34, cons35, cons36, cons37, config_mc_block_limits, config_block_limits, cons14, cons0, cons1, cons2, cons3, cons4, cons6, cons7, cons9, cons10, cons12, cons15, cons16, cons17, cons18, cons31, cons39, cons11, cons28, cons8, config_mc_gas_prices, config_gas_prices, cons29, config_mc_fwd_prices, config_fwd_prices };
static constexpr int cons_len_exact = 0;
int m_;
ConfigParam(int m) : m_(m) {}
@ -6699,6 +6872,18 @@ struct ConfigParam final : TLB_Complex {
Record_cons9() = default;
Record_cons9(Ref<CellSlice> _mandatory_params) : mandatory_params(std::move(_mandatory_params)) {}
};
struct Record_cons10 {
typedef ConfigParam type_class;
Ref<CellSlice> critical_params; // critical_params : Hashmap 32 True
Record_cons10() = default;
Record_cons10(Ref<CellSlice> _critical_params) : critical_params(std::move(_critical_params)) {}
};
struct Record_cons11 {
typedef ConfigParam type_class;
Ref<CellSlice> x; // ConfigVotingSetup
Record_cons11() = default;
Record_cons11(Ref<CellSlice> _x) : x(std::move(_x)) {}
};
struct Record_cons12 {
typedef ConfigParam type_class;
Ref<CellSlice> workchains; // workchains : HashmapE 32 WorkchainDescr
@ -6890,6 +7075,22 @@ struct ConfigParam final : TLB_Complex {
bool pack_cons9(vm::CellBuilder& cb, Ref<CellSlice> mandatory_params) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record_cons9& data) const;
bool cell_pack_cons9(Ref<vm::Cell>& cell_ref, Ref<CellSlice> mandatory_params) const;
bool unpack(vm::CellSlice& cs, Record_cons10& data) const;
bool unpack_cons10(vm::CellSlice& cs, Ref<CellSlice>& critical_params) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record_cons10& data) const;
bool cell_unpack_cons10(Ref<vm::Cell> cell_ref, Ref<CellSlice>& critical_params) const;
bool pack(vm::CellBuilder& cb, const Record_cons10& data) const;
bool pack_cons10(vm::CellBuilder& cb, Ref<CellSlice> critical_params) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record_cons10& data) const;
bool cell_pack_cons10(Ref<vm::Cell>& cell_ref, Ref<CellSlice> critical_params) const;
bool unpack(vm::CellSlice& cs, Record_cons11& data) const;
bool unpack_cons11(vm::CellSlice& cs, Ref<CellSlice>& x) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record_cons11& data) const;
bool cell_unpack_cons11(Ref<vm::Cell> cell_ref, Ref<CellSlice>& x) const;
bool pack(vm::CellBuilder& cb, const Record_cons11& data) const;
bool pack_cons11(vm::CellBuilder& cb, Ref<CellSlice> x) const;
bool cell_pack(Ref<vm::Cell>& cell_ref, const Record_cons11& data) const;
bool cell_pack_cons11(Ref<vm::Cell>& cell_ref, Ref<CellSlice> x) const;
bool unpack(vm::CellSlice& cs, Record_cons12& data) const;
bool unpack_cons12(vm::CellSlice& cs, Ref<CellSlice>& workchains) const;
bool cell_unpack(Ref<vm::Cell> cell_ref, Record_cons12& data) const;
@ -8689,9 +8890,9 @@ extern const RefT t_Ref_McBlockExtra;
// Maybe ^McBlockExtra
extern const Maybe t_Maybe_Ref_McBlockExtra;
// ^[$_ from_prev_blk:CurrencyCollection to_next_blk:CurrencyCollection imported:CurrencyCollection exported:CurrencyCollection ]
extern const RefT t_Ref_TYPE_1648;
// ^[$_ fees_imported:CurrencyCollection recovered:CurrencyCollection created:CurrencyCollection minted:CurrencyCollection ]
extern const RefT t_Ref_TYPE_1649;
// ^[$_ fees_imported:CurrencyCollection recovered:CurrencyCollection created:CurrencyCollection minted:CurrencyCollection ]
extern const RefT t_Ref_TYPE_1650;
// ## 3
extern const NatWidth t_natwidth_3;
// BinTree ShardDescr
@ -8717,7 +8918,7 @@ extern const NatWidth t_natwidth_16;
// Maybe ExtBlkRef
extern const Maybe t_Maybe_ExtBlkRef;
// ^[$_ flags:(## 16) {<= flags 1} validator_info:ValidatorInfo prev_blocks:OldMcBlocksInfo after_key_block:Bool last_key_block:(Maybe ExtBlkRef) block_create_stats:flags.0?BlockCreateStats ]
extern const RefT t_Ref_TYPE_1666;
extern const RefT t_Ref_TYPE_1667;
// ^SignedCertificate
extern const RefT t_Ref_SignedCertificate;
// HashmapE 16 CryptoSignaturePair
@ -8725,13 +8926,27 @@ extern const HashmapE t_HashmapE_16_CryptoSignaturePair;
// Maybe ^InMsg
extern const Maybe t_Maybe_Ref_InMsg;
// ^[$_ prev_blk_signatures:(HashmapE 16 CryptoSignaturePair) recover_create_msg:(Maybe ^InMsg) mint_msg:(Maybe ^InMsg) ]
extern const RefT t_Ref_TYPE_1674;
extern const RefT t_Ref_TYPE_1675;
// Hashmap 16 ValidatorDescr
extern const Hashmap t_Hashmap_16_ValidatorDescr;
// HashmapE 16 ValidatorDescr
extern const HashmapE t_HashmapE_16_ValidatorDescr;
// Hashmap 32 True
extern const Hashmap t_Hashmap_32_True;
// uint8
extern const UInt t_uint8;
// ^ConfigProposalSetup
extern const RefT t_Ref_ConfigProposalSetup;
// uint256
extern const UInt t_uint256;
// Maybe uint256
extern const Maybe t_Maybe_uint256;
// ^ConfigProposal
extern const RefT t_Ref_ConfigProposal;
// HashmapE 16 True
extern const HashmapE t_HashmapE_16_True;
// int64
extern const Int t_int64;
// ## 12
extern const NatWidth t_natwidth_12;
// ## 32
@ -8756,8 +8971,6 @@ extern const Maybe t_Maybe_Ref_BlockSignatures;
extern const RefT t_Ref_TopBlockDescr;
// HashmapE 96 ^TopBlockDescr
extern const HashmapE t_HashmapE_96_Ref_TopBlockDescr;
// int64
extern const Int t_int64;
// int257
extern const Int t_int257;
// ## 10
@ -8771,7 +8984,7 @@ extern const NatWidth t_natwidth_24;
// HashmapE 4 VmStackValue
extern const HashmapE t_HashmapE_4_VmStackValue;
// ^[$_ max_limit:int64 cur_limit:int64 credit:int64 ]
extern const RefT t_Ref_TYPE_1705;
extern const RefT t_Ref_TYPE_1709;
// HashmapE 256 ^Cell
extern const HashmapE t_HashmapE_256_Ref_Cell;
// uint13

View File

@ -344,11 +344,11 @@ unsigned long long VarUIntegerPos::as_uint(const vm::CellSlice& cs) const {
bool VarUIntegerPos::store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const {
int k = value.bit_size(false);
return k <= (n - 1) * 8 && value.sgn() > 0 && cb.store_long_bool((k + 7) >> 3, ln) &&
return k <= (n - 1) * 8 && value.sgn() >= (int)store_pos_only && cb.store_long_bool((k + 7) >> 3, ln) &&
cb.store_int256_bool(value, (k + 7) & -8, false);
}
const VarUIntegerPos t_VarUIntegerPos_16{16}, t_VarUIntegerPos_32{32};
const VarUIntegerPos t_VarUIntegerPos_16{16}, t_VarUIntegerPos_32{32}, t_VarUIntegerPosRelaxed_32{32, true};
static inline bool redundant_int(const vm::CellSlice& cs) {
int t = (int)cs.prefetch_long(9);
@ -500,8 +500,8 @@ bool HashmapE::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice
int n = root_type.n;
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
const TLB& vt = root_type.value_type;
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
throw CombineError{};
}
@ -514,8 +514,8 @@ bool HashmapE::add_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Ce
int n = root_type.n;
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
const TLB& vt = root_type.value_type;
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
if (!vt.add_values(cb, cs1_ref.write(), cs2_ref.write())) {
throw CombineError{};
}
@ -535,8 +535,8 @@ int HashmapE::sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice&
int n = root_type.n;
vm::Dictionary dict1{vm::DictAdvance(), cs1, n}, dict2{vm::DictAdvance(), cs2, n};
const TLB& vt = root_type.value_type;
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
if (r < 0) {
throw CombineError{};
@ -555,8 +555,8 @@ int HashmapE::sub_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cel
int n = root_type.n;
vm::Dictionary dict1{std::move(arg1), n}, dict2{std::move(arg2), n};
const TLB& vt = root_type.value_type;
vm::Dictionary::simple_combine_func_t combine = [vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
vm::Dictionary::simple_combine_func_t combine = [&vt](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
int r = vt.sub_values(cb, cs1_ref.write(), cs2_ref.write());
if (r < 0) {
throw CombineError{};

View File

@ -68,13 +68,17 @@ struct VarUInteger final : TLB_Complex {
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
unsigned precompute_integer_size(const td::BigInt256& value) const;
unsigned precompute_integer_size(td::RefInt256 value) const;
std::ostream& print_type(std::ostream& os) const override {
return os << "(VarUInteger " << n << ")";
}
};
extern const VarUInteger t_VarUInteger_3, t_VarUInteger_7, t_VarUInteger_16, t_VarUInteger_32;
struct VarUIntegerPos final : TLB_Complex {
int n, ln;
VarUIntegerPos(int _n) : n(_n) {
bool store_pos_only;
VarUIntegerPos(int _n, bool relaxed = false) : n(_n), store_pos_only(!relaxed) {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
@ -82,9 +86,12 @@ struct VarUIntegerPos final : TLB_Complex {
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
unsigned long long as_uint(const vm::CellSlice& cs) const override;
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "(VarUIntegerPos " << n << ")";
}
};
extern const VarUIntegerPos t_VarUIntegerPos_16, t_VarUIntegerPos_32;
extern const VarUIntegerPos t_VarUIntegerPos_16, t_VarUIntegerPos_32, t_VarUIntegerPosRelaxed_32;
struct VarInteger final : TLB_Complex {
int n, ln;
@ -99,6 +106,9 @@ struct VarInteger final : TLB_Complex {
return cb.store_zeroes_bool(ln);
}
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "(VarInteger " << n << ")";
}
};
struct VarIntegerNz final : TLB_Complex {
@ -111,6 +121,9 @@ struct VarIntegerNz final : TLB_Complex {
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
long long as_int(const vm::CellSlice& cs) const override;
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
std::ostream& print_type(std::ostream& os) const override {
return os << "(VarIntegerNz " << n << ")";
}
};
struct Unary final : TLB {
@ -312,8 +325,8 @@ struct MsgAddress final : TLB_Complex {
extern const MsgAddress t_MsgAddress;
struct ExtraCurrencyCollection final : TLB {
HashmapE dict_type;
ExtraCurrencyCollection() : dict_type(32, t_VarUIntegerPos_32) {
HashmapE dict_type, dict_type2;
ExtraCurrencyCollection() : dict_type(32, t_VarUIntegerPos_32), dict_type2(32, t_VarUIntegerPosRelaxed_32) {
}
int get_size(const vm::CellSlice& cs) const override {
return dict_type.get_size(cs);
@ -328,13 +341,13 @@ struct ExtraCurrencyCollection final : TLB {
return dict_type.add_values(cb, cs1, cs2);
}
int sub_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override {
return dict_type.sub_values(cb, cs1, cs2);
return dict_type2.sub_values(cb, cs1, cs2);
}
bool add_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
return dict_type.add_values_ref(res, std::move(arg1), std::move(arg2));
}
int sub_values_ref(Ref<vm::Cell>& res, Ref<vm::Cell> arg1, Ref<vm::Cell> arg2) const {
return dict_type.sub_values_ref(res, std::move(arg1), std::move(arg2));
return dict_type2.sub_values_ref(res, std::move(arg1), std::move(arg2));
}
bool store_ref(vm::CellBuilder& cb, Ref<vm::Cell> arg) const {
return dict_type.store_ref(cb, std::move(arg));

View File

@ -20,6 +20,7 @@
#include "block/block.h"
#include "block/block-auto.h"
#include "block/block-parse.h"
#include "block/mc-config.h"
#include "ton/ton-shard.h"
#include "common/bigexp.h"
#include "common/util.h"
@ -1602,33 +1603,50 @@ bool check_one_config_param(Ref<vm::CellSlice> cs_ref, td::ConstBitPtr key, td::
const int mandatory_config_params[] = {18, 20, 21, 22, 23, 24, 25, 28, 34};
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors, bool relax_par0) {
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors, bool relax_par0,
Ref<vm::Cell> old_mparams) {
using namespace std::placeholders;
if (cell.is_null()) {
return false;
}
if (!catch_errors) {
vm::Dictionary dict{std::move(cell), 32};
for (int x : mandatory_config_params) {
if (!dict.int_key_exists(x)) {
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
return false;
}
if (catch_errors) {
try {
return valid_config_data(std::move(cell), addr, false, relax_par0, std::move(old_mparams));
} catch (vm::VmError&) {
return false;
}
return dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0));
}
try {
vm::Dictionary dict{std::move(cell), 32};
for (int x : mandatory_config_params) {
if (!dict.int_key_exists(x)) {
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
return false;
}
}
return dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0));
} catch (vm::VmError&) {
vm::Dictionary dict{std::move(cell), 32};
if (!dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0))) {
return false;
}
for (int x : mandatory_config_params) {
if (!dict.int_key_exists(x)) {
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
return false;
}
}
return config_params_present(dict, dict.lookup_ref(td::BitArray<32>{9})) &&
config_params_present(dict, std::move(old_mparams));
}
bool config_params_present(vm::Dictionary& dict, Ref<vm::Cell> param_dict_root) {
auto res = block::Config::unpack_param_dict(std::move(param_dict_root));
if (res.is_error()) {
LOG(ERROR)
<< "invalid mandatory parameters dictionary while checking existence of all mandatory configuration parameters";
return false;
}
for (int x : res.move_as_ok()) {
// LOG(DEBUG) << "checking whether mandatory configuration parameter #" << x << " exists";
if (!dict.int_key_exists(x)) {
LOG(ERROR) << "configuration parameter #" << x
<< " (declared as mandatory in configuration parameter #9) is missing";
return false;
}
}
// LOG(DEBUG) << "all mandatory configuration parameters present";
return true;
}
bool add_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res) {
@ -1651,7 +1669,7 @@ bool sub_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell
res.clear();
return false;
} else {
return block::tlb::t_ExtraCurrencyCollection.sub_values_ref(res, std::move(extra1), std::move(extra2));
return block::tlb::t_ExtraCurrencyCollection.sub_values_ref(res, std::move(extra1), std::move(extra2)) >= 0;
}
}

View File

@ -606,7 +606,8 @@ bool unpack_CurrencyCollection(Ref<vm::CellSlice> csr, td::RefInt256& value, Ref
bool valid_library_collection(Ref<vm::Cell> cell, bool catch_errors = true);
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors = true,
bool relax_par0 = false);
bool relax_par0 = false, Ref<vm::Cell> old_mparams = {});
bool config_params_present(vm::Dictionary& dict, Ref<vm::Cell> param_dict_root);
bool add_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res);
bool sub_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res);

View File

@ -414,7 +414,7 @@ block_info#9bc7a987 version:uint32
after_split:(## 1)
want_split:Bool want_merge:Bool
key_block:Bool vert_seqno_incr:(## 1)
flags:(## 8)
flags:(## 8) { flags <= 1 }
seq_no:# vert_seq_no:# { vert_seq_no >= vert_seqno_incr }
{ prev_seq_no:# } { ~prev_seq_no + 1 = seq_no }
shard:ShardIdent gen_utime:uint32
@ -423,6 +423,7 @@ block_info#9bc7a987 version:uint32
gen_catchain_seqno:uint32
min_ref_mc_seqno:uint32
prev_key_block_seqno:uint32
gen_software:flags . 0?GlobalVersion
master_ref:not_master?^BlkMasterInfo
prev_ref:^(BlkPrevInfo after_merge)
prev_vert_ref:vert_seqno_incr?^(BlkPrevInfo 0)
@ -572,6 +573,17 @@ _ to_mint:ExtraCurrencyCollection = ConfigParam 7;
capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion;
_ GlobalVersion = ConfigParam 8; // all zero if absent
_ mandatory_params:(Hashmap 32 True) = ConfigParam 9;
_ critical_params:(Hashmap 32 True) = ConfigParam 10;
cfg_vote_cfg#36 min_tot_rounds:uint8 max_tot_rounds:uint8 min_wins:uint8 max_losses:uint8 min_store_sec:uint32 max_store_sec:uint32 bit_price:uint32 cell_price:uint32 = ConfigProposalSetup;
cfg_vote_setup#91 normal_params:^ConfigProposalSetup critical_params:^ConfigProposalSetup = ConfigVotingSetup;
_ ConfigVotingSetup = ConfigParam 11;
cfg_proposal#f3 param_id:int32 param_value:(Maybe ^Cell) if_hash_equal:(Maybe uint256)
= ConfigProposal;
cfg_proposal_status#ce expires:uint32 proposal:^ConfigProposal is_critical:Bool
voters:(HashmapE 16 True) remaining_weight:int64 validator_set_id:uint256
rounds_remaining:uint8 wins:uint8 losses:uint8 = ConfigProposalStatus;
wfmt_basic#1 vm_version:int32 vm_mode:uint64 = WorkchainFormat 1;
wfmt_ext#0 min_addr_len:(## 12) max_addr_len:(## 12) addr_len_step:(## 12)

View File

@ -55,6 +55,8 @@
#include "td/utils/port/path.h"
#include "td/utils/port/signals.h"
#include "tonlib/keys/Mnemonic.h"
#include "block.h"
#include "block-parse.h"
#include "block-auto.h"
@ -616,7 +618,43 @@ void interpret_is_workchain_descr(vm::Stack& stack) {
stack.push_bool(block::gen::t_WorkchainDescr.validate_ref(std::move(cell)));
}
void interpret_add_extra_currencies(vm::Stack& stack) {
Ref<vm::Cell> y = stack.pop_maybe_cell(), x = stack.pop_maybe_cell(), res;
bool ok = block::add_extra_currency(std::move(x), std::move(y), res);
if (ok) {
stack.push_maybe_cell(std::move(res));
}
stack.push_bool(ok);
}
void interpret_sub_extra_currencies(vm::Stack& stack) {
Ref<vm::Cell> y = stack.pop_maybe_cell(), x = stack.pop_maybe_cell(), res;
bool ok = block::sub_extra_currency(std::move(x), std::move(y), res);
if (ok) {
stack.push_maybe_cell(std::move(res));
}
stack.push_bool(ok);
}
void interpret_mnemonic_to_privkey(vm::Stack& stack, int mode) {
td::SecureString str{td::Slice{stack.pop_string()}};
auto res = tonlib::Mnemonic::create(std::move(str), td::SecureString());
if (res.is_error()) {
throw fift::IntError{res.move_as_error().to_string()};
}
auto privkey = res.move_as_ok().to_private_key();
td::SecureString key;
if (mode & 1) {
auto pub = privkey.get_public_key();
key = pub.move_as_ok().as_octet_string();
} else {
key = privkey.as_octet_string();
}
stack.push_bytes(key.as_slice());
}
void init_words_custom(fift::Dictionary& d) {
using namespace std::placeholders;
d.def_stack_word("verb@ ", interpret_get_verbosity);
d.def_stack_word("verb! ", interpret_set_verbosity);
d.def_stack_word("wcid@ ", interpret_get_workchain);
@ -631,6 +669,10 @@ void init_words_custom(fift::Dictionary& d) {
d.def_stack_word("create_state ", interpret_create_state);
d.def_stack_word("isShardState? ", interpret_is_shard_state);
d.def_stack_word("isWorkchainDescr? ", interpret_is_workchain_descr);
d.def_stack_word("CC+? ", interpret_add_extra_currencies);
d.def_stack_word("CC-? ", interpret_sub_extra_currencies);
d.def_stack_word("mnemo>priv ", std::bind(interpret_mnemonic_to_privkey, _1, 0));
d.def_stack_word("mnemo>pub ", std::bind(interpret_mnemonic_to_privkey, _1, 1));
}
tlb::TypenameLookup tlb_dict;
@ -704,7 +746,12 @@ void interpret_tlb_validate_skip(vm::Stack& stack) {
stack.push_bool(ok);
}
void interpret_tlb_type_const(vm::Stack& stack, const tlb::TLB* ptr) {
stack.push_make_object<tlb::TlbTypeHolder>(ptr);
}
void init_words_tlb(fift::Dictionary& d) {
using namespace std::placeholders;
tlb_dict.register_types(block::gen::register_simple_types);
d.def_stack_word("tlb-type-lookup ", interpret_tlb_type_lookup);
d.def_stack_word("tlb-type-name ", interpret_tlb_type_name);
@ -713,6 +760,8 @@ void init_words_tlb(fift::Dictionary& d) {
d.def_stack_word("(tlb-dump-str?) ", interpret_tlb_dump_to_str);
d.def_stack_word("tlb-skip ", interpret_tlb_skip);
d.def_stack_word("tlb-validate-skip ", interpret_tlb_validate_skip);
d.def_stack_word("ExtraCurrencyCollection",
std::bind(interpret_tlb_type_const, _1, &block::tlb::t_ExtraCurrencyCollection));
}
void usage(const char* progname) {

View File

@ -40,6 +40,7 @@
#include <algorithm>
namespace block {
using namespace std::literals::string_literals;
using td::Ref;
Config::Config(Ref<vm::Cell> config_root, const td::Bits256& config_addr, int _mode)
@ -335,6 +336,59 @@ std::unique_ptr<vm::Dictionary> ShardConfig::extract_shard_hashes_dict(Ref<vm::C
}
}
td::Result<std::vector<int>> Config::unpack_param_dict(vm::Dictionary& dict) {
try {
std::vector<int> vect;
if (dict.check_for_each(
[&vect](Ref<vm::CellSlice> value, td::ConstBitPtr key, int key_len) {
bool ok = (key_len == 32 && value->empty_ext());
if (ok) {
vect.push_back((int)key.get_int(32));
}
return ok;
},
true)) {
return std::move(vect);
} else {
return td::Status::Error("invalid parameter list dictionary");
}
} catch (vm::VmError& vme) {
return td::Status::Error("error unpacking parameter list dictionary: "s + vme.get_msg());
}
}
td::Result<std::vector<int>> Config::unpack_param_dict(Ref<vm::Cell> dict_root) {
vm::Dictionary dict{std::move(dict_root), 32};
return unpack_param_dict(dict);
}
std::unique_ptr<vm::Dictionary> Config::get_param_dict(int idx) const {
return std::make_unique<vm::Dictionary>(get_config_param(idx), 32);
}
td::Result<std::vector<int>> Config::unpack_param_list(int idx) const {
return unpack_param_dict(*get_param_dict(idx));
}
bool Config::all_mandatory_params_defined(int* bad_idx_ptr) const {
auto res = get_mandatory_param_list();
if (res.is_error()) {
if (bad_idx_ptr) {
*bad_idx_ptr = -1;
}
return false;
}
for (int x : res.move_as_ok()) {
if (get_config_param(x).is_null()) {
if (bad_idx_ptr) {
*bad_idx_ptr = x;
}
return false;
}
}
return true;
}
std::unique_ptr<vm::AugmentedDictionary> ConfigInfo::create_accounts_dict() const {
if (mode & needAccountsRoot) {
return std::make_unique<vm::AugmentedDictionary>(accounts_root, 256, block::tlb::aug_ShardAccounts);

View File

@ -534,6 +534,21 @@ class Config {
bool create_stats_enabled() const {
return has_capability(ton::capCreateStatsEnabled);
}
std::unique_ptr<vm::Dictionary> get_param_dict(int idx) const;
td::Result<std::vector<int>> unpack_param_list(int idx) const;
std::unique_ptr<vm::Dictionary> get_mandatory_param_dict() const {
return get_param_dict(9);
}
std::unique_ptr<vm::Dictionary> get_critical_param_dict() const {
return get_param_dict(10);
}
td::Result<std::vector<int>> get_mandatory_param_list() const {
return unpack_param_list(9);
}
td::Result<std::vector<int>> get_critical_param_list() const {
return unpack_param_list(10);
}
bool all_mandatory_params_defined(int* bad_idx_ptr = nullptr) const;
td::Result<ton::StdSmcAddress> get_dns_root_addr() const;
bool set_block_id_ext(const ton::BlockIdExt& block_id_ext);
td::Result<std::vector<ton::StdSmcAddress>> get_special_smartcontracts(bool without_config = false) const;
@ -580,6 +595,8 @@ class Config {
static td::Result<std::unique_ptr<Config>> extract_from_state(Ref<vm::Cell> mc_state_root, int mode = 0);
static td::Result<std::unique_ptr<Config>> extract_from_key_block(Ref<vm::Cell> key_block_root, int mode = 0);
static td::Result<std::pair<ton::UnixTime, ton::UnixTime>> unpack_validator_set_start_stop(Ref<vm::Cell> root);
static td::Result<std::vector<int>> unpack_param_dict(vm::Dictionary& dict);
static td::Result<std::vector<int>> unpack_param_dict(Ref<vm::Cell> dict_root);
protected:
Config(int _mode) : mode(_mode) {

View File

@ -1555,9 +1555,17 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
Ref<vm::Cell> new_extra;
if (!block::sub_extra_currency(ap.remaining_balance.extra, req.extra, new_extra)) {
LOG(DEBUG) << "not enough extra currency to send with the message";
LOG(DEBUG) << "not enough extra currency to send with the message: "
<< block::CurrencyCollection{0, req.extra}.to_str() << " required, only "
<< block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() << " available";
return skip_invalid ? 0 : 38; // not enough (extra) funds
}
if (ap.remaining_balance.extra.not_null() || req.extra.not_null()) {
LOG(DEBUG) << "subtracting extra currencies: "
<< block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str() << " minus "
<< block::CurrencyCollection{0, req.extra}.to_str() << " equals "
<< block::CurrencyCollection{0, new_extra}.to_str();
}
auto fwd_fee_mine = msg_prices.get_first_part(fwd_fee);
auto fwd_fee_remain = fwd_fee - fwd_fee_mine;
@ -1691,7 +1699,9 @@ int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap,
}
}
if (!block::sub_extra_currency(ap.remaining_balance.extra, reserve.extra, newc.extra)) {
LOG(DEBUG) << "not enough extra currency to reserve";
LOG(DEBUG) << "not enough extra currency to reserve: " << block::CurrencyCollection{0, reserve.extra}.to_str()
<< " required, only " << block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str()
<< " available";
if (mode & 2) {
// TODO: process (mode & 2) correctly by setting res_extra := inf (reserve.extra, ap.remaining_balance.extra)
}
@ -1720,11 +1730,17 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
}
bounce_phase = std::make_unique<BouncePhase>();
BouncePhase& bp = *bounce_phase;
block::gen::Message::Record msg;
block::gen::CommonMsgInfo::Record_int_msg_info info;
if (!tlb::unpack_cell_inexact(in_msg, info)) {
auto cs = vm::load_cell_slice(in_msg);
if (!(tlb::unpack(cs, info) && gen::t_Maybe_Either_StateInit_Ref_StateInit.skip(cs) && cs.have(1) &&
cs.have_refs((int)cs.prefetch_ulong(1)))) {
bounce_phase.reset();
return false;
}
if (cs.fetch_ulong(1)) {
cs = vm::load_cell_slice(cs.prefetch_ref());
}
info.ihr_disabled = true;
info.bounce = false;
info.bounced = true;
@ -1776,10 +1792,26 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
&& block::tlb::t_Grams.store_long(cb, bp.fwd_fees) // fwd_fee:Grams
&& cb.store_long_bool(info.created_lt, 64) // created_lt:uint64
&& cb.store_long_bool(info.created_at, 32) // created_at:uint32
&& cb.store_long_bool(0, 2) // init:(Maybe ...) state:(Either ..)
&& cb.finalize_to(bp.out_msg));
&& cb.store_bool_bool(false)); // init:(Maybe ...)
if (cfg.bounce_msg_body) {
int body_bits = std::min((int)cs.size(), cfg.bounce_msg_body);
if (cb.remaining_bits() >= body_bits + 33u) {
CHECK(cb.store_bool_bool(false) // body:(Either X ^X) -> left X
&& cb.store_long_bool(-1, 32) // int = -1 ("message type")
&& cb.append_bitslice(cs.prefetch_bits(body_bits))); // truncated message body
} else {
vm::CellBuilder cb2;
CHECK(cb.store_bool_bool(true) // body:(Either X ^X) -> right ^X
&& cb2.store_long_bool(-1, 32) // int = -1 ("message type")
&& cb2.append_bitslice(cs.prefetch_bits(body_bits)) // truncated message body
&& cb.store_builder_ref_bool(std::move(cb2))); // ^X
}
} else {
CHECK(cb.store_bool_bool(false)); // body:(Either ..)
}
CHECK(cb.finalize_to(bp.out_msg));
if (verbosity > 2) {
std::cerr << "generated bounced message: ";
LOG(INFO) << "generated bounced message: ";
block::gen::t_Message_Any.print_ref(std::cerr, bp.out_msg);
}
out_msgs.push_back(bp.out_msg);

View File

@ -139,6 +139,7 @@ struct ComputePhaseConfig {
struct ActionPhaseConfig {
int max_actions{255};
int bounce_msg_body{0}; // usually 0 or 256 bits
MsgPrices fwd_std;
MsgPrices fwd_mc; // from/to masterchain
const WorkchainSet* workchains{nullptr};

View File

@ -0,0 +1,50 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2020 Telegram Systems LLP
*/
namespace td {
class LinearAllocator {
std::size_t size;
char *ptr, *cur, *end;
public:
LinearAllocator(std::size_t _size) : size(_size) {
cur = ptr = (char*)malloc(size);
if (!ptr) {
throw std::bad_alloc();
}
end = ptr + size;
}
~LinearAllocator() {
free(ptr);
}
void* allocate(std::size_t count) {
char* t = cur;
cur += (count + 7) & -8;
if (cur > end) {
throw std::bad_alloc();
}
return (void*)t;
}
};
} // namespace td
inline void* operator new(std::size_t count, td::LinearAllocator& alloc) {
return alloc.allocate(count);
}

View File

@ -118,6 +118,24 @@ std::pair<RefInt256, RefInt256> divmod(RefInt256 x, RefInt256 y, int round_mode)
return std::make_pair(std::move(quot), std::move(x));
}
RefInt256 muldiv(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode) {
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
RefInt256 quot{true};
tmp.mod_div(*z, quot.unique_write(), round_mode);
quot.write().normalize();
return quot;
}
std::pair<RefInt256, RefInt256> muldivmod(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode) {
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
RefInt256 quot{true};
tmp.mod_div(*z, quot.unique_write(), round_mode);
quot.write().normalize();
return std::make_pair(std::move(quot), td::make_refint(tmp));
}
RefInt256 operator&(RefInt256 x, RefInt256 y) {
x.write() &= *y;
return x;

View File

@ -45,6 +45,8 @@ extern RefInt256 operator%(RefInt256 x, RefInt256 y);
extern RefInt256 div(RefInt256 x, RefInt256 y, int round_mode = -1);
extern RefInt256 mod(RefInt256 x, RefInt256 y, int round_mode = -1);
extern std::pair<RefInt256, RefInt256> divmod(RefInt256 x, RefInt256 y, int round_mode = -1);
extern RefInt256 muldiv(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode = -1);
extern std::pair<RefInt256, RefInt256> muldivmod(RefInt256 x, RefInt256 y, RefInt256 z, int round_mode = -1);
extern RefInt256 operator-(RefInt256 x);
extern RefInt256 operator&(RefInt256 x, RefInt256 y);
extern RefInt256 operator|(RefInt256 x, RefInt256 y);

View File

@ -1,7 +1,7 @@
library TVM_Asm
// simple TVM Assembler
variable @atend
'nop @atend !
{ "not in asm context" abort } @atend !
{ `normal eq? not abort"must be terminated by }>" } : @normal?
{ @atend @ 1 { @atend ! @normal? } does @atend ! } : @pushatend
{ @pushatend <b } : <{
@ -12,10 +12,11 @@ variable @atend
{ @atend @ 2 { @atend ! rot b> ref, swap @endblk } does @atend ! <b } : @|
{ @atend @ 3 { @atend ! 2swap rot execute } does @atend ! <b } : @doafter<{
{ over brembits <= } : @havebits
{ rot + -rot + swap } : pair+
{ rot >= -rot <= and } : 2x<=
{ 2 pick brembitrefs 1- 2x<= } : @havebitrefs
{ @havebits not ' @| if } : @ensurebits
{ @havebitrefs not ' @| if } : @ensurebitrefs
{ @havebits ' @| ifnot } : @ensurebits
{ @havebitrefs ' @| ifnot } : @ensurebitrefs
{ rot over @ensurebits -rot u, } : @simpleuop
{ tuck sbitrefs @ensurebitrefs swap s, } : @addop
{ tuck bbitrefs @ensurebitrefs swap b+ } : @addopb
@ -27,6 +28,7 @@ variable @atend
{ 1 { <b swap s, swap 4 u, @addopb } does create } : @Defop(4u)
{ 1 { <b swap s, rot 4 u, swap 4 u, @addopb } does create } : @Defop(4u,4u)
{ 1 { <b swap s, swap ref, @addopb } does create } : @Defop(ref)
{ 1 { <b swap s, rot ref, swap ref, @addopb } does create } : @Defop(ref*2)
{ <b 0xef 8 u, swap 12 i, b> } : si()
// x mi ma -- ?
{ rot tuck >= -rot <= and } : @range
@ -272,10 +274,27 @@ x{8A} @Defop(ref) PUSHREFCONT
} cond
} cond
} dup : PUSHSLICE : SLICE
{ tuck bbitrefs swap 16 + dup 7 and 3 -roll swap @havebitrefs
not rot or
{ swap b> PUSHREFCONT }
{ over bbitrefs 2dup 120 0 2x<=
// ( b' -- ? )
{ bbitrefs or 0= } : @cont-empty?
{ bbits 7 and 0= } : @cont-aligned?
// ( b b' -- ? )
{ bbitrefs over 7 and { 2drop drop false } {
swap 16 + swap @havebitrefs nip
} cond
} : @cont-fits?
// ( b b' -- ? )
{ bbitrefs over 7 and { 2drop drop false } {
32 1 pair+ @havebitrefs nip
} cond
} : @cont-ref-fit?
// ( b b' b'' -- ? )
{ over @cont-aligned? over @cont-aligned? and not { 2drop drop false } {
bbitrefs rot bbitrefs pair+ swap 32 + swap @havebitrefs nip
} cond
} : @two-cont-fit?
{ 2dup @cont-fits? not
{ b> PUSHREFCONT }
{ swap over bbitrefs 2dup 120 0 2x<=
{ drop swap x{9} s, swap 3 >> 4 u, swap b+ }
{ rot x{8F_} s, swap 2 u, swap 3 >> 7 u, swap b+ } cond
} cond
@ -320,12 +339,16 @@ x{A985} @Defop MULDIVR
x{A98C} @Defop MULDIVMOD
x{A9A4} @Defop MULRSHIFT
x{A9A5} @Defop MULRSHIFTR
x{A9A6} @Defop MULRSHIFTC
x{A9B4} @Defop(8u+1) MULRSHIFT#
x{A9B5} @Defop(8u+1) MULRSHIFTR#
x{A9B6} @Defop(8u+1) MULRSHIFTC#
x{A9C4} @Defop LSHIFTDIV
x{A9C5} @Defop LSHIFTDIVR
x{A9C6} @Defop LSHIFTDIVC
x{A9D4} @Defop(8u+1) LSHIFT#DIV
x{A9D5} @Defop(8u+1) LSHIFT#DIVR
x{A9D6} @Defop(8u+1) LSHIFT#DIVC
x{AA} @Defop(8u+1) LSHIFT#
x{AB} @Defop(8u+1) RSHIFT#
x{AC} @Defop LSHIFT
@ -628,46 +651,80 @@ x{DB3F} @Defop RETDATA
x{DC} @Defop IFRET
x{DD} @Defop IFNOTRET
x{DE} @Defop IF
{ }> PUSHCONT IF } : }>IF
x{DF} @Defop IFNOT
{ }> PUSHCONT IFNOT } : }>IFNOT
' IFNOTRET : IF:
' IFRET : IFNOT:
x{E0} @Defop IFJMP
{ }> PUSHCONT IFJMP } : }>IFJMP
{ { @normal? PUSHCONT IFJMP } @doafter<{ } : IFJMP:<{
x{E1} @Defop IFNOTJMP
{ }> PUSHCONT IFNOTJMP } : }>IFNOTJMP
{ { @normal? PUSHCONT IFNOTJMP } @doafter<{ } : IFNOTJMP:<{
x{E2} @Defop IFELSE
{ `else @endblk } : }>ELSE<{
{ `else: @endblk } : }>ELSE:
{ PUSHCONT { @normal? PUSHCONT IFELSE } @doafter<{ } : @doifelse
{ 1 { swap @normal? -rot PUSHCONT swap PUSHCONT IFELSE } does @doafter<{ } : @doifnotelse
{
{ dup `else eq?
{ drop @doifelse }
{ dup `else: eq?
{ drop PUSHCONT IFJMP }
{ @normal? PUSHCONT IF
} cond
} cond
} @doafter<{
} : IF:<{
{
{ dup `else eq?
{ drop @doifnotelse }
{ dup `else: eq?
{ drop PUSHCONT IFNOTJMP }
{ @normal? PUSHCONT IFNOT
} cond
} cond
} @doafter<{
} : IFNOT:<{
x{E300} @Defop(ref) IFREF
x{E301} @Defop(ref) IFNOTREF
x{E302} @Defop(ref) IFJMPREF
x{E303} @Defop(ref) IFNOTJMPREF
x{E30D} @Defop(ref) IFREFELSE
x{E30E} @Defop(ref) IFELSEREF
x{E30F} @Defop(ref*2) IFREFELSEREF
{ 16 1 @havebitrefs nip } : @refop-fits?
// b b1 [e0 e1 e2] -- b'
{ -rot dup @cont-empty? { drop swap 0 } {
2dup @cont-fits? { rot 1 } {
over @refop-fits? { b> rot 2 } {
swap @| swap 2dup @cont-fits? { rot 1 } {
b> rot 2
} cond } cond } cond } cond
[] execute
} : @run-cont-op
{ triple 1 ' @run-cont-op does create } : @def-cont-op
{ } { PUSHCONT IF } { IFREF } @def-cont-op IF-cont
{ IFRET } { PUSHCONT IFJMP } { IFJMPREF } @def-cont-op IFJMP-cont
{ } { PUSHCONT IFNOT } { IFNOTREF } @def-cont-op IFNOT-cont
{ IFNOTRET } { PUSHCONT IFNOTJMP } { IFNOTJMPREF } @def-cont-op IFNOTJMP-cont
{ dup 2over rot } : 3dup
recursive IFELSE-cont2 {
dup @cont-empty? { drop IF-cont } {
over @cont-empty? { nip IFNOT-cont } {
3dup @two-cont-fit? { -rot PUSHCONT swap PUSHCONT IFELSE } {
3dup nip @cont-ref-fit? { rot swap PUSHCONT swap b> IFREFELSE } {
3dup drop @cont-ref-fit? { -rot PUSHCONT swap b> IFELSEREF } {
rot 32 2 @havebitrefs { rot b> rot b> IFREFELSEREF } {
@| -rot IFELSE-cont2
} cond } cond } cond } cond } cond } cond
} swap !
{ }> IF-cont } : }>IF
{ }> IFNOT-cont } : }>IFNOT
{ }> IFJMP-cont } : }>IFJMP
{ }> IFNOTJMP-cont } : }>IFNOTJMP
{ { @normal? IFJMP-cont } @doafter<{ } : IFJMP:<{
{ { @normal? IFNOTJMP-cont } @doafter<{ } : IFNOTJMP:<{
{ `else @endblk } : }>ELSE<{
{ `else: @endblk } : }>ELSE:
{ 1 { swap @normal? swap IFELSE-cont2 } does @doafter<{ } : @doifelse
{ 1 { swap @normal? IFELSE-cont2 } does @doafter<{ } : @doifnotelse
{
{ dup `else eq?
{ drop @doifelse }
{ dup `else: eq?
{ drop IFJMP-cont }
{ @normal? IF-cont
} cond
} cond
} @doafter<{
} : IF:<{
{
{ dup `else eq?
{ drop @doifnotelse }
{ dup `else: eq?
{ drop IFNOTJMP-cont }
{ @normal? IFNOT-cont
} cond
} cond
} @doafter<{
} : IFNOT:<{
x{E304} @Defop CONDSEL
x{E305} @Defop CONDSELCHK
x{E308} @Defop IFRETALT
@ -676,18 +733,22 @@ x{E309} @Defop IFNOTRETALT
{ <b x{E3B_} swap 5 u, @addopb } : IFNBITJMP
{ <b x{E3D_} swap 5 u, swap ref, @addopb } : IFBITJMPREF
{ <b x{E3F_} swap 5 u, swap ref, @addopb } : IFNBITJMPREF
x{E4} @Defop REPEAT
{ }> PUSHCONT REPEAT } : }>REPEAT
{ { @normal? PUSHCONT REPEAT } @doafter<{ } : REPEAT:<{
x{E5} dup @Defop REPEATEND @Defop REPEAT:
x{E6} @Defop UNTIL
{ }> PUSHCONT UNTIL } : }>UNTIL
{ { @normal? PUSHCONT UNTIL } @doafter<{ } : UNTIL:<{
x{E7} dup @Defop UNTILEND @Defop UNTIL:
x{E8} @Defop WHILE
x{E9} @Defop WHILEEND
x{EA} @Defop AGAIN
x{EB} dup @Defop AGAINEND @Defop AGAIN:
{ `do @endblk } : }>DO<{
{ `do: @endblk } : }>DO:
{ }> PUSHCONT REPEAT } : }>REPEAT
{ { @normal? PUSHCONT REPEAT } @doafter<{ } : REPEAT:<{
{ }> PUSHCONT UNTIL } : }>UNTIL
{ { @normal? PUSHCONT UNTIL } @doafter<{ } : UNTIL:<{
{ PUSHCONT { @normal? PUSHCONT WHILE } @doafter<{ } : @dowhile
{
{ dup `do eq?
@ -696,10 +757,34 @@ x{E9} @Defop WHILEEND
} cond
} @doafter<{
} : WHILE:<{
x{EA} @Defop AGAIN
{ }> PUSHCONT AGAIN } : }>AGAIN
{ { @normal? PUSHCONT AGAIN } @doafter<{ } : AGAIN:<{
x{EB} dup @Defop AGAINEND @Defop AGAIN:
x{E314} @Defop REPEATBRK
x{E315} @Defop REPEATENDBRK
x{E316} @Defop UNTILBRK
x{E317} dup @Defop UNTILENDBRK @Defop UNTILBRK:
x{E318} @Defop WHILEBRK
x{E319} @Defop WHILEENDBRK
x{E31A} @Defop AGAINBRK
x{E31B} dup @Defop AGAINENDBRK @Defop AGAINBRK:
{ }> PUSHCONT REPEATBRK } : }>REPEATBRK
{ { @normal? PUSHCONT REPEATBRK } @doafter<{ } : REPEATBRK:<{
{ }> PUSHCONT UNTILBRK } : }>UNTILBRK
{ { @normal? PUSHCONT UNTILBRK } @doafter<{ } : UNTILBRK:<{
{ PUSHCONT { @normal? PUSHCONT WHILEBRK } @doafter<{ } : @dowhile
{
{ dup `do eq?
{ drop @dowhile }
{ `do: eq? not abort"`}>DO<{` expected" PUSHCONT WHILEENDBRK
} cond
} @doafter<{
} : WHILEBRK:<{
{ }> PUSHCONT AGAINBRK } : }>AGAINBRK
{ { @normal? PUSHCONT AGAINBRK } @doafter<{ } : AGAINBRK:<{
//
// continuation stack manipulation and continuation creation
//
@ -745,6 +830,8 @@ x{EDF6} @Defop THENRET
x{EDF7} @Defop THENRETALT
x{EDF8} @Defop INVERT
x{EDF9} @Defop BOOLEVAL
x{EDFA} @Defop SAMEALT
x{EDFB} @Defop SAMEALTSAVE
// x{EE} is BLESSARGS
//
// dictionary subroutine call/jump primitives

View File

@ -111,6 +111,8 @@ variable base
{ cdr cdr } : cddr
{ cdr cdr car } : caddr
{ null ' cons rot times } : list
{ -rot pair swap ! } : 2!
{ @ unpair } : 2@
{ true (atom) drop } : atom
{ bl word atom 1 'nop } ::_ `
{ hole dup 1 { @ execute } does create } : recursive
@ -121,13 +123,18 @@ variable base
{ 0 word -trailing scan-until-word 1 'nop } ::_ $<<
{ 0x40 runvmx } : runvmcode
{ 0x48 runvmx } : gasrunvmcode
{ 0xc8 runvmx } : gas2runvmcode
{ 0x43 runvmx } : runvmdict
{ 0x4b runvmx } : gasrunvmdict
{ 0xcb runvmx } : gas2runvmdict
{ 0x45 runvmx } : runvm
{ 0x4d runvmx } : gasrunvm
{ 0xcd runvmx } : gas2runvm
{ 0x55 runvmx } : runvmctx
{ 0x5d runvmx } : gasrunvmctx
{ 0xdd runvmx } : gas2runvmctx
{ 0x75 runvmx } : runvmctxact
{ 0x7d runvmx } : gasrunvmctxact
{ 0xfd runvmx } : gas2runvmctxact
{ 0x35 runvmx } : runvmctxactq
{ 0x3d runvmx } : gasrunvmctxactq

View File

@ -111,6 +111,42 @@ recursive list-map {
swap uncons -rot over execute -rot list-map cons
} cond
} swap !
variable ctxdump variable curctx
// (a1 .. an) e -- executes e for a1, ..., an
{ ctxdump @ curctx @ ctxdump 2! curctx 2!
{ curctx 2@ over null? not } { swap uncons rot tuck curctx 2! execute }
while 2drop ctxdump 2@ curctx ! ctxdump !
} : list-foreach
forget ctxdump forget curctx
//
// Experimental implementation of `for` loops with index
//
variable loopdump variable curloop
{ curloop @ loopdump @ loopdump 2! } : push-loop-ctx
{ loopdump 2@ loopdump ! curloop ! } : pop-loop-ctx
// ilast i0 e -- executes e for i=i0,i0+1,...,ilast-1
{ -rot 2dup > {
push-loop-ctx {
triple dup curloop ! first execute curloop @ untriple 1+ 2dup <=
} until pop-loop-ctx
} if 2drop drop
} : for
// ilast i0 e -- same as 'for', but pushes current index i before executing e
{ -rot 2dup > {
push-loop-ctx {
triple dup curloop ! untriple nip swap execute curloop @ untriple 1+ 2dup <=
} until pop-loop-ctx
} if 2drop drop
} : for-i
// ( -- i ) Returns innermost loop index
{ curloop @ third } : i
// ( -- j ) Returns outer loop index
{ loopdump @ car third } : j
{ loopdump @ cadr third } : k
forget curloop forget loopdump
//
// create Lisp-style lists using words "(" and ")"
//

View File

@ -77,15 +77,17 @@ library TonUtil // TON Blockchain Fift Library
1000000000 constant Gram
{ Gram swap */r } : Gram*/
{ Gram * } : Gram*
{ (number) dup { 1- ' Gram*/ ' Gram* cond true } if
} : $>GR?
// ( S -- nanograms )
{ (number) ?dup 0= abort"not a valid Gram amount"
1- ' Gram*/ ' Gram* cond
{ $>GR? not abort"not a valid Gram amount"
} : $>GR
{ bl word $>GR 1 'nop } ::_ GR$
// ( nanograms -- S )
{ dup abs <# ' # 9 times char . hold #s rot sign #>
nip -trailing0 } : (.GR)
{ (.GR) ."GR$" type space } : .GR
{ (.GR) ."GR$" type } : .GR_
{ .GR_ space } : .GR
// b x -- b' ( serializes a Gram amount )
{ -1 { 1+ 2dup 8 * ufits } until
@ -105,19 +107,66 @@ nip -trailing0 } : (.GR)
' VarUInt32, : val,
' VarUInt32@ : val@
// d k v -- d'
{ <b swap val, b> <s swap rot cc-key-bits idict! not abort"cannot add key-value to CurrencyCollection" } : +ccpair
{ <b swap val, b> <s swap rot cc-key-bits idict!+ not abort"cannot add key-value to CurrencyCollection"
} : +newccpair
{ dup { -rot tuck swap cc-key-bits idict@- { val@ 2swap -rot + } { swap rot } cond +newccpair
} { 2drop } cond
} : +ccpair
dictnew constant cc0 // zero currency collection
// ( v k -- d ) Creates currency collection representing v units of currency k
{ cc0 swap rot +ccpair } : of-cc
{ dictnew { over null? not } { swap uncons -rot unpair +ccpair } while nip } : list>cc
{ dup null? { ."(null) " drop } { val@ . } cond } dup : .maybeVarUInt32 : .val
{ cc-key-bits { swap 32 1<< rmod . ."-> " .val ."; " true } dictforeach drop cr } : .cc
{ dup null? { ."(null)" drop } { val@ ._ } cond } dup : .maybeVarUInt32 : .val
{ swap cc-key-bits { rot { ."+" } if .val ."*$" ._ true true } idictforeach drop } : (.cc)
{ false (.cc) { ."0" } ifnot } : .cc_
{ .cc_ space } : .cc
{ true (.cc) drop } : .+cc_
{ .+cc_ space } : .+cc
{ cc-key-bits { rot . ."-> " swap .val .val ."; " true } dictdiff drop cr } : show-cc-diff
{ cc-key-bits { val@ swap val@ + val, true } dictmerge } : cc+
{ null swap cc-key-bits { val@ pair swap cons true } dictforeach drop } : cc>list-rev
{ null swap cc-key-bits { val@ pair swap cons true } idictforeach drop } : cc>list-rev
{ cc>list-rev list-reverse } : cc>list
forget val, forget val@ forget .val
// ( S -- x -1 or 0 )
{ (number) dup 2 = { -rot 2drop } if 1 = } : int?
{ int? dup { drop dup 0< { drop false } { true } cond } if } : pos-int?
// ( S -- k v -1 or 0 ) Parses expression <value>*<currency> or <value>*$<currency>
{ dup "*" $pos dup 0< { 2drop false } {
$| dup $len 2 < { 2drop false } {
1 $| nip dup 1 $| swap "$" $= { swap } if drop
int? dup { over 32 fits { 2drop false } ifnot } if
not { drop false } {
swap pos-int? not { drop false } {
true
} cond } cond } cond } cond
} : cc-key-value?
// ( S -- D -1 or 0 ) Parses an extra currency collection
// e.g. "10000*$3+7777*$-11" means "10000 units of currency #3 and 7777 units of currency #-11"
{ dictnew { // S D
swap dup "+" $pos dup 0< { drop null -rot } { $| 1 $| nip -rot } cond
cc-key-value? { +ccpair over null? dup { rot drop true } if } { 2drop false true } cond
} until
} : $>xcc?
{ $>xcc? not abort"invalid extra currency collection" } : $>xcc
{ char } word dup $len { $>xcc } { drop dictnew } cond 1 'nop } ::_ CX{
// complete currency collections
{ $>xcc? { true } { drop false } cond } : end-parse-cc
// ( S -- x D -1 or 0 ) Parses a currency collection
// e.g. "1.2+300*$2" means "1200000000ng plus 300 units of currency #2"
{ 0 swap dup "+" $pos dup 0< { drop dup
$>GR? { nip nip dictnew true } { end-parse-cc } cond
} { over swap $| swap $>GR? { 2swap 2drop swap 1 $| nip } { drop
} cond end-parse-cc } cond
} : $>cc?
{ $>cc? not abort"invalid currency collection" } : $>cc
{ char } word dup $len { $>cc } { drop 0 dictnew } cond 2 'nop } ::_ CC{
// ( x D -- )
{ swap ?dup { .GR_ .+cc_ } { .cc_ } cond } : .GR+cc_
{ .GR+cc_ space } : .GR+cc
{ -rot Gram, swap dict, } : Gram+cc,
// Libraries
// ( -- D ) New empty library collection
' dictnew : Libs{

View File

@ -177,28 +177,15 @@ void interpret_divmod(vm::Stack& stack, int round_mode) {
}
void interpret_times_div(vm::Stack& stack, int round_mode) {
auto z = stack.pop_int();
auto y = stack.pop_int();
auto x = stack.pop_int();
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int(std::move(q));
auto z = stack.pop_int(), y = stack.pop_int(), x = stack.pop_int();
stack.push_int(muldiv(std::move(x), std::move(y), std::move(z), round_mode));
}
void interpret_times_divmod(vm::Stack& stack, int round_mode) {
auto z = stack.pop_int();
auto y = stack.pop_int();
auto x = stack.pop_int();
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int(std::move(q));
stack.push_int(td::make_refint(tmp));
auto z = stack.pop_int(), y = stack.pop_int(), x = stack.pop_int();
auto dm = muldivmod(std::move(x), std::move(y), std::move(z));
stack.push_int(std::move(dm.first));
stack.push_int(std::move(dm.second));
}
void interpret_times_mod(vm::Stack& stack, int round_mode) {
@ -2242,6 +2229,7 @@ std::vector<Ref<vm::Cell>> get_vm_libraries() {
// +16 = load c7 (smart-contract context)
// +32 = return c5 (actions)
// +64 = log vm ops to stderr
// +128 = pop hard gas limit (enabled by ACCEPT) from stack as well
void interpret_run_vm(IntCtx& ctx, int mode) {
if (mode < 0) {
mode = ctx.stack.pop_smallint_range(0xff);
@ -2249,7 +2237,13 @@ void interpret_run_vm(IntCtx& ctx, int mode) {
bool with_data = mode & 4;
Ref<vm::Tuple> c7;
Ref<vm::Cell> data, actions;
long long gas_max = (mode & 128) ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
long long gas_limit = (mode & 8) ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
if (!(mode & 128)) {
gas_max = gas_limit;
} else {
gas_max = std::max(gas_max, gas_limit);
}
if (mode & 16) {
c7 = ctx.stack.pop_tuple();
}
@ -2259,7 +2253,7 @@ void interpret_run_vm(IntCtx& ctx, int mode) {
auto cs = ctx.stack.pop_cellslice();
OstreamLogger ostream_logger(ctx.error_stream);
auto log = create_vm_log((mode & 64) && ctx.error_stream ? &ostream_logger : nullptr);
vm::GasLimits gas{gas_limit};
vm::GasLimits gas{gas_limit, gas_max};
int res =
vm::run_vm_code(cs, ctx.stack, mode & 3, &data, log, nullptr, &gas, get_vm_libraries(), std::move(c7), &actions);
ctx.stack.push_smallint(res);

View File

@ -427,9 +427,7 @@ AsmOp compile_negate(std::vector<VarDescr>& res, std::vector<VarDescr>& args) {
return exec_op("NEGATE", 1);
}
AsmOp compile_mul(std::vector<VarDescr>& res, std::vector<VarDescr>& args) {
assert(res.size() == 1 && args.size() == 2);
VarDescr &r = res[0], &x = args[0], &y = args[1];
AsmOp compile_mul_internal(VarDescr& r, VarDescr& x, VarDescr& y) {
if (x.is_int_const() && y.is_int_const()) {
r.set_const(x.int_const * y.int_const);
x.unused();
@ -492,6 +490,11 @@ AsmOp compile_mul(std::vector<VarDescr>& res, std::vector<VarDescr>& args) {
return exec_op("MUL", 2);
}
AsmOp compile_mul(std::vector<VarDescr>& res, std::vector<VarDescr>& args) {
assert(res.size() == 1 && args.size() == 2);
return compile_mul_internal(res[0], args[0], args[1]);
}
AsmOp compile_lshift(std::vector<VarDescr>& res, std::vector<VarDescr>& args) {
assert(res.size() == 1 && args.size() == 2);
VarDescr &r = res[0], &x = args[0], &y = args[1];
@ -566,9 +569,7 @@ AsmOp compile_rshift(std::vector<VarDescr>& res, std::vector<VarDescr>& args, in
return exec_op(rshift, 2);
}
AsmOp compile_div(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int round_mode) {
assert(res.size() == 1 && args.size() == 2);
VarDescr &r = res[0], &x = args[0], &y = args[1];
AsmOp compile_div_internal(VarDescr& r, VarDescr& x, VarDescr& y, int round_mode) {
if (x.is_int_const() && y.is_int_const()) {
r.set_const(div(x.int_const, y.int_const, round_mode));
x.unused();
@ -608,6 +609,11 @@ AsmOp compile_div(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int r
return exec_op(op, 2);
}
AsmOp compile_div(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int round_mode) {
assert(res.size() == 1 && args.size() == 2);
return compile_div_internal(res[0], args[0], args[1], round_mode);
}
AsmOp compile_mod(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int round_mode) {
assert(res.size() == 1 && args.size() == 2);
VarDescr &r = res[0], &x = args[0], &y = args[1];
@ -648,6 +654,87 @@ AsmOp compile_mod(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int r
return exec_op(op, 2);
}
AsmOp compile_muldiv(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int round_mode) {
assert(res.size() == 1 && args.size() == 3);
VarDescr &r = res[0], &x = args[0], &y = args[1], &z = args[2];
if (x.is_int_const() && y.is_int_const() && z.is_int_const()) {
r.set_const(muldiv(x.int_const, y.int_const, z.int_const, round_mode));
x.unused();
y.unused();
z.unused();
return push_const(r.int_const);
}
if (x.always_zero() || y.always_zero()) {
// dubious optimization for z=0...
x.unused();
y.unused();
z.unused();
r.set_const(td::make_refint(0));
return push_const(r.int_const);
}
char c = (round_mode < 0) ? 0 : (round_mode > 0 ? 'C' : 'R');
r.val = emulate_div(emulate_mul(x.val, y.val), z.val);
if (z.is_int_const()) {
if (*z.int_const == 0) {
x.unused();
y.unused();
z.unused();
r.set_const(div(z.int_const, z.int_const));
return push_const(r.int_const);
}
if (*z.int_const == 1) {
z.unused();
return compile_mul_internal(r, x, y);
}
}
if (y.is_int_const() && *y.int_const == 1) {
y.unused();
return compile_div_internal(r, x, z, round_mode);
}
if (x.is_int_const() && *x.int_const == 1) {
x.unused();
return compile_div_internal(r, y, z, round_mode);
}
if (z.is_int_const()) {
int k = is_pos_pow2(z.int_const);
if (k > 0) {
z.unused();
std::string op = "MULRSHIFT";
if (c) {
op += c;
}
return exec_arg_op(op + '#', k, 2);
}
}
if (y.is_int_const()) {
int k = is_pos_pow2(y.int_const);
if (k > 0) {
y.unused();
std::string op = "LSHIFT#DIV";
if (c) {
op += c;
}
return exec_arg_op(op, k, 2);
}
}
if (x.is_int_const()) {
int k = is_pos_pow2(x.int_const);
if (k > 0) {
x.unused();
std::string op = "LSHIFT#DIV";
if (c) {
op += c;
}
return exec_arg_op(op, k, 2);
}
}
std::string op = "MULDIV";
if (c) {
op += c;
}
return exec_op(op, 3);
}
int compute_compare(td::RefInt256 x, td::RefInt256 y, int mode) {
int s = td::cmp(x, y);
if (mode == 7) {
@ -933,8 +1020,9 @@ void define_builtins() {
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));
define_builtin_func("muldivr", TypeExpr::new_map(Int3, Int), AsmOp::Custom("MULDIVR", 3));
define_builtin_func("muldiv", TypeExpr::new_map(Int3, Int), AsmOp::Custom("MULDIV", 3));
define_builtin_func("muldiv", TypeExpr::new_map(Int3, Int), std::bind(compile_muldiv, _1, _2, -1));
define_builtin_func("muldivr", TypeExpr::new_map(Int3, Int), std::bind(compile_muldiv, _1, _2, 0));
define_builtin_func("muldivc", TypeExpr::new_map(Int3, Int), std::bind(compile_muldiv, _1, _2, 1));
define_builtin_func("muldivmod", TypeExpr::new_map(Int3, Int2), AsmOp::Custom("MULDIVMOD", 3, 2));
define_builtin_func("_==_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 2));
define_builtin_func("_!=_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 5));

View File

@ -575,9 +575,9 @@ bool Optimizer::find_at_least(int pb) {
(is_push_rotrev(&i) && rewrite(AsmOp::Push(i), AsmOp::Custom("-ROT"))) ||
(is_push_xchg(&i, &j, &k) && rewrite(AsmOp::Push(i), AsmOp::Xchg(j, k))) ||
(is_reverse(&i, &j) && rewrite(AsmOp::BlkReverse(i, j))) ||
(is_blkdrop2(&i, &j) && rewrite(AsmOp::BlkDrop2(i, j))) ||
(is_nip_seq(&i, &j) && rewrite(AsmOp::Xchg(i, j), AsmOp::BlkDrop(i))) ||
(is_pop_blkdrop(&i, &k) && rewrite(AsmOp::Pop(i), AsmOp::BlkDrop(k))) ||
(is_blkdrop2(&i, &j) && rewrite(AsmOp::BlkDrop2(i, j))) ||
(is_2pop_blkdrop(&i, &j, &k) && (k >= 3 && k <= 13 && i != j + 1 && i <= 15 && j <= 14
? rewrite(AsmOp::Xchg2(j + 1, i), AsmOp::BlkDrop(k + 2))
: rewrite(AsmOp::Pop(i), AsmOp::Pop(j), AsmOp::BlkDrop(k)))) ||

View File

@ -1288,7 +1288,9 @@ void parse_func_def(Lexer& lex) {
sym::close_scope(lex);
}
bool parse_source(std::istream* is, const src::FileDescr* fdescr) {
std::vector<const src::FileDescr*> source_fdescr;
bool parse_source(std::istream* is, src::FileDescr* fdescr) {
src::SourceReader reader{is, fdescr};
Lexer lex{reader, true, ";,()[] ~."};
while (lex.tp() != _Eof) {
@ -1306,6 +1308,7 @@ bool parse_source_file(const char* filename) {
throw src::Fatal{"source file name is an empty string"};
}
src::FileDescr* cur_source = new src::FileDescr{filename};
source_fdescr.push_back(cur_source);
std::ifstream ifs{filename};
if (ifs.fail()) {
throw src::Fatal{std::string{"cannot open source file `"} + filename + "`"};
@ -1314,7 +1317,9 @@ bool parse_source_file(const char* filename) {
}
bool parse_source_stdin() {
return parse_source(&std::cin, new src::FileDescr{"stdin", true});
src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
source_fdescr.push_back(cur_source);
return parse_source(&std::cin, cur_source);
}
} // namespace funC

View File

@ -14,9 +14,10 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "srcread.h"
#include <algorithm>
namespace src {
@ -34,9 +35,47 @@ std::ostream& operator<<(std::ostream& os, const Fatal& fatal) {
return os << fatal.get_msg();
}
const char* FileDescr::convert_offset(long offset, long* line_no, long* line_pos, long* line_size) const {
long lno = 0, lpos = -1, lsize = 0;
const char* lstart = nullptr;
if (offset >= 0 && offset < (long)text.size()) {
auto it = std::upper_bound(line_offs.begin(), line_offs.end(), offset);
lno = it - line_offs.begin();
if (lno && it != line_offs.end()) {
lsize = it[0] - it[-1];
lpos = offset - it[-1];
lstart = text.data() + it[-1];
}
} else {
lno = (long)line_offs.size();
}
if (line_no) {
*line_no = lno;
}
if (line_pos) {
*line_pos = lpos;
}
if (line_size) {
*line_size = lsize;
}
return lstart;
}
const char* FileDescr::push_line(std::string new_line) {
if (line_offs.empty()) {
line_offs.push_back(0);
}
std::size_t cur_size = text.size();
text += new_line;
text += '\0';
line_offs.push_back((long)text.size());
return text.data() + cur_size;
}
void SrcLocation::show(std::ostream& os) const {
os << fdescr;
if (line_no > 0) {
long line_no, line_pos;
if (fdescr && convert_pos(&line_no, &line_pos)) {
os << ':' << line_no;
if (line_pos >= 0) {
os << ':' << (line_pos + 1);
@ -45,13 +84,15 @@ void SrcLocation::show(std::ostream& os) const {
}
bool SrcLocation::show_context(std::ostream& os) const {
if (text.empty() || line_pos < 0 || (unsigned)line_pos > text.size()) {
long line_no, line_pos, line_size;
if (!fdescr || !convert_pos(&line_no, &line_pos, &line_size)) {
return false;
}
bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < text.size());
const char* start = skip_left ? text.c_str() + line_pos - 100 : text.c_str();
const char* end = skip_right ? text.c_str() + line_pos + 100 : text.c_str() + text.size();
const char* here = text.c_str() + line_pos;
bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < line_size);
const char* here = fdescr->text.data() + char_offs;
const char* base = here - line_pos;
const char* start = skip_left ? here - 100 : base;
const char* end = skip_right ? here + 100 : base + line_size;
os << " ";
if (skip_left) {
os << "... ";
@ -99,8 +140,8 @@ void ParseError::show(std::ostream& os) const {
where.show_context(os);
}
SourceReader::SourceReader(std::istream* _is, const FileDescr* _fdescr)
: ifs(_is), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) {
SourceReader::SourceReader(std::istream* _is, FileDescr* _fdescr)
: ifs(_is), fdescr(_fdescr), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) {
load_line();
}
@ -139,7 +180,7 @@ const char* SourceReader::set_ptr(const char* ptr) {
if (ptr < cur || ptr > end) {
error("parsing position went outside of line");
}
loc.line_pos = (int)(ptr - start);
loc.char_offs += ptr - cur;
cur = ptr;
}
return ptr;
@ -149,12 +190,11 @@ bool SourceReader::load_line() {
if (eof) {
return false;
}
loc.set_eof();
if (ifs->eof()) {
set_eof();
return false;
}
++loc.line_no;
loc.line_pos = -1;
std::getline(*ifs, cur_line);
if (ifs->fail()) {
set_eof();
@ -174,11 +214,16 @@ bool SourceReader::load_line() {
cur_line.pop_back();
--len;
}
loc.text = cur_line;
cur_line_len = (int)len;
loc.line_pos = 0;
cur = start = cur_line.c_str();
end = start + cur_line_len;
if (fdescr) {
cur = start = fdescr->push_line(std::move(cur_line));
end = start + len;
loc.char_offs = (std::size_t)(cur - fdescr->text.data());
cur_line.clear();
} else {
cur = start = cur_line.c_str();
end = start + cur_line_len;
}
return true;
}

View File

@ -14,11 +14,12 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include <string>
#include <vector>
#include <iostream>
namespace src {
@ -31,9 +32,13 @@ namespace src {
struct FileDescr {
std::string filename;
std::string text;
std::vector<long> line_offs;
bool is_stdin;
FileDescr(std::string _fname, bool _stdin = false) : filename(std::move(_fname)), is_stdin(_stdin) {
}
const char* push_line(std::string new_line);
const char* convert_offset(long offset, long* line_no, long* line_pos, long* line_size = nullptr) const;
};
struct Fatal {
@ -49,16 +54,23 @@ std::ostream& operator<<(std::ostream& os, const Fatal& fatal);
struct SrcLocation {
const FileDescr* fdescr;
int line_no;
int line_pos;
std::string text;
SrcLocation() : fdescr(nullptr), line_no(0), line_pos(-1) {
long char_offs;
SrcLocation() : fdescr(nullptr), char_offs(-1) {
}
SrcLocation(const FileDescr* _fdescr, int line = 0, int pos = -1) : fdescr(_fdescr), line_no(line), line_pos(pos) {
SrcLocation(const FileDescr* _fdescr, long offs = -1) : fdescr(_fdescr), char_offs(-1) {
}
bool defined() const {
return fdescr;
}
bool eof() const {
return char_offs == -1;
}
void set_eof() {
char_offs = -1;
}
const char* convert_pos(long* line_no, long* line_pos, long* line_size = nullptr) const {
return defined() ? fdescr->convert_offset(char_offs, line_no, line_pos, line_size) : nullptr;
}
void show(std::ostream& os) const;
bool show_context(std::ostream& os) const;
void show_gen_error(std::ostream& os, std::string message, std::string err_type = "") const;
@ -98,6 +110,7 @@ struct ParseError : Error {
class SourceReader {
std::istream* ifs;
FileDescr* fdescr;
SrcLocation loc;
bool eof;
std::string cur_line;
@ -106,7 +119,7 @@ class SourceReader {
const char *start, *cur, *end;
public:
SourceReader(std::istream* _is, const FileDescr* _fdescr);
SourceReader(std::istream* _is, FileDescr* _fdescr);
bool load_line();
bool is_eof() const {
return eof;

View File

@ -52,43 +52,56 @@
// elected-for elections-begin-before elections-end-before stakes-frozen
{ 4 0 reverse <b { swap 32 u, } 4 times b> 15 config! } : config.election_params!
dictnew 0 2constant validator-dict
{ @' validator-dict } : validator-dict@
{ validator-dict@ nip } : validator#
variable validator-dict
dictnew 0 validator-dict 2!
{ validator-dict @ second } : validator#
// val-pubkey weight --
{ dup 0<= abort"validator weight must be non-negative"
dup 64 ufits not abort"validator weight must fit into 64 bits"
over Blen 32 <> abort"validator public key must be 32 bytes long"
<b x{538e81278a} s, rot B, swap 64 u, b> <s
validator-dict@ dup 1+ 3 -roll swap
validator-dict 2@ dup 1+ 3 -roll swap
16 udict!+ 0= abort"cannot add validator"
swap 2 'nop does : validator-dict
swap validator-dict 2!
} : add-validator
// since-ut until-ut main-val-cnt-or-0 --
{ ?dup 0= { validator# } if
validator# 0= abort"no initial validators defined"
rot <b x{11} s, swap 32 u, rot 32 u, validator# 16 u, swap 16 u,
validator-dict@ drop <s s, b>
validator-dict @ first <s s, b>
34 config!
} : config.validators!
dictnew constant workchain-dict
variable workchain-dict
// root-hash file-hash enable-utime actual-min-split min-split max-split workchain-id --
{ <b x{a6} s, 5 roll 32 u, 4 roll 8 u, 3 roll 8 u, rot 8 u, x{e000} s,
3 roll 256 u, rot 256 u, 0 32 u, x{1} s, -1 32 i, 0 64 u, b>
dup isWorkchainDescr? not abort"invalid WorkchainDescr created"
<s swap @' workchain-dict 32 idict!+ 0= abort"cannot add workchain"
=: workchain-dict
<s swap workchain-dict @ 32 idict!+ 0= abort"cannot add workchain"
workchain-dict !
} : add-std-workchain
// --
{ @' workchain-dict dict>s s>c 12 config! } : config.workchains!
{ workchain-dict @ dict>s s>c 12 config! } : config.workchains!
dictnew constant special-dict
variable special-dict
// special-smc-addr --
{ x{} swap @' special-dict 256 udict! not abort"cannot add a new special smart contract"
=: special-dict
{ x{} swap special-dict @ 256 udict! not abort"cannot add a new special smart contract"
special-dict !
} : make_special
{ @' special-dict dict>s s>c 31 config! } : config.special!
{ special-dict @ dict>s s>c 31 config! } : config.special!
// ( l -- D ) Converts a list of parameter indices into a dictionary
{ dictnew { swap uncons -rot <b swap rot 32 b>idict! not abort"cannot add parameter index" over null?
} until nip
} : param-list-to-dict
{ param-list-to-dict 9 config! } : config.mandatory_params!
{ param-list-to-dict 10 config! } : config.critical_params!
// min_tot_rounds max_tot_rounds min_wins max_losses min_store_sec max_store_sec bit_price cell_price --
{ 8 untuple 8 0 reverse <b x{36} s, { swap 8 u, } 4 times { swap 32 u, } 4 times b> } : cfg-prop-setup
// normal-prop-params critical-prop-params --
{ swap cfg-prop-setup swap cfg-prop-setup <b x{91} s, rot ref, swap ref, b> } : make-proposals-setup
{ make-proposals-setup 11 config! } : config.param_proposals_setup!
// bit-pps cell-pps mc-bit-pps mc-cell-pps --
{ <b x{cc} s, 0 32 u, 4 roll 64 u, 3 roll 64 u, rot 64 u, swap 64 u,

View File

@ -1 +1 @@
with_tvm_code("config", "te6ccgECHQEAA5oAART/APSkE/S88sgLAQIBIAIDAgFIBAUCAvEYGQICxQYHABGgmS/aiaGuFj8CAc0ICQAGqoJbAgEgCgsCASATFAIBSAwNAgEgDg8A6wB0NMD+kAwIPpEAaQDcbATsSPHALGSXwPgAtMf0z8ighBOVlNUuo4+bBLU0XH4MyBukjB/lNDXC//iA3AEup0yIfAE+CNSILwCvLAC3gKdgCRY8AGCEO52T0vwBuAxghDudk9v8AfgECRfBCDAAAGDHrCx8qWAAJTtRNDUUDOAIPQVyMwBzxbJ7VSACASAQEQIBIBISADM0NMHAcAS8onTH9Mf0w/TDzAgwgDyib7yiYAArHCAGMjLBVAFzxYUy27LH8s/yQH7AIAAJIBA8AWACAUgVFgHh8CuNhNkfyAqYNBg/oHN9DPkeuF/6mDQYP6BzfQkHlVcUwagnoCaZ/p/8wYNqoKgzggCfEojF7KmLaZOADvKalACHoHN9CYya+ENvBAEGR8EeeAoDHACHohgdAQU4GBVQAJXk0ttgkBQYP6LZgA8C0KQXAFscfgz0NcL//gjghBOQ29kcIIAxP/IyxAUy/+DHfoCE8tqEssfyz8BzxbJcPsAgAKcIYIQQ2ZQIbqcMdMf1NFAE4Ag9BUB4CGCEE5Db2S6jhMx1CH7BO1DAtDtHu1TAfEGgvIA4CGCEFBiSyG6lWwh0//R4CGCEE5D7wW6kzHwCOAw8mCAAJAPI9AASyz/L/wHPFgKDB/RDbQChDDtRNDUgCCAJFMx9GogbpFbjjMg0CDXScInjibTB9cLH/gjuwHAErCOFYAiWFFE9G5UUyH0bjCAJEAT9FowAZFb4pJfA+LiAcjMAc8Wye1UgAccgwjXGCDTH9Mf0x/4IxK58mPtRNDU0x/T//QE0VFSuvKhJYIQVm90ZaF+sIrhBvkBVBB2+RDyovgABaRUdQQlA8jMEssfy//0AMntVPgPEDVEVfAJQwMDyMwSyx/L//QAye1UgGgLWA9MPIds8AdMHgCCzErDAU/Kp0x8BghCOgSeKuvKp0//TPzAK+QFAu/kQ8qL4AAKkVHMEKAPIzBLLH8v/9ADJ7VT4D4Ai+DP5ABBXEDQQI0iQ8A9Uc0IkA8jMEssfy//0AMntVCBukl8FiuIbHABOgCL4MyBuk1ttcODQ0wcBwBLyqIBg1yHTP8gBzxbJEoAQ9A5voTABAC7THxA0ECTwCUMDA8jMEssfy//0AMntVA==");
with_tvm_code("config", "te6ccgECJAEABcUAART/APSkE/S88sgLAQIBIAIDAgFIBAUCAvEeHwICxQYHABGgmS/aiaGuFj8CAcsICQAGqoJbAgEgCgsB46KCuNhNkfyAqYNBg/oHN9DPkeuF/6mDQYP6BzfQkHlVcUwagnoCaZ/p/8wYNqoKgzggCfEojF7KmLaZOADvKalACHoHN9CYya+ENvBAEGR8EeeAoDHACHohgdAQU4GBVQAJXk0ttgkBQYP6LZgA8C0KQB0CASAMDQIBZhscAgFIDg8CAVgZGgL3AHQ0wP6QCH6RAGkBHGwFLEkxwCxkl8F4APTH9M/IoIQTlZTVLqORDI0NAPU0XH4MyBukjB/lNDXC//iAnADup0xIPAG+CNSILwCvLAB3gGfgCQB8AGCEO52T0uAQPAH4DCCEO52T2+AQPAH4DAzIIIQblZQUrrjAmxBIIBARACU7UTQ1FAzgCD0FcjMAc8Wye1UgATwwUCPbPIBAIaMiwv+cW3T7AoIQ7lZQUoMGkTLi8AcSABLAAAGDHrCx8qUC9gHTH9TSADAiqx2V+CMToQLeIds8IML/jhci+DMgbpIwcJL5AOIhvZcwghcdm5yq3o4VefgzUjCAIPQMb6ExlzCCFzKvkZTe4iHXZYMHvpcwghc9npuq3iDB/5JsYeAjkTKOFHr4MxOAIPQMb6Exl4IXPI2WrDLe4iHB/xMUAC7Q0gcBwPPyrNIf9ATSAAGS0/+SfwHi0QTskxVfBeAxIds8byg0NDVSgLmYXwmCFzqHj5fgUHO2CAODCflBMoMJoBeoBqYCEqgVoFMBqPgjE6DtRNDU0x/T//QE0Sj5AFMBgwf0Dm+h4wIwNlGmoYMduZhfCoIXD56G3ODbPDBzqdQApHBtA/kAEFcQSxpDMBUWIxcAZoAL+DPQ0wcBgQCRuvKsAZLUMd7XTNDTBwHANvKs0wfTB9MH0wfTH9Mf0x/TH1VwbwgB0QHUODk5Bds8Uk29mF8Pghc8jZar4FNYvphfD4IXPpONu+BShqGDDaAZqFHdoYMduZhfDYIXD56G3OAQVkAUUHcDgM7IygcWyx8UzBLKAPQAyj/L/1AEzxZARYMH9EMTA8jMEssfy//0AMntVBgAWoDOyMoHFssfFMwSygD0AMo/y/8XywcUyw9AFoMH9EMSA8jMEssfy//0AMntVAAk0gcBwM7yrNMf1NIA9ATSP9P/ADM0NMHAcAS8onTH9Mf0w/TDzAgwgDyib7yiYAArHCAGMjLBVAFzxYUy27LH8s/yQH7AIABbHH4M9DXC//4I4IQTkNvZHCCAMT/yMsQFMv/gx36AhPLahLLH8s/Ac8WyXD7AIACnCGCEENmUCG6nDHSH9TRQBOAIPQVAeAhghBOQ29kuo4TMdQh+wTtQwLQ7R7tUwHxBoLyAOAhghBQYkshupVsIdP/0eAhghBOQ+8FupMx8ArgMPJggACQDyPQAEss/y/8BzxYCgwf0Q20AoQw7UTQ1IAggCRTMfRqIG6RW44zINAg10nCJ44m0wfXCx/4I7sBwBKwjhWAIlhRRPRuVFMh9G4wgCRAE/RaMAGRW+KSXwPi4gHIzAHPFsntVIAHVIMI1xgg0x/TH9Mf+CMSufJjINdkwkDyZ+1E0NTTH9P/9ATRUVK68qElghBWb3RloX6w4wMG+QFUEHb5EPKi+AAFpFR1BCUDyMwSyx/L//QAye1U+A8QNURV8AtDAwPIzBLLH8v/9ADJ7VSAgAuQD0w8h2zwB0weAILMSsMBT8qnTHwGCEI6BJ4q68qnT/9M/MAr5AUC7+RDyovgAAqRUcwQoA8jMEssfy//0AMntVPgPIoMJ+UNfA4Ai+DP5ABBXEDQQI0iQ8BVUc0IkA8jMEssfy//0AMntVCBukl8F4w4hIgEi2zwyyFjPFskSgBD0Dm+hMAEjAC7THxA0ECTwC0MDA8jMEssfy//0AMntVAAmgCL4MyDQ0wcBwBLyqIBg1yHTPw==");

Some files were not shown because too many files have changed in this diff Show More