Update tonlib

This commit is contained in:
Ali 2020-03-02 02:52:41 +04:00
parent e813ff8be6
commit 1ad432fd9c
284 changed files with 31520 additions and 7794 deletions

View File

@ -38,8 +38,12 @@
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(PRODUCT_BUNDLE_SHORT_VERSION)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${BUILD_NUMBER}</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key>

View File

@ -1,61 +0,0 @@
{
"additionalFilePaths" : [
"Wallet/BUILD"
],
"buildTargets" : [
"//Wallet:Lib",
"//Wallet:Main",
"//Wallet:Wallet",
],
"optionSet" : {
"BazelBuildOptionsDebug" : {
"p" : "$(inherited) --features=swift.use_global_module_cache --features=swift.swift.no_generated_header --spawn_strategy=standalone --strategy=SwiftCompile=standalone --define=wallet_bundle_id=org.ton.TonWallet-iOS"
},
"BazelBuildOptionsRelease" : {
"p" : "$(inherited)"
},
"BazelBuildStartupOptionsDebug" : {
"p" : "$(inherited)"
},
"BazelBuildStartupOptionsRelease" : {
"p" : "$(inherited)"
},
"BuildActionPostActionScript" : {
"p" : "$(inherited)"
},
"BuildActionPreActionScript" : {
"p" : "$(inherited)"
},
"CommandlineArguments" : {
"p" : "$(inherited)"
},
"EnvironmentVariables" : {
"p" : "$(inherited)"
},
"LaunchActionPostActionScript" : {
"p" : "$(inherited)"
},
"LaunchActionPreActionScript" : {
"p" : "$(inherited)"
},
"ProjectGenerationBazelStartupOptions" : {
"p" : "$(inherited)"
},
"ProjectPrioritizesSwift" : {
"p" : "YES"
},
"TestActionPostActionScript" : {
"p" : "$(inherited)"
},
"TestActionPreActionScript" : {
"p" : "$(inherited)"
}
},
"projectName" : "Wallet",
"sourceFilters" : [
"Wallet",
"Wallet/Sources",
"Wallet/SupportFiles",
"submodules/...",
]
}

View File

@ -1,10 +0,0 @@
{
"optionSet" : {
"BazelPath" : {
"p" : "/usr/local/bin/bazel"
},
"WorkspaceRootPath" : {
"p" : "/Users/peter/build/telegram-temp/telegram-ios"
}
}
}

View File

@ -1,14 +0,0 @@
{
"configDefaults" : {
"optionSet" : {
"ProjectPrioritizesSwift" : {
"p" : "YES"
}
}
},
"packages" : [
"Wallet"
],
"projectName" : "Wallet",
"workspaceRoot" : "../.."
}

View File

@ -39,15 +39,43 @@ NS_ASSUME_NONNULL_BEGIN
@end
@protocol TONTransactionMessageContents <NSObject>
@end
@interface TONTransactionMessageContentsRawData : NSObject <TONTransactionMessageContents>
@property (nonatomic, strong, readonly) NSData * _Nonnull data;
- (instancetype)initWithData:(NSData * _Nonnull)data;
@end
@interface TONTransactionMessageContentsPlainText : NSObject <TONTransactionMessageContents>
@property (nonatomic, strong, readonly) NSString * _Nonnull text;
- (instancetype)initWithText:(NSString * _Nonnull)text;
@end
@interface TONTransactionMessageContentsEncryptedText : NSObject <TONTransactionMessageContents>
@property (nonatomic, strong, readonly) NSData * _Nonnull data;
- (instancetype)initWithData:(NSData * _Nonnull)data;
@end
@interface TONTransactionMessage : NSObject
@property (nonatomic, readonly) int64_t value;
@property (nonatomic, strong, readonly) NSString * _Nonnull source;
@property (nonatomic, strong, readonly) NSString * _Nonnull destination;
@property (nonatomic, strong, readonly) NSString * _Nonnull textMessage;
@property (nonatomic, strong, readonly) id<TONTransactionMessageContents> _Nonnull contents;
@property (nonatomic, strong, readonly) NSData * _Nonnull bodyHash;
- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination textMessage:(NSString * _Nonnull)textMessage bodyHash:(NSData * _Nonnull)bodyHash;
- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination contents:(id<TONTransactionMessageContents> _Nonnull)contents bodyHash:(NSData * _Nonnull)bodyHash;
@end
@ -87,10 +115,10 @@ NS_ASSUME_NONNULL_BEGIN
@interface TONSendGramsQueryFees : NSObject
@property (nonatomic, strong, readonly) TONFees *sourceFees;
@property (nonatomic, strong, readonly) TONFees *destinationFees;
@property (nonatomic, strong, readonly) TONFees * _Nonnull sourceFees;
@property (nonatomic, strong, readonly) NSArray<TONFees *> * _Nonnull destinationFees;
- (instancetype)initWithSourceFees:(TONFees *)sourceFees destinationFees:(TONFees *)destinationFees;
- (instancetype)initWithSourceFees:(TONFees * _Nonnull)sourceFees destinationFees:(NSArray<TONFees *> * _Nonnull)destinationFees;
@end

View File

@ -48,14 +48,38 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
}
NSString *source = readString(message->source_);
NSString *destination = readString(message->destination_);
NSString *textMessage = readString(message->message_);
id<TONTransactionMessageContents> contents = nil;
if (message->msg_data_->get_id() == tonlib_api::msg_dataRaw::ID) {
auto msgData = tonlib_api::move_object_as<tonlib_api::msg_dataRaw>(message->msg_data_);
contents = [[TONTransactionMessageContentsRawData alloc] initWithData:makeData(msgData->body_)];
} else if (message->msg_data_->get_id() == tonlib_api::msg_dataText::ID) {
auto msgData = tonlib_api::move_object_as<tonlib_api::msg_dataText>(message->msg_data_);
NSString *text = readString(msgData->text_);
if (text == nil) {
contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:@""];
} else {
contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:text];
}
} else if (message->msg_data_->get_id() == tonlib_api::msg_dataDecryptedText::ID) {
auto msgData = tonlib_api::move_object_as<tonlib_api::msg_dataDecryptedText>(message->msg_data_);
NSString *text = readString(msgData->text_);
if (text == nil) {
contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:@""];
} else {
contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:text];
}
} 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_)];
} else {
contents = [[TONTransactionMessageContentsRawData alloc] initWithData:[NSData data]];
}
if (source == nil || destination == nil) {
return nil;
}
if (textMessage == nil) {
textMessage = @"";
}
return [[TONTransactionMessage alloc] initWithValue:message->value_ source:source destination:destination textMessage:textMessage bodyHash:makeData(message->body_hash_)];
return [[TONTransactionMessage alloc] initWithValue:message->value_ source:source destination:destination contents:contents bodyHash:makeData(message->body_hash_)];
}
@implementation TONKey
@ -100,15 +124,51 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
@end
@implementation TONTransactionMessageContentsRawData
- (instancetype)initWithData:(NSData * _Nonnull)data {
self = [super init];
if (self != nil) {
_data = data;
}
return self;
}
@end
@implementation TONTransactionMessageContentsPlainText
- (instancetype)initWithText:(NSString * _Nonnull)text {
self = [super init];
if (self != nil) {
_text = text;
}
return self;
}
@end
@implementation TONTransactionMessageContentsEncryptedText
- (instancetype)initWithData:(NSData * _Nonnull)data {
self = [super init];
if (self != nil) {
_data = data;
}
return self;
}
@end
@implementation TONTransactionMessage
- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination textMessage:(NSString * _Nonnull)textMessage bodyHash:(NSData * _Nonnull)bodyHash {
- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination contents:(id<TONTransactionMessageContents> _Nonnull)contents bodyHash:(NSData * _Nonnull)bodyHash {
self = [super init];
if (self != nil) {
_value = value;
_source = source;
_destination = destination;
_textMessage = textMessage;
_contents = contents;
_bodyHash = bodyHash;
}
return self;
@ -164,7 +224,7 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
@implementation TONSendGramsQueryFees
- (instancetype)initWithSourceFees:(TONFees *)sourceFees destinationFees:(TONFees *)destinationFees {
- (instancetype)initWithSourceFees:(TONFees * _Nonnull)sourceFees destinationFees:(NSArray<TONFees *> * _Nonnull)destinationFees {
self = [super init];
if (self != nil) {
_sourceFees = sourceFees;
@ -582,11 +642,14 @@ typedef enum {
}
}];
auto query = make_object<tonlib_api::wallet_v3_getAccountAddress>(
make_object<tonlib_api::wallet_v3_initialAccountState>(
makeString(publicKeyData),
initialWalletId
)
auto initialAccountState = make_object<tonlib_api::wallet_v3_initialAccountState>(
makeString(publicKeyData),
initialWalletId
);
auto query = make_object<tonlib_api::getAccountAddress>(
tonlib_api::move_object_as<tonlib_api::InitialAccountState>(initialAccountState),
1
);
_client->send({ requestId, std::move(query) });
@ -604,36 +667,31 @@ 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::generic_accountStateUninited::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateUninited>(object);
TONTransactionId *lastTransactionId = nil;
if (result->account_state_->last_transaction_id_ != nullptr) {
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
} else if (object->get_id() == tonlib_api::fullAccountState::ID) {
auto fullAccountState = tonlib_api::move_object_as<tonlib_api::fullAccountState>(object);
int32_t seqNo = -1;
if (fullAccountState->account_state_->get_id() == tonlib_api::uninited_accountState::ID) {
seqNo = -1;
} else if (fullAccountState->account_state_->get_id() == tonlib_api::wallet_v3_accountState::ID) {
auto v3AccountState = tonlib_api::move_object_as<tonlib_api::wallet_v3_accountState>(fullAccountState->account_state_);
seqNo = v3AccountState->seqno_;
} else {
[subscriber putError:[[TONError alloc] initWithText:@"Unknown type"]];
return;
}
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:false balance:result->account_state_->balance_ seqno:-1 lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
[subscriber putCompletion];
} else if (object->get_id() == tonlib_api::generic_accountStateWallet::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateWallet>(object);
TONTransactionId *lastTransactionId = nil;
if (result->account_state_->last_transaction_id_ != nullptr) {
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
if (fullAccountState->last_transaction_id_ != nullptr) {
lastTransactionId = [[TONTransactionId alloc] initWithLt:fullAccountState->last_transaction_id_->lt_ transactionHash:makeData(fullAccountState->last_transaction_id_->hash_)];
}
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:false balance:fullAccountState->balance_ seqno:-1 lastTransactionId:lastTransactionId syncUtime:fullAccountState->sync_utime_]];
[subscriber putCompletion];
} else if (object->get_id() == tonlib_api::generic_accountStateWalletV3::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateWalletV3>(object);
TONTransactionId *lastTransactionId = nil;
if (result->account_state_->last_transaction_id_ != nullptr) {
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
}
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
[subscriber putCompletion];
}else {
} else {
assert(false);
}
}];
auto query = make_object<tonlib_api::generic_getAccountState>(make_object<tonlib_api::accountAddress>(accountAddress.UTF8String));
auto query = make_object<tonlib_api::getAccountState>(make_object<tonlib_api::accountAddress>(accountAddress.UTF8String));
_client->send({ requestId, std::move(query) });
return [[SBlockDisposable alloc] initWithBlock:^{
@ -681,7 +739,21 @@ typedef enum {
}
}];
auto query = make_object<tonlib_api::generic_createSendGramsQuery>(
auto inputMessageData = make_object<tonlib_api::msg_dataEncryptedText>(
makeString(textMessage)
);
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),
amount,
tonlib_api::move_object_as<tonlib_api::msg_Data>(inputMessageData)
));
auto inputAction = make_object<tonlib_api::actionMsg>(
std::move(inputMessages),
forceIfDestinationNotInitialized
);
auto query = make_object<tonlib_api::createQuery>(
make_object<tonlib_api::inputKeyRegular>(
make_object<tonlib_api::key>(
makeString(publicKeyData),
@ -690,11 +762,8 @@ typedef enum {
makeSecureString(localPassword)
),
make_object<tonlib_api::accountAddress>(fromAddress.UTF8String),
make_object<tonlib_api::accountAddress>(address.UTF8String),
amount,
timeout,
forceIfDestinationNotInitialized,
makeString(textMessage)
tonlib_api::move_object_as<tonlib_api::Action>(inputAction)
);
_client->send({ requestId, std::move(query) });
@ -723,14 +792,25 @@ typedef enum {
}
}];
auto query = make_object<tonlib_api::generic_createSendGramsQuery>(
make_object<tonlib_api::inputKeyFake>(),
make_object<tonlib_api::accountAddress>(fromAddress.UTF8String),
auto inputMessageData = make_object<tonlib_api::msg_dataEncryptedText>(
makeString(textMessage)
);
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),
amount,
tonlib_api::move_object_as<tonlib_api::msg_Data>(inputMessageData)
));
auto inputAction = make_object<tonlib_api::actionMsg>(
std::move(inputMessages),
forceIfDestinationNotInitialized
);
auto query = make_object<tonlib_api::createQuery>(
make_object<tonlib_api::inputKeyFake>(),
make_object<tonlib_api::accountAddress>(fromAddress.UTF8String),
timeout,
forceIfDestinationNotInitialized,
makeString(textMessage)
tonlib_api::move_object_as<tonlib_api::Action>(inputAction)
);
_client->send({ requestId, std::move(query) });
@ -751,7 +831,12 @@ typedef enum {
} else if (object->get_id() == tonlib_api::query_fees::ID) {
auto result = tonlib_api::move_object_as<tonlib_api::query_fees>(object);
TONFees *sourceFees = [[TONFees alloc] initWithInFwdFee:result->source_fees_->in_fwd_fee_ storageFee:result->source_fees_->storage_fee_ gasFee:result->source_fees_->gas_fee_ fwdFee:result->source_fees_->fwd_fee_];
TONFees *destinationFees = [[TONFees alloc] initWithInFwdFee:result->destination_fees_->in_fwd_fee_ storageFee:result->destination_fees_->storage_fee_ gasFee:result->destination_fees_->gas_fee_ fwdFee:result->destination_fees_->fwd_fee_];
NSMutableArray<TONFees *> *destinationFees = [[NSMutableArray alloc] init];
for (auto &fee : result->destination_fees_) {
TONFees *destinationFee = [[TONFees alloc] initWithInFwdFee:fee->in_fwd_fee_ storageFee:fee->storage_fee_ gasFee:fee->gas_fee_ fwdFee:fee->fwd_fee_];
[destinationFees addObject:destinationFee];
}
[subscriber putNext:[[TONSendGramsQueryFees alloc] initWithSourceFees:sourceFees destinationFees:destinationFees]];
[subscriber putCompletion];
} else {
@ -978,6 +1063,7 @@ typedef enum {
}];
auto query = make_object<tonlib_api::raw_getTransactions>(
make_object<tonlib_api::inputKeyFake>(),
make_object<tonlib_api::accountAddress>(
makeString(addressData)
),

View File

@ -1060,18 +1060,73 @@ private extension WalletTransactionId {
}
}
public enum WalletTransactionMessageContentsDecodingError: Error {
case generic
}
public enum WalletTransactionMessageContents: Codable, Equatable {
enum Key: CodingKey {
case raw
case plainText
case encryptedText
}
case raw(Data)
case plainText(String)
case encryptedText(Data)
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: Key.self)
if let data = try? container.decode(Data.self, forKey: .raw) {
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 {
throw WalletTransactionMessageContentsDecodingError.generic
}
}
public func encode(to encoder: Encoder) throws {
var container = try 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)
}
}
}
private extension WalletTransactionMessageContents {
init(tonTransactionMessageContents: TONTransactionMessageContents) {
if let raw = tonTransactionMessageContents as? TONTransactionMessageContentsRawData {
self = .raw(raw.data)
} else if let plainText = tonTransactionMessageContents as? TONTransactionMessageContentsPlainText {
self = .plainText(plainText.text)
} else if let encryptedText = tonTransactionMessageContents as? TONTransactionMessageContentsEncryptedText {
self = .encryptedText(encryptedText.data)
} else {
self = .raw(Data())
}
}
}
public final class WalletTransactionMessage: Codable, Equatable {
public let value: Int64
public let source: String
public let destination: String
public let textMessage: String
public let contents: WalletTransactionMessageContents
public let bodyHash: Data
init(value: Int64, source: String, destination: String, textMessage: String, bodyHash: Data) {
init(value: Int64, source: String, destination: String, contents: WalletTransactionMessageContents, bodyHash: Data) {
self.value = value
self.source = source
self.destination = destination
self.textMessage = textMessage
self.contents = contents
self.bodyHash = bodyHash
}
@ -1085,7 +1140,7 @@ public final class WalletTransactionMessage: Codable, Equatable {
if lhs.destination != rhs.destination {
return false
}
if lhs.textMessage != rhs.textMessage {
if lhs.contents != rhs.contents {
return false
}
if lhs.bodyHash != rhs.bodyHash {
@ -1097,7 +1152,7 @@ public final class WalletTransactionMessage: Codable, Equatable {
private extension WalletTransactionMessage {
convenience init(tonTransactionMessage: TONTransactionMessage) {
self.init(value: tonTransactionMessage.value, source: tonTransactionMessage.source, destination: tonTransactionMessage.destination, textMessage: tonTransactionMessage.textMessage, bodyHash: tonTransactionMessage.bodyHash)
self.init(value: tonTransactionMessage.value, source: tonTransactionMessage.source, destination: tonTransactionMessage.destination, contents: WalletTransactionMessageContents(tonTransactionMessageContents: tonTransactionMessage.contents), bodyHash: tonTransactionMessage.bodyHash)
}
}

View File

@ -242,7 +242,14 @@ class WalletInfoTransactionItemNode: ListViewItemNode {
if !description.isEmpty {
description.append("\n")
}
description.append(message.textMessage)
switch message.contents {
case .raw:
break
case .encryptedText:
description.append("<encrypted>")
case let .plainText(text):
description.append(text)
}
}
}
case let .pending(transaction):
@ -268,7 +275,14 @@ class WalletInfoTransactionItemNode: ListViewItemNode {
case let .completed(transaction):
if let inMessage = transaction.inMessage {
text = formatAddress(inMessage.source)
description = inMessage.textMessage
switch inMessage.contents {
case .raw:
description = ""
case .encryptedText:
description = "<encrypted>"
case let .plainText(text):
description = text
}
} else {
text = "<unknown>"
}

View File

@ -106,11 +106,25 @@ private func extractDescription(_ walletTransaction: WalletInfoTransaction) -> S
if !text.isEmpty {
text.append("\n\n")
}
text.append(message.textMessage)
switch message.contents {
case .raw:
break
case .encryptedText:
text.append("<encrypted>")
case let .plainText(plainText):
text.append(plainText)
}
}
} else {
if let inMessage = walletTransaction.inMessage {
text = inMessage.textMessage
switch inMessage.contents {
case .raw:
text = ""
case .encryptedText:
text = "<encrypted>"
case let .plainText(plainText):
text = plainText
}
}
}
return text

View File

@ -35,12 +35,19 @@ ton_lib_names = [
"tonlib",
]
filegroup(
name = "TonSources",
srcs = glob([
"tonlib-src/**/*"
]),
)
genrule(
name = "ton_build",
srcs = [
"build-ton-bazel.sh",
"iOS-bazel.cmake",
"tonlib-src.tar.gz",
":TonSources",
"//submodules/openssl:openssl_include",
"//submodules/openssl:libcrypto.a",
],
@ -70,7 +77,10 @@ genrule(
cp $(location :build-ton-bazel.sh) "$$BUILD_DIR/"
cp $(location :iOS-bazel.cmake) "$$BUILD_DIR/"
tar -xzf $(location tonlib-src.tar.gz) -C "$$BUILD_DIR/"
SOURCE_PATH="submodules/tonlib/tonlib-src"
cp -R "$$SOURCE_PATH" "$$BUILD_DIR/"
mkdir -p "$$BUILD_DIR/openssl_headers/include/openssl"
mkdir -p "$$BUILD_DIR/openssl_headers/lib"

Binary file not shown.

View File

@ -14,5 +14,5 @@
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
*/

View File

@ -8,18 +8,19 @@ The software is likely to compile and work properly on most Linux systems. It sh
BASIC COMPILATION AND INSTALLATION INSTRUCTIONS
1) Download and unpack the newest version of this archive, available at
1) Download the newest version of the TON blockchain sources, available at GitHub repository https://github.com/ton-blockchain/ton/ :
https://test.ton.org/download
git clone https://github.com/ton-blockchain/ton.git
git submodule update
The TON Blockchain Test Network is updated quite often, so we cannot guarantee that older versions of the Lite Client will always work. Backward compatibility is not enforced at this development stage.
2) Install the newest versions of make, cmake (version 3.0.2 or later), OpenSSL (including C header files), and g++ or clang (or another C++14-compatible compiler as appropriate for your operating system). We strongly recommend installing OpenSSL version 1.1.1 or later for better performance, especially if you intend to run a Full Node or a Validator as well.
3) Suppose that you have unpacked this archive to directory ~/lite-client, where ~ is your home directory, and that you have created an empty directory ~/liteclient-build. Then run the following in a terminal on a Linux system:
3) Suppose that you have fetched the source tree to directory ~/ton, where ~ is your home directory, and that you have created an empty directory ~/liteclient-build. Then run the following in a terminal on a Linux system:
cd ~/liteclient-build
cmake ~/lite-client
cmake ~/ton
cmake --build . --target lite-client
You might also build some extra utilities useful for smart-contract development:

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
@ -75,6 +75,10 @@ class AdnlNodeIdShort {
return hash_.is_zero();
}
static td::Result<AdnlNodeIdShort> parse(td::Slice key);
std::string serialize();
private:
PublicKeyHash hash_;
};

View File

@ -1,3 +1,21 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "td/utils/int_types.h"

View File

@ -23,6 +23,7 @@ set(TON_CRYPTO_SOURCE
vm/atom.cpp
vm/continuation.cpp
vm/dict.cpp
vm/memo.cpp
vm/dispatch.cpp
vm/opctable.cpp
vm/cp0.cpp
@ -35,6 +36,8 @@ set(TON_CRYPTO_SOURCE
vm/debugops.cpp
vm/tonops.cpp
vm/boc.cpp
vm/utils.cpp
vm/vm.cpp
tl/tlblib.cpp
Ed25519.h
@ -74,12 +77,15 @@ set(TON_CRYPTO_SOURCE
vm/excno.hpp
vm/fmt.hpp
vm/log.h
vm/memo.h
vm/opctable.h
vm/stack.hpp
vm/stackops.h
vm/tupleops.h
vm/tonops.h
vm/vmstate.h
vm/utils.h
vm/vm.h
vm/cells.h
vm/cellslice.h
@ -201,6 +207,9 @@ set(BLOCK_SOURCE
set(SMC_ENVELOPE_SOURCE
smc-envelope/GenericAccount.cpp
smc-envelope/HighloadWallet.cpp
smc-envelope/HighloadWalletV2.cpp
smc-envelope/ManualDns.cpp
smc-envelope/MultisigWallet.cpp
smc-envelope/SmartContract.cpp
smc-envelope/SmartContractCode.cpp
@ -210,12 +219,16 @@ set(SMC_ENVELOPE_SOURCE
smc-envelope/WalletV3.cpp
smc-envelope/GenericAccount.h
smc-envelope/HighloadWallet.h
smc-envelope/HighloadWalletV2.h
smc-envelope/ManualDns.h
smc-envelope/MultisigWallet.h
smc-envelope/SmartContract.h
smc-envelope/SmartContractCode.h
smc-envelope/TestGiver.h
smc-envelope/TestWallet.h
smc-envelope/Wallet.h
smc-envelope/WalletInterface.h
smc-envelope/WalletV3.h
)
@ -343,7 +356,7 @@ if (NOT CMAKE_CROSSCOMPILING)
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND fift -Ifift/lib:smartcont -s asm-to-cpp.fif ${ARG_DEST_FIF} ${ARG_DEST_CPP} ${ARG_NAME}
MAIN_DEPENDENCY ${ARG_SOURCE}
DEPENDS fift ${ARG_DEST_FIF} smartcont/asm-to-cpp.fif
DEPENDS fift ${ARG_DEST_FIF} smartcont/asm-to-cpp.fif fift/lib/Asm.fif
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_CPP}
)
add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST_FIF} ${ARG_DEST_CPP})
@ -355,12 +368,15 @@ if (NOT CMAKE_CROSSCOMPILING)
GenFif(DEST smartcont/auto/wallet3-code SOURCE smartcont/wallet3-code.fc NAME wallet3)
GenFif(DEST smartcont/auto/simple-wallet-code SOURCE smartcont/simple-wallet-code.fc NAME simple-wallet)
GenFif(DEST smartcont/auto/highload-wallet-code SOURCE smartcont/highload-wallet-code.fc NAME highload-wallet)
GenFif(DEST smartcont/auto/highload-wallet-v2-code SOURCE smartcont/highload-wallet-v2-code.fc NAME highoad-wallet-v2)
GenFif(DEST smartcont/auto/highload-wallet-v2-code SOURCE smartcont/highload-wallet-v2-code.fc NAME highload-wallet-v2)
GenFif(DEST smartcont/auto/elector-code SOURCE smartcont/elector-code.fc NAME elector-code)
GenFif(DEST smartcont/auto/multisig-code SOURCE smartcont/multisig-code.fc NAME multisig)
GenFif(DEST smartcont/auto/restricted-wallet-code SOURCE smartcont/restricted-wallet-code.fc NAME restricted-wallet)
GenFif(DEST smartcont/auto/restricted-wallet2-code SOURCE smartcont/restricted-wallet2-code.fc NAME restricted-wallet2)
GenFif(DEST smartcont/auto/dns-manual-code SOURCE smartcont/dns-manual-code.fc NAME dns-manual)
GenFif(DEST smartcont/auto/dns-auto-code SOURCE smartcont/dns-auto-code.fc NAME dns-auto)
GenFif(DEST smartcont/auto/simple-wallet-ext-code SOURCE smartcont/simple-wallet-ext-code.fc NAME simple-wallet-ext)
endif()
@ -387,5 +403,13 @@ if (WINGETOPT_FOUND)
target_link_libraries_system(dump-block wingetopt)
endif()
add_executable(adjust-block block/adjust-block.cpp)
target_include_directories(adjust-block PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(adjust-block PUBLIC ton_crypto fift-lib ton_block)
if (WINGETOPT_FOUND)
target_link_libraries_system(dump-block wingetopt)
endif()
install(TARGETS fift func RUNTIME DESTINATION bin)
install(DIRECTORY fift/lib/ DESTINATION lib/fift)

View File

@ -0,0 +1,203 @@
/*
This file is part of TON Blockchain source code.
TON Blockchain is free software; you can redistribute it and/or
modify it under the terms of the GNU 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 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
You must obey the GNU General Public License in all respects for all
of the code used other than OpenSSL. If you modify file(s) with this
exception, you may extend this exception to your version of the file(s),
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
*/
#include "block/block.h"
#include "vm/boc.h"
#include <iostream>
#include "block-db.h"
#include "block-auto.h"
#include "block-parse.h"
#include "vm/cp0.h"
#include "td/utils/crypto.h"
#include <getopt.h>
using td::Ref;
using namespace std::literals::string_literals;
int verbosity;
struct IntError {
std::string err_msg;
IntError(std::string _msg) : err_msg(_msg) {
}
IntError(const char* _msg) : err_msg(_msg) {
}
};
int fatal(std::string str) {
std::cerr << "fatal error: " << str << std::endl;
std::exit(2);
return 2;
}
static inline void fail_unless(td::Status res) {
if (res.is_error()) {
throw IntError{res.to_string()};
}
}
td::Ref<vm::Cell> load_block(std::string filename, ton::BlockIdExt& id) {
std::cerr << "loading block from bag-of-cell file " << filename << std::endl;
auto bytes_res = block::load_binary_file(filename);
if (bytes_res.is_error()) {
throw IntError{PSTRING() << "cannot load file `" << filename << "` : " << bytes_res.move_as_error()};
}
ton::FileHash fhash;
td::sha256(bytes_res.ok(), fhash.as_slice());
vm::BagOfCells boc;
auto res = boc.deserialize(bytes_res.move_as_ok());
if (res.is_error()) {
throw IntError{PSTRING() << "cannot deserialize bag-of-cells " << res.move_as_error()};
}
if (res.move_as_ok() <= 0 || boc.get_root_cell().is_null()) {
throw IntError{"cannot deserialize bag-of-cells"};
}
auto root = boc.get_root_cell();
std::vector<ton::BlockIdExt> prev;
ton::BlockIdExt mc_blkid;
bool after_split;
fail_unless(block::unpack_block_prev_blk_try(root, id, prev, mc_blkid, after_split, &id));
id.file_hash = fhash;
std::cerr << "loaded block " << id.to_str() << std::endl;
return root;
}
bool save_block(std::string filename, Ref<vm::Cell> root, ton::BlockIdExt& id) {
std::cerr << "saving block into bag-of-cell file " << filename << std::endl;
if (root.is_null()) {
throw IntError{"new block has no root"};
}
id.root_hash = root->get_hash().bits();
auto res = vm::std_boc_serialize(std::move(root), 31);
if (res.is_error()) {
throw IntError{PSTRING() << "cannot serialize modified block as a bag-of-cells: "
<< res.move_as_error().to_string()};
}
auto data = res.move_as_ok();
td::sha256(data, id.file_hash.as_slice());
auto res1 = block::save_binary_file(filename, std::move(data));
if (res1.is_error()) {
throw IntError{PSTRING() << "cannot save file `" << filename << "` : " << res1};
}
return true;
}
Ref<vm::Cell> adjust_block(Ref<vm::Cell> root, int vseqno_incr, const ton::BlockIdExt& id) {
std::vector<ton::BlockIdExt> prev;
ton::BlockIdExt mc_blkid;
bool after_split;
fail_unless(block::unpack_block_prev_blk_try(root, id, prev, mc_blkid, after_split));
std::cerr << "unpacked header of block " << id.to_str() << std::endl;
if (!id.is_masterchain()) {
throw IntError{"can modify only masterchain blocks"};
}
block::gen::Block::Record blk;
block::gen::BlockInfo::Record info;
if (!(tlb::unpack_cell(root, blk) && tlb::unpack_cell(blk.info, info))) {
throw IntError{"cannot unpack block header"};
}
if (!info.key_block) {
throw IntError{"can modify only key blocks"};
}
info.vert_seqno_incr = true;
info.vert_seq_no += vseqno_incr;
if (!block::tlb::t_ExtBlkRef.pack_to(info.prev_vert_ref, id, info.end_lt)) {
throw IntError{"cannot pack prev_vert_ref"};
}
if (!(tlb::pack_cell(blk.info, info) && tlb::pack_cell(root, blk))) {
throw IntError{"cannot pack block header"};
}
return root;
}
void usage() {
std::cout << "usage: adjust-block [-i<vs-incr>] <in-boc-file> <out-boc-file>\n\tor adjust-block -h\n\tAdjusts block "
"loaded from <in-boc-file> by incrementing vert_seqno by <vs-incr> (1 by default)\n";
std::exit(3);
}
int main(int argc, char* const argv[]) {
int i, vseqno_incr = 1;
int new_verbosity_level = VERBOSITY_NAME(INFO);
std::string in_fname, out_fname;
while ((i = getopt(argc, argv, "hi:v:")) != -1) {
switch (i) {
case 'h':
usage();
break;
case 'i':
vseqno_incr = td::to_integer<int>(td::Slice(optarg));
CHECK(vseqno_incr > 0 && vseqno_incr < 1000);
break;
case 'v':
new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer<int>(td::Slice(optarg)));
break;
default:
usage();
break;
}
}
SET_VERBOSITY_LEVEL(new_verbosity_level);
if (argc != optind + 2) {
usage();
return 2;
}
in_fname = argv[optind];
out_fname = argv[optind + 1];
try {
ton::BlockIdExt old_id, new_id;
auto root = load_block(in_fname, old_id);
if (root.is_null()) {
return fatal("cannot load BoC from file "s + in_fname);
}
bool ok = block::gen::t_Block.validate_ref(root);
if (!ok) {
return fatal("file `"s + in_fname + " does not contain a valid block");
}
auto adjusted = adjust_block(root, vseqno_incr, old_id);
if (adjusted.is_null()) {
return fatal("cannot adjust block");
}
ok = block::gen::t_Block.validate_ref(root);
if (!ok) {
return fatal("modified block is not valid");
}
new_id = old_id;
if (!save_block(out_fname, adjusted, new_id)) {
return fatal("cannot save modified block to file `"s + out_fname + "`");
}
std::cout << "old block id: " << old_id.to_str() << std::endl;
std::cout << "new block id: " << new_id.to_str() << std::endl;
} catch (IntError& err) {
std::cerr << "internal error: " << err.err_msg << std::endl;
return 1;
} catch (vm::VmError& err) {
std::cerr << "vm error: " << err.get_msg() << std::endl;
return 1;
}
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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 "td/utils/bits.h"
#include "block/block-parse.h"
@ -80,7 +80,7 @@ bool Maybe_Anycast::skip_get_depth(vm::CellSlice& cs, int& depth) const {
const Maybe_Anycast t_Maybe_Anycast;
bool MsgAddressInt::validate_skip(vm::CellSlice& cs, bool weak) const {
bool MsgAddressInt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
if (!cs.have(3)) {
return false;
}
@ -241,16 +241,38 @@ bool MsgAddressInt::extract_std_address(vm::CellSlice& cs, ton::WorkchainId& wor
return false;
}
bool MsgAddressInt::store_std_address(vm::CellBuilder& cb, ton::WorkchainId workchain,
const ton::StdSmcAddress& addr) const {
if (workchain >= -128 && workchain < 128) {
return cb.store_long_bool(4, 3) // addr_std$10 anycast:(Maybe Anycast)
&& cb.store_long_bool(workchain, 8) // workchain_id:int8
&& cb.store_bits_bool(addr); // address:bits256 = MsgAddressInt;
} else {
return cb.store_long_bool(0xd00, 12) // addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
&& cb.store_long_bool(workchain, 32) // workchain_id:int32
&& cb.store_bits_bool(addr); // address:(bits addr_len) = MsgAddressInt;
}
}
Ref<vm::CellSlice> MsgAddressInt::pack_std_address(ton::WorkchainId workchain, const ton::StdSmcAddress& addr) const {
vm::CellBuilder cb;
if (store_std_address(cb, workchain, addr)) {
return vm::load_cell_slice_ref(cb.finalize());
} else {
return {};
}
}
const MsgAddressInt t_MsgAddressInt;
bool MsgAddress::validate_skip(vm::CellSlice& cs, bool weak) const {
bool MsgAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case addr_none:
case addr_ext:
return t_MsgAddressExt.validate_skip(cs, weak);
return t_MsgAddressExt.validate_skip(ops, cs, weak);
case addr_std:
case addr_var:
return t_MsgAddressInt.validate_skip(cs, weak);
return t_MsgAddressInt.validate_skip(ops, cs, weak);
}
return false;
}
@ -262,7 +284,7 @@ bool VarUInteger::skip(vm::CellSlice& cs) const {
return len >= 0 && len < n && cs.advance(len * 8);
}
bool VarUInteger::validate_skip(vm::CellSlice& cs, bool weak) const {
bool VarUInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len >= 0 && len < n && (!len || cs.prefetch_ulong(8)) && cs.advance(len * 8);
}
@ -303,7 +325,7 @@ bool VarUIntegerPos::skip(vm::CellSlice& cs) const {
return len > 0 && len < n && cs.advance(len * 8);
}
bool VarUIntegerPos::validate_skip(vm::CellSlice& cs, bool weak) const {
bool VarUIntegerPos::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len > 0 && len < n && cs.prefetch_ulong(8) && cs.advance(len * 8);
}
@ -338,7 +360,7 @@ bool VarInteger::skip(vm::CellSlice& cs) const {
return len >= 0 && len < n && cs.advance(len * 8);
}
bool VarInteger::validate_skip(vm::CellSlice& cs, bool weak) const {
bool VarInteger::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len >= 0 && len < n && (!len || !redundant_int(cs)) && cs.advance(len * 8);
}
@ -364,7 +386,7 @@ bool VarIntegerNz::skip(vm::CellSlice& cs) const {
return len > 0 && len < n && cs.advance(len * 8);
}
bool VarIntegerNz::validate_skip(vm::CellSlice& cs, bool weak) const {
bool VarIntegerNz::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int len = (int)cs.fetch_ulong(ln);
return len > 0 && len < n && !redundant_int(cs) && cs.advance(len * 8);
}
@ -387,8 +409,8 @@ bool VarIntegerNz::store_integer_value(vm::CellBuilder& cb, const td::BigInt256&
cb.store_int256_bool(value, (k + 7) & -8, true);
}
bool Grams::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_16.validate_skip(cs, weak);
bool Grams::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_16.validate_skip(ops, cs, weak);
}
td::RefInt256 Grams::as_integer_skip(vm::CellSlice& cs) const {
@ -442,15 +464,15 @@ bool HashmapNode::skip(vm::CellSlice& cs) const {
return n ? cs.advance_refs(2) : value_type.skip(cs);
}
bool HashmapNode::validate_skip(vm::CellSlice& cs, bool weak) const {
bool HashmapNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
assert(n >= 0);
if (!n) {
// hmn_leaf
return value_type.validate_skip(cs, weak);
return value_type.validate_skip(ops, cs, weak);
} else {
// hmn_fork
Hashmap branch_type{n - 1, value_type};
return branch_type.validate_ref(cs.fetch_ref(), weak) && branch_type.validate_ref(cs.fetch_ref(), weak);
return branch_type.validate_ref(ops, cs.fetch_ref(), weak) && branch_type.validate_ref(ops, cs.fetch_ref(), weak);
}
}
@ -459,9 +481,9 @@ bool Hashmap::skip(vm::CellSlice& cs) const {
return HmLabel{n}.skip(cs, l) && HashmapNode{n - l, value_type}.skip(cs);
}
bool Hashmap::validate_skip(vm::CellSlice& cs, bool weak) const {
bool Hashmap::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int l;
return HmLabel{n}.validate_skip(cs, weak, l) && HashmapNode{n - l, value_type}.validate_skip(cs, weak);
return HmLabel{n}.validate_skip(cs, weak, l) && HashmapNode{n - l, value_type}.validate_skip(ops, cs, weak);
}
int HashmapE::get_size(const vm::CellSlice& cs) const {
@ -469,9 +491,9 @@ int HashmapE::get_size(const vm::CellSlice& cs) const {
return (tag >= 0 ? (tag > 0 ? 0x10001 : 1) : -1);
}
bool HashmapE::validate(const vm::CellSlice& cs, bool weak) const {
bool HashmapE::validate(int* ops, const vm::CellSlice& cs, bool weak) const {
int tag = get_tag(cs);
return tag <= 0 ? !tag : root_type.validate_ref(cs.prefetch_ref(), weak);
return tag <= 0 ? !tag : root_type.validate_ref(ops, cs.prefetch_ref(), weak);
}
bool HashmapE::add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const {
@ -561,8 +583,8 @@ bool HashmapE::store_ref(vm::CellBuilder& cb, Ref<vm::Cell> arg) const {
const ExtraCurrencyCollection t_ExtraCurrencyCollection;
bool CurrencyCollection::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_Grams.validate_skip(cs, weak) && t_ExtraCurrencyCollection.validate_skip(cs, weak);
bool CurrencyCollection::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_Grams.validate_skip(ops, cs, weak) && t_ExtraCurrencyCollection.validate_skip(ops, cs, weak);
}
bool CurrencyCollection::skip(vm::CellSlice& cs) const {
@ -619,25 +641,25 @@ bool CurrencyCollection::pack(vm::CellBuilder& cb, const block::CurrencyCollecti
const CurrencyCollection t_CurrencyCollection;
bool CommonMsgInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
bool CommonMsgInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int tag = get_tag(cs);
switch (tag) {
case int_msg_info:
return cs.advance(4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
&& t_MsgAddressInt.validate_skip(cs, weak) // src
&& t_MsgAddressInt.validate_skip(cs, weak) // dest
&& t_CurrencyCollection.validate_skip(cs, weak) // value
&& t_Grams.validate_skip(cs, weak) // ihr_fee
&& t_Grams.validate_skip(cs, weak) // fwd_fee
&& cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
return cs.advance(4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
&& t_MsgAddressInt.validate_skip(ops, cs, weak) // src
&& t_MsgAddressInt.validate_skip(ops, cs, weak) // dest
&& t_CurrencyCollection.validate_skip(ops, cs, weak) // value
&& t_Grams.validate_skip(ops, cs, weak) // ihr_fee
&& t_Grams.validate_skip(ops, cs, weak) // fwd_fee
&& cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
case ext_in_msg_info:
return cs.advance(2) && t_MsgAddressExt.validate_skip(cs, weak) // src
&& t_MsgAddressInt.validate_skip(cs, weak) // dest
&& t_Grams.validate_skip(cs, weak); // import_fee
return cs.advance(2) && t_MsgAddressExt.validate_skip(ops, cs, weak) // src
&& t_MsgAddressInt.validate_skip(ops, cs, weak) // dest
&& t_Grams.validate_skip(ops, cs, weak); // import_fee
case ext_out_msg_info:
return cs.advance(2) && t_MsgAddressInt.validate_skip(cs, weak) // src
&& t_MsgAddressExt.validate_skip(cs, weak) // dest
&& cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
return cs.advance(2) && t_MsgAddressInt.validate_skip(ops, cs, weak) // src
&& t_MsgAddressExt.validate_skip(ops, cs, weak) // dest
&& cs.advance(64 + 32); // created_lt:uint64 created_at:uint32
}
return false;
}
@ -699,28 +721,29 @@ const CommonMsgInfo t_CommonMsgInfo;
const TickTock t_TickTock;
const RefAnything t_RefCell;
bool StateInit::validate_skip(vm::CellSlice& cs, bool weak) const {
return Maybe<UInt>{5}.validate_skip(cs, weak) // split_depth:(Maybe (## 5))
&& Maybe<TickTock>{}.validate_skip(cs, weak) // special:(Maybe TickTock)
&& Maybe<RefAnything>{}.validate_skip(cs, weak) // code:(Maybe ^Cell)
&& Maybe<RefAnything>{}.validate_skip(cs, weak) // data:(Maybe ^Cell)
&& Maybe<RefAnything>{}.validate_skip(cs, weak); // library:(Maybe ^Cell)
bool StateInit::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return Maybe<UInt>{5}.validate_skip(ops, cs, weak) // split_depth:(Maybe (## 5))
&& Maybe<TickTock>{}.validate_skip(ops, cs, weak) // special:(Maybe TickTock)
&& Maybe<RefAnything>{}.validate_skip(ops, cs, weak) // code:(Maybe ^Cell)
&& Maybe<RefAnything>{}.validate_skip(ops, cs, weak) // data:(Maybe ^Cell)
&& Maybe<RefAnything>{}.validate_skip(ops, cs, weak); // library:(Maybe ^Cell)
}
bool StateInit::get_ticktock(vm::CellSlice& cs, int& ticktock) const {
bool have_tt;
ticktock = 0;
return Maybe<UInt>{5}.validate_skip(cs) && cs.fetch_bool_to(have_tt) && (!have_tt || cs.fetch_uint_to(2, ticktock));
return Maybe<UInt>{5}.validate_skip_upto(1, cs) && cs.fetch_bool_to(have_tt) &&
(!have_tt || cs.fetch_uint_to(2, ticktock));
}
const StateInit t_StateInit;
bool Message::validate_skip(vm::CellSlice& cs, bool weak) const {
bool Message::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
static const Maybe<Either<StateInit, RefTo<StateInit>>> init_type;
static const Either<Anything, RefAnything> body_type;
return t_CommonMsgInfo.validate_skip(cs, weak) // info:CommonMsgInfo
&& init_type.validate_skip(cs, weak) // init:(Maybe (Either StateInit ^StateInit))
&& body_type.validate_skip(cs, weak); // body:(Either X ^X)
return t_CommonMsgInfo.validate_skip(ops, cs, weak) // info:CommonMsgInfo
&& init_type.validate_skip(ops, cs, weak) // init:(Maybe (Either StateInit ^StateInit))
&& body_type.validate_skip(ops, cs, weak); // body:(Either X ^X)
}
bool Message::extract_info(vm::CellSlice& cs) const {
@ -738,7 +761,7 @@ bool Message::is_internal(Ref<vm::Cell> ref) const {
const Message t_Message;
const RefTo<Message> t_Ref_Message;
bool IntermediateAddress::validate_skip(vm::CellSlice& cs, bool weak) const {
bool IntermediateAddress::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case interm_addr_regular:
return cs.advance(1) && cs.fetch_ulong(7) <= 96U;
@ -773,12 +796,12 @@ int IntermediateAddress::get_size(const vm::CellSlice& cs) const {
const IntermediateAddress t_IntermediateAddress;
bool MsgEnvelope::validate_skip(vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(4) == 4 // msg_envelope#4
&& t_IntermediateAddress.validate_skip(cs, weak) // cur_addr:IntermediateAddress
&& t_IntermediateAddress.validate_skip(cs, weak) // next_addr:IntermediateAddress
&& t_Grams.validate_skip(cs, weak) // fwd_fee_remaining:Grams
&& t_Ref_Message.validate_skip(cs, weak); // msg:^Message
bool MsgEnvelope::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(4) == 4 // msg_envelope#4
&& t_IntermediateAddress.validate_skip(ops, cs, weak) // cur_addr:IntermediateAddress
&& t_IntermediateAddress.validate_skip(ops, cs, weak) // next_addr:IntermediateAddress
&& t_Grams.validate_skip(ops, cs, weak) // fwd_fee_remaining:Grams
&& t_Ref_Message.validate_skip(ops, cs, weak); // msg:^Message
}
bool MsgEnvelope::skip(vm::CellSlice& cs) const {
@ -827,10 +850,10 @@ bool MsgEnvelope::get_created_lt(const vm::CellSlice& cs, unsigned long long& cr
const MsgEnvelope t_MsgEnvelope;
const RefTo<MsgEnvelope> t_Ref_MsgEnvelope;
bool StorageUsed::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_7.validate_skip(cs, weak) // cells:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(cs, weak) // bits:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(cs, weak); // public_cells:(VarUInteger 7)
bool StorageUsed::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_7.validate_skip(ops, cs, weak) // cells:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(ops, cs, weak) // bits:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(ops, cs, weak); // public_cells:(VarUInteger 7)
}
bool StorageUsed::skip(vm::CellSlice& cs) const {
@ -841,9 +864,9 @@ bool StorageUsed::skip(vm::CellSlice& cs) const {
const StorageUsed t_StorageUsed;
bool StorageUsedShort::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_7.validate_skip(cs, weak) // cells:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(cs, weak); // bits:(VarUInteger 7)
bool StorageUsedShort::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_7.validate_skip(ops, cs, weak) // cells:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(ops, cs, weak); // bits:(VarUInteger 7)
}
bool StorageUsedShort::skip(vm::CellSlice& cs) const {
@ -861,22 +884,22 @@ bool StorageInfo::skip(vm::CellSlice& cs) const {
&& t_Maybe_Grams.skip(cs); // due_payment:(Maybe Grams)
}
bool StorageInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_StorageUsed.validate_skip(cs, weak) // used:StorageUsed
&& cs.advance(32) // last_paid:uint32
&& t_Maybe_Grams.validate_skip(cs, weak); // due_payment:(Maybe Grams)
bool StorageInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_StorageUsed.validate_skip(ops, cs, weak) // used:StorageUsed
&& cs.advance(32) // last_paid:uint32
&& t_Maybe_Grams.validate_skip(ops, cs, weak); // due_payment:(Maybe Grams)
}
const StorageInfo t_StorageInfo;
bool AccountState::validate_skip(vm::CellSlice& cs, bool weak) const {
bool AccountState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case account_uninit:
return cs.advance(2);
case account_frozen:
return cs.advance(2 + 256);
case account_active:
return cs.advance(1) && t_StateInit.validate_skip(cs, weak);
return cs.advance(1) && t_StateInit.validate_skip(ops, cs, weak);
}
return false;
}
@ -899,8 +922,9 @@ bool AccountStorage::skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) c
return cs.advance(64) && t_CurrencyCollection.skip_copy(cb, cs) && t_AccountState.skip(cs);
}
bool AccountStorage::validate_skip(vm::CellSlice& cs, bool weak) const {
return cs.advance(64) && t_CurrencyCollection.validate_skip(cs, weak) && t_AccountState.validate_skip(cs, weak);
bool AccountStorage::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.advance(64) && t_CurrencyCollection.validate_skip(ops, cs, weak) &&
t_AccountState.validate_skip(ops, cs, weak);
}
const AccountStorage t_AccountStorage;
@ -918,15 +942,15 @@ bool Account::skip(vm::CellSlice& cs) const {
return false;
}
bool Account::validate_skip(vm::CellSlice& cs, bool weak) const {
bool Account::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case account_none:
return allow_empty && cs.advance(1);
case account:
return cs.advance(1) // account$1
&& t_MsgAddressInt.validate_skip(cs, weak) // addr:MsgAddressInt
&& t_StorageInfo.validate_skip(cs, weak) // storage_stat:StorageInfo
&& t_AccountStorage.validate_skip(cs, weak); // storage:AccountStorage
return cs.advance(1) // account$1
&& t_MsgAddressInt.validate_skip(ops, cs, weak) // addr:MsgAddressInt
&& t_StorageInfo.validate_skip(ops, cs, weak) // storage_stat:StorageInfo
&& t_AccountStorage.validate_skip(ops, cs, weak); // storage:AccountStorage
}
return false;
}
@ -1010,19 +1034,19 @@ bool HashmapAugNode::skip(vm::CellSlice& cs) const {
}
}
bool HashmapAugNode::validate_skip(vm::CellSlice& cs, bool weak) const {
bool HashmapAugNode::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
if (n < 0) {
return false;
}
if (!n) {
// ahmn_leaf
vm::CellSlice cs_extra{cs};
if (!aug.extra_type.validate_skip(cs, weak)) {
if (!aug.extra_type.validate_skip(ops, cs, weak)) {
return false;
}
cs_extra.cut_tail(cs);
vm::CellSlice cs_value{cs};
if (!aug.value_type.validate_skip(cs, weak)) {
if (!aug.value_type.validate_skip(ops, cs, weak)) {
return false;
}
cs_value.cut_tail(cs);
@ -1033,13 +1057,14 @@ bool HashmapAugNode::validate_skip(vm::CellSlice& cs, bool weak) const {
return false;
}
HashmapAug branch_type{n - 1, aug};
if (!branch_type.validate_ref(cs.prefetch_ref(0), weak) || !branch_type.validate_ref(cs.prefetch_ref(1), weak)) {
if (!branch_type.validate_ref(ops, cs.prefetch_ref(0), weak) ||
!branch_type.validate_ref(ops, cs.prefetch_ref(1), weak)) {
return false;
}
auto cs_left = load_cell_slice(cs.fetch_ref());
auto cs_right = load_cell_slice(cs.fetch_ref());
vm::CellSlice cs_extra{cs};
if (!aug.extra_type.validate_skip(cs, weak)) {
if (!aug.extra_type.validate_skip(ops, cs, weak)) {
return false;
}
cs_extra.cut_tail(cs);
@ -1052,9 +1077,9 @@ bool HashmapAug::skip(vm::CellSlice& cs) const {
return HmLabel{n}.skip(cs, l) && HashmapAugNode{n - l, aug}.skip(cs);
}
bool HashmapAug::validate_skip(vm::CellSlice& cs, bool weak) const {
bool HashmapAug::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int l;
return HmLabel{n}.validate_skip(cs, weak, l) && HashmapAugNode{n - l, aug}.validate_skip(cs, weak);
return HmLabel{n}.validate_skip(cs, weak, l) && HashmapAugNode{n - l, aug}.validate_skip(ops, cs, weak);
}
bool HashmapAug::extract_extra(vm::CellSlice& cs) const {
@ -1062,20 +1087,20 @@ bool HashmapAug::extract_extra(vm::CellSlice& cs) const {
return HmLabel{n}.skip(cs, l) && (l == n || cs.advance_refs(2)) && aug.extra_type.extract(cs);
}
bool HashmapAugE::validate_skip(vm::CellSlice& cs, bool weak) const {
bool HashmapAugE::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
Ref<vm::CellSlice> extra;
switch (get_tag(cs)) {
case ahme_empty:
return cs.advance(1) && (extra = root_type.aug.extra_type.validate_fetch(cs, weak)).not_null() &&
return cs.advance(1) && (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() &&
root_type.aug.check_empty(extra.unique_write());
case ahme_root:
if (cs.advance(1) && root_type.validate_ref(cs.prefetch_ref(), weak)) {
if (cs.advance(1) && root_type.validate_ref(ops, cs.prefetch_ref(), weak)) {
bool special;
auto cs_root = load_cell_slice_special(cs.fetch_ref(), special);
if (special) {
return weak;
}
return (extra = root_type.aug.extra_type.validate_fetch(cs, weak)).not_null() &&
return (extra = root_type.aug.extra_type.validate_fetch(ops, cs, weak)).not_null() &&
root_type.extract_extra(cs_root) && extra->contents_equal(cs_root);
}
break;
@ -1099,9 +1124,10 @@ bool DepthBalanceInfo::skip(vm::CellSlice& cs) const {
cs); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection = DepthBalanceInfo;
}
bool DepthBalanceInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(5) <= 30 && t_CurrencyCollection.validate_skip(
cs, weak); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection
bool DepthBalanceInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(5) <= 30 &&
t_CurrencyCollection.validate_skip(ops, cs,
weak); // depth_balance$_ split_depth:(#<= 30) balance:CurrencyCollection
}
bool DepthBalanceInfo::null_value(vm::CellBuilder& cb) const {
@ -1137,10 +1163,10 @@ bool TrStoragePhase::skip(vm::CellSlice& cs) const {
&& t_AccStatusChange.skip(cs); // status_change:AccStatusChange
}
bool TrStoragePhase::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_Grams.validate_skip(cs, weak) // storage_fees_collected:Grams
&& t_Maybe_Grams.validate_skip(cs, weak) // storage_fees_due:Grams
&& t_AccStatusChange.validate_skip(cs, weak); // status_change:AccStatusChange
bool TrStoragePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_Grams.validate_skip(ops, cs, weak) // storage_fees_collected:Grams
&& t_Maybe_Grams.validate_skip(ops, cs, weak) // storage_fees_due:Grams
&& t_AccStatusChange.validate_skip(ops, cs, weak); // status_change:AccStatusChange
}
bool TrStoragePhase::get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const {
@ -1164,9 +1190,9 @@ bool TrCreditPhase::skip(vm::CellSlice& cs) const {
&& t_CurrencyCollection.skip(cs); // credit:CurrencyCollection
}
bool TrCreditPhase::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_Maybe_Grams.validate_skip(cs, weak) // due_fees_collected:(Maybe Grams)
&& t_CurrencyCollection.validate_skip(cs, weak); // credit:CurrencyCollection
bool TrCreditPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_Maybe_Grams.validate_skip(ops, cs, weak) // due_fees_collected:(Maybe Grams)
&& t_CurrencyCollection.validate_skip(ops, cs, weak); // credit:CurrencyCollection
}
const TrCreditPhase t_TrCreditPhase;
@ -1182,15 +1208,15 @@ bool TrComputeInternal1::skip(vm::CellSlice& cs) const {
// vm_final_state_hash:uint256
}
bool TrComputeInternal1::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_7.validate_skip(cs, weak) // gas_used:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(cs, weak) // gas_limit:(VarUInteger 7)
&& Maybe<VarUInteger>{3}.validate_skip(cs, weak) // gas_credit:(Maybe (VarUInteger 3))
&& cs.advance(8 + 32) // mode:int8 exit_code:int32
&& Maybe<Int>{32}.validate_skip(cs, weak) // exit_arg:(Maybe int32)
&& cs.advance(32 + 256 + 256); // vm_steps:uint32
// vm_init_state_hash:uint256
// vm_final_state_hash:uint256
bool TrComputeInternal1::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_VarUInteger_7.validate_skip(ops, cs, weak) // gas_used:(VarUInteger 7)
&& t_VarUInteger_7.validate_skip(ops, cs, weak) // gas_limit:(VarUInteger 7)
&& Maybe<VarUInteger>{3}.validate_skip(ops, cs, weak) // gas_credit:(Maybe (VarUInteger 3))
&& cs.advance(8 + 32) // mode:int8 exit_code:int32
&& Maybe<Int>{32}.validate_skip(ops, cs, weak) // exit_arg:(Maybe int32)
&& cs.advance(32 + 256 + 256); // vm_steps:uint32
// vm_init_state_hash:uint256
// vm_final_state_hash:uint256
}
const TrComputeInternal1 t_TrComputeInternal1;
@ -1209,14 +1235,14 @@ bool TrComputePhase::skip(vm::CellSlice& cs) const {
return false;
}
bool TrComputePhase::validate_skip(vm::CellSlice& cs, bool weak) const {
bool TrComputePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case tr_phase_compute_skipped:
return cs.advance(1) && t_ComputeSkipReason.validate_skip(cs, weak);
return cs.advance(1) && t_ComputeSkipReason.validate_skip(ops, cs, weak);
case tr_phase_compute_vm:
return cs.advance(1 + 3) // tr_phase_compute_vm$1 success:Bool msg_state_used:Bool account_activated:Bool
&& t_Grams.validate_skip(cs, weak) // gas_fees:Grams
&& t_Ref_TrComputeInternal1.validate_skip(cs, weak); // ^[ gas_used:(..) .. ]
&& t_Grams.validate_skip(ops, cs, weak) // gas_fees:Grams
&& t_Ref_TrComputeInternal1.validate_skip(ops, cs, weak); // ^[ gas_used:(..) .. ]
}
return false;
}
@ -1236,17 +1262,17 @@ bool TrActionPhase::skip(vm::CellSlice& cs) const {
&& t_StorageUsedShort.skip(cs); // tot_msg_size:StorageUsedShort
}
bool TrActionPhase::validate_skip(vm::CellSlice& cs, bool weak) const {
return cs.advance(3) // success:Bool valid:Bool no_funds:Bool
&& t_AccStatusChange.validate_skip(cs, weak) // status_change:AccStatusChange
&& t_Maybe_Grams.validate_skip(cs, weak) // total_fwd_fees:(Maybe Grams)
&& t_Maybe_Grams.validate_skip(cs, weak) // total_action_fees:(Maybe Grams)
&& cs.advance(32) // result_code:int32
&& Maybe<Int>{32}.validate_skip(cs, weak) // result_arg:(Maybe int32)
&& cs.advance(16 * 4 + 256) // tot_actions:uint16 spec_actions:uint16
// skipped_actions:uint16 msgs_created:uint16
// action_list_hash:uint256
&& t_StorageUsedShort.validate_skip(cs, weak); // tot_msg_size:StorageUsed
bool TrActionPhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.advance(3) // success:Bool valid:Bool no_funds:Bool
&& t_AccStatusChange.validate_skip(ops, cs, weak) // status_change:AccStatusChange
&& t_Maybe_Grams.validate_skip(ops, cs, weak) // total_fwd_fees:(Maybe Grams)
&& t_Maybe_Grams.validate_skip(ops, cs, weak) // total_action_fees:(Maybe Grams)
&& cs.advance(32) // result_code:int32
&& Maybe<Int>{32}.validate_skip(ops, cs, weak) // result_arg:(Maybe int32)
&& cs.advance(16 * 4 + 256) // tot_actions:uint16 spec_actions:uint16
// skipped_actions:uint16 msgs_created:uint16
// action_list_hash:uint256
&& t_StorageUsedShort.validate_skip(ops, cs, weak); // tot_msg_size:StorageUsed
}
const TrActionPhase t_TrActionPhase;
@ -1268,19 +1294,19 @@ bool TrBouncePhase::skip(vm::CellSlice& cs) const {
return false;
}
bool TrBouncePhase::validate_skip(vm::CellSlice& cs, bool weak) const {
bool TrBouncePhase::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case tr_phase_bounce_negfunds:
return cs.advance(2); // tr_phase_bounce_negfunds$00
case tr_phase_bounce_nofunds:
return cs.advance(2) // tr_phase_bounce_nofunds$01
&& t_StorageUsedShort.validate_skip(cs, weak) // msg_size:StorageUsedShort
&& t_Grams.validate_skip(cs, weak); // req_fwd_fees:Grams
return cs.advance(2) // tr_phase_bounce_nofunds$01
&& t_StorageUsedShort.validate_skip(ops, cs, weak) // msg_size:StorageUsedShort
&& t_Grams.validate_skip(ops, cs, weak); // req_fwd_fees:Grams
case tr_phase_bounce_ok:
return cs.advance(1) // tr_phase_bounce_ok$1
&& t_StorageUsedShort.validate_skip(cs, weak) // msg_size:StorageUsedShort
&& t_Grams.validate_skip(cs, weak) // msg_fees:Grams
&& t_Grams.validate_skip(cs, weak); // fwd_fees:Grams
return cs.advance(1) // tr_phase_bounce_ok$1
&& t_StorageUsedShort.validate_skip(ops, cs, weak) // msg_size:StorageUsedShort
&& t_Grams.validate_skip(ops, cs, weak) // msg_fees:Grams
&& t_Grams.validate_skip(ops, cs, weak); // fwd_fees:Grams
}
return false;
}
@ -1300,7 +1326,7 @@ bool SplitMergeInfo::skip(vm::CellSlice& cs) const {
return cs.advance(6 + 6 + 256 + 256);
}
bool SplitMergeInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
bool SplitMergeInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
if (!cs.have(6 + 6 + 256 + 256)) {
return false;
}
@ -1370,52 +1396,52 @@ bool TransactionDescr::skip(vm::CellSlice& cs) const {
return false;
}
bool TransactionDescr::validate_skip(vm::CellSlice& cs, bool weak) const {
bool TransactionDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case trans_ord:
return cs.advance(4 + 1) // trans_ord$0000 credit_first:Bool
&& Maybe<TrStoragePhase>{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& Maybe<TrCreditPhase>{}.validate_skip(cs, weak) // credit_ph:(Maybe TrCreditPhase)
&& t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(1) // aborted:Bool
&& Maybe<TrBouncePhase>{}.validate_skip(cs, weak) // bounce:(Maybe TrBouncePhase)
&& cs.advance(1); // destroyed:Bool
return cs.advance(4 + 1) // trans_ord$0000 credit_first:Bool
&& Maybe<TrStoragePhase>{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& Maybe<TrCreditPhase>{}.validate_skip(ops, cs, weak) // credit_ph:(Maybe TrCreditPhase)
&& t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(1) // aborted:Bool
&& Maybe<TrBouncePhase>{}.validate_skip(ops, cs, weak) // bounce:(Maybe TrBouncePhase)
&& cs.advance(1); // destroyed:Bool
case trans_storage:
return cs.advance(4) // trans_storage$0001
&& t_TrStoragePhase.validate_skip(cs, weak); // storage_ph:TrStoragePhase
return cs.advance(4) // trans_storage$0001
&& t_TrStoragePhase.validate_skip(ops, cs, weak); // storage_ph:TrStoragePhase
case trans_tick_tock:
return cs.advance(4) // trans_tick_tock$001 is_tock:Bool
&& t_TrStoragePhase.validate_skip(cs, weak) // storage_ph:TrStoragePhase
&& t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
return cs.advance(4) // trans_tick_tock$001 is_tock:Bool
&& t_TrStoragePhase.validate_skip(ops, cs, weak) // storage_ph:TrStoragePhase
&& t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
case trans_split_prepare:
return cs.advance(4) // trans_split_prepare$0100
&& t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
&& Maybe<TrStoragePhase>{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
return cs.advance(4) // trans_split_prepare$0100
&& t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
&& Maybe<TrStoragePhase>{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& t_TrComputePhase.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
case trans_split_install:
return cs.advance(4) // trans_split_install$0101
&& t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
&& t_Ref_Transaction.validate_skip(cs, weak) // prepare_transaction:^Transaction
&& cs.advance(1); // installed:Bool
return cs.advance(4) // trans_split_install$0101
&& t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
&& t_Ref_Transaction.validate_skip(ops, cs, weak) // prepare_transaction:^Transaction
&& cs.advance(1); // installed:Bool
case trans_merge_prepare:
return cs.advance(4) // trans_merge_prepare$0110
&& t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
&& t_TrStoragePhase.validate_skip(cs, weak) // storage_ph:TrStoragePhase
&& cs.advance(1); // aborted:Bool
return cs.advance(4) // trans_merge_prepare$0110
&& t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
&& t_TrStoragePhase.validate_skip(ops, cs, weak) // storage_ph:TrStoragePhase
&& cs.advance(1); // aborted:Bool
case trans_merge_install:
return cs.advance(4) // trans_merge_install$0111
&& t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
&& t_Ref_Transaction.validate_skip(cs, weak) // prepare_transaction:^Transaction
&& Maybe<TrStoragePhase>{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& Maybe<TrCreditPhase>{}.validate_skip(cs, weak) // credit_ph:(Maybe TrCreditPhase)
&& Maybe<TrComputePhase>{}.validate_skip(cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
return cs.advance(4) // trans_merge_install$0111
&& t_SplitMergeInfo.validate_skip(ops, cs, weak) // split_info:SplitMergeInfo
&& t_Ref_Transaction.validate_skip(ops, cs, weak) // prepare_transaction:^Transaction
&& Maybe<TrStoragePhase>{}.validate_skip(ops, cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& Maybe<TrCreditPhase>{}.validate_skip(ops, cs, weak) // credit_ph:(Maybe TrCreditPhase)
&& Maybe<TrComputePhase>{}.validate_skip(ops, cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(ops, cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
}
return false;
}
@ -1479,9 +1505,9 @@ bool Transaction_aux::skip(vm::CellSlice& cs) const {
&& HashmapE{15, t_Ref_Message}.skip(cs); // out_msgs:(HashmapE 15 ^Message)
}
bool Transaction_aux::validate_skip(vm::CellSlice& cs, bool weak) const {
return Maybe<RefTo<Message>>{}.validate_skip(cs, weak) // in_msg:(Maybe ^Message)
&& HashmapE{15, t_Ref_Message}.validate_skip(cs, weak); // out_msgs:(HashmapE 15 ^Message)
bool Transaction_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return Maybe<RefTo<Message>>{}.validate_skip(ops, cs, weak) // in_msg:(Maybe ^Message)
&& HashmapE{15, t_Ref_Message}.validate_skip(ops, cs, weak); // out_msgs:(HashmapE 15 ^Message)
}
const Transaction_aux t_Transaction_aux;
@ -1498,18 +1524,18 @@ bool Transaction::skip(vm::CellSlice& cs) const {
&& RefTo<TransactionDescr>{}.skip(cs); // description:^TransactionDescr
}
bool Transaction::validate_skip(vm::CellSlice& cs, bool weak) const {
bool Transaction::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(4) == 7 // transaction$0111
&&
cs.advance(
256 + 64 + 256 + 64 + 32 +
15) // account_addr:uint256 lt:uint64 prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 outmsg_cnt:uint15
&& t_AccountStatus.validate_skip(cs, weak) // orig_status:AccountStatus
&& t_AccountStatus.validate_skip(cs, weak) // end_status:AccountStatus
&& RefTo<Transaction_aux>{}.validate_skip(cs, weak) // ^[ in_msg:... out_msgs:... ]
&& t_CurrencyCollection.validate_skip(cs, weak) // total_fees:CurrencyCollection
&& t_Ref_HashUpdate.validate_skip(cs, weak) // state_update:^(HASH_UPDATE Account)
&& RefTo<TransactionDescr>{}.validate_skip(cs, weak); // description:^TransactionDescr
&& t_AccountStatus.validate_skip(ops, cs, weak) // orig_status:AccountStatus
&& t_AccountStatus.validate_skip(ops, cs, weak) // end_status:AccountStatus
&& RefTo<Transaction_aux>{}.validate_skip(ops, cs, weak) // ^[ in_msg:... out_msgs:... ]
&& t_CurrencyCollection.validate_skip(ops, cs, weak) // total_fees:CurrencyCollection
&& t_Ref_HashUpdate.validate_skip(ops, cs, weak) // state_update:^(HASH_UPDATE Account)
&& RefTo<TransactionDescr>{}.validate_skip(ops, cs, weak); // description:^TransactionDescr
}
bool Transaction::get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const {
@ -1573,12 +1599,12 @@ bool AccountBlock::skip(vm::CellSlice& cs) const {
&& cs.advance_refs(1); // state_update:^(HASH_UPDATE Account)
}
bool AccountBlock::validate_skip(vm::CellSlice& cs, bool weak) const {
bool AccountBlock::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.fetch_ulong(4) == 5 // acc_trans#5
&& cs.advance(256) // account_addr:bits256
&&
t_AccountTransactions.validate_skip(cs, weak) // transactions:(HashmapAug 64 ^Transaction CurrencyCollection)
&& t_Ref_HashUpdate.validate_skip(cs, weak); // state_update:^(HASH_UPDATE Account)
&& t_AccountTransactions.validate_skip(ops, cs,
weak) // transactions:(HashmapAug 64 ^Transaction CurrencyCollection)
&& t_Ref_HashUpdate.validate_skip(ops, cs, weak); // state_update:^(HASH_UPDATE Account)
}
bool AccountBlock::get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const {
@ -1598,8 +1624,8 @@ const Aug_ShardAccountBlocks aug_ShardAccountBlocks;
const HashmapAugE t_ShardAccountBlocks{256,
aug_ShardAccountBlocks}; // (HashmapAugE 256 AccountBlock CurrencyCollection)
bool ImportFees::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_Grams.validate_skip(cs, weak) && t_CurrencyCollection.validate_skip(cs, weak);
bool ImportFees::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_Grams.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak);
}
bool ImportFees::skip(vm::CellSlice& cs) const {
@ -1654,44 +1680,44 @@ bool InMsg::skip(vm::CellSlice& cs) const {
return false;
}
bool InMsg::validate_skip(vm::CellSlice& cs, bool weak) const {
bool InMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case msg_import_ext:
return cs.advance(3) // msg_import_ext$000
&& t_Ref_Message.validate_skip(cs, weak) // msg:^Message
&& t_Ref_Transaction.validate_skip(cs, weak); // transaction:^Transaction
return cs.advance(3) // msg_import_ext$000
&& t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message
&& t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction
case msg_import_ihr:
return cs.advance(3) // msg_import_ihr$010
&& t_Ref_Message.validate_skip(cs, weak) // msg:^Message
&& t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
&& t_Grams.validate_skip(cs, weak) // ihr_fee:Grams
&& t_RefCell.validate_skip(cs, weak); // proof_created:^Cell
return cs.advance(3) // msg_import_ihr$010
&& t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message
&& t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
&& t_Grams.validate_skip(ops, cs, weak) // ihr_fee:Grams
&& t_RefCell.validate_skip(ops, cs, weak); // proof_created:^Cell
case msg_import_imm:
return cs.advance(3) // msg_import_imm$011
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
&& t_Grams.validate_skip(cs, weak); // fwd_fee:Grams
return cs.advance(3) // msg_import_imm$011
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
&& t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams
case msg_import_fin:
return cs.advance(3) // msg_import_fin$100
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
&& t_Grams.validate_skip(cs, weak); // fwd_fee:Grams
return cs.advance(3) // msg_import_fin$100
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
&& t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams
case msg_import_tr:
return cs.advance(3) // msg_import_tr$101
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
&& t_Grams.validate_skip(cs, weak); // transit_fee:Grams
return cs.advance(3) // msg_import_tr$101
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
&& t_Grams.validate_skip(ops, cs, weak); // transit_fee:Grams
case msg_discard_fin:
return cs.advance(3) // msg_discard_fin$110
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
&& cs.advance(64) // transaction_id:uint64
&& t_Grams.validate_skip(cs, weak); // fwd_fee:Grams
return cs.advance(3) // msg_discard_fin$110
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
&& cs.advance(64) // transaction_id:uint64
&& t_Grams.validate_skip(ops, cs, weak); // fwd_fee:Grams
case msg_discard_tr:
return cs.advance(3) // msg_discard_tr$111
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // in_msg:^MsgEnvelope
&& cs.advance(64) // transaction_id:uint64
&& t_Grams.validate_skip(cs, weak) // fwd_fee:Grams
&& t_RefCell.validate_skip(cs, weak); // proof_delivered:^Cell
return cs.advance(3) // msg_discard_tr$111
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // in_msg:^MsgEnvelope
&& cs.advance(64) // transaction_id:uint64
&& t_Grams.validate_skip(ops, cs, weak) // fwd_fee:Grams
&& t_RefCell.validate_skip(ops, cs, weak); // proof_delivered:^Cell
}
return false;
}
@ -1829,37 +1855,37 @@ bool OutMsg::skip(vm::CellSlice& cs) const {
return false;
}
bool OutMsg::validate_skip(vm::CellSlice& cs, bool weak) const {
bool OutMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
switch (get_tag(cs)) {
case msg_export_ext:
return cs.advance(3) // msg_export_ext$000
&& t_Ref_Message.validate_skip(cs, weak) // msg:^Message
&& t_Ref_Transaction.validate_skip(cs, weak); // transaction:^Transaction
return cs.advance(3) // msg_export_ext$000
&& t_Ref_Message.validate_skip(ops, cs, weak) // msg:^Message
&& t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction
case msg_export_imm:
return cs.advance(3) // msg_export_imm$010
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(cs, weak) // transaction:^Transaction
&& RefTo<InMsg>{}.validate_skip(cs, weak); // reimport:^InMsg
return cs.advance(3) // msg_export_imm$010
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(ops, cs, weak) // transaction:^Transaction
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak); // reimport:^InMsg
case msg_export_new:
return cs.advance(3) // msg_export_new$001
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(cs, weak); // transaction:^Transaction
return cs.advance(3) // msg_export_new$001
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
&& t_Ref_Transaction.validate_skip(ops, cs, weak); // transaction:^Transaction
case msg_export_tr:
return cs.advance(3) // msg_export_tr$011
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
&& RefTo<InMsg>{}.validate_skip(cs, weak); // imported:^InMsg
return cs.advance(3) // msg_export_tr$011
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak); // imported:^InMsg
case msg_export_deq_imm:
return cs.advance(3) // msg_export_deq_imm$100
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
&& RefTo<InMsg>{}.validate_skip(cs, weak); // reimport:^InMsg
return cs.advance(3) // msg_export_deq_imm$100
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak); // reimport:^InMsg
case msg_export_deq:
return cs.advance(3) // msg_export_deq$110
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
&& cs.advance(64); // import_block_lt:uint64
return cs.advance(3) // msg_export_deq$110
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
&& cs.advance(64); // import_block_lt:uint64
case msg_export_tr_req:
return cs.advance(3) // msg_export_tr_req$111
&& t_Ref_MsgEnvelope.validate_skip(cs, weak) // out_msg:^MsgEnvelope
&& RefTo<InMsg>{}.validate_skip(cs, weak); // imported:^InMsg
return cs.advance(3) // msg_export_tr_req$111
&& t_Ref_MsgEnvelope.validate_skip(ops, cs, weak) // out_msg:^MsgEnvelope
&& RefTo<InMsg>{}.validate_skip(ops, cs, weak); // imported:^InMsg
}
return false;
}
@ -1932,8 +1958,8 @@ const OutMsg t_OutMsg;
const Aug_OutMsgDescr aug_OutMsgDescr;
const OutMsgDescr t_OutMsgDescr;
bool EnqueuedMsg::validate_skip(vm::CellSlice& cs, bool weak) const {
return cs.advance(64) && t_Ref_MsgEnvelope.validate_skip(cs, weak);
bool EnqueuedMsg::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.advance(64) && t_Ref_MsgEnvelope.validate_skip(ops, cs, weak);
}
const EnqueuedMsg t_EnqueuedMsg;
@ -1967,9 +1993,9 @@ bool OutMsgQueueInfo::skip(vm::CellSlice& cs) const {
return t_OutMsgQueue.skip(cs) && t_ProcessedInfo.skip(cs) && t_IhrPendingInfo.skip(cs);
}
bool OutMsgQueueInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_OutMsgQueue.validate_skip(cs, weak) && t_ProcessedInfo.validate_skip(cs, weak) &&
t_IhrPendingInfo.validate_skip(cs, weak);
bool OutMsgQueueInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_OutMsgQueue.validate_skip(ops, cs, weak) && t_ProcessedInfo.validate_skip(ops, cs, weak) &&
t_IhrPendingInfo.validate_skip(ops, cs, weak);
}
const OutMsgQueueInfo t_OutMsgQueueInfo;
@ -2005,10 +2031,27 @@ bool ExtBlkRef::unpack(Ref<vm::CellSlice> cs_ref, ton::BlockIdExt& blkid, ton::L
return true;
}
bool ExtBlkRef::store(vm::CellBuilder& cb, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const {
return cb.store_long_bool(end_lt, 64) // ext_blk_ref$_ end_lt:uint64
&& cb.store_long_bool(blkid.seqno(), 32) // seq_no:uint32
&& cb.store_bits_bool(blkid.root_hash) // root_hash:bits256
&& cb.store_bits_bool(blkid.file_hash); // file_hash:bits256 = ExtBlkRef;
}
Ref<vm::Cell> ExtBlkRef::pack_cell(const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const {
vm::CellBuilder cb;
return store(cb, blkid, end_lt) ? cb.finalize() : Ref<vm::Cell>{};
}
bool ExtBlkRef::pack_to(Ref<vm::Cell>& cell, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const {
vm::CellBuilder cb;
return store(cb, blkid, end_lt) && cb.finalize_to(cell);
}
const ExtBlkRef t_ExtBlkRef;
const BlkMasterInfo t_BlkMasterInfo;
bool ShardIdent::validate_skip(vm::CellSlice& cs, bool weak) const {
bool ShardIdent::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int shard_pfx_len, workchain_id;
unsigned long long shard_pfx;
if (cs.fetch_ulong(2) == 0 && cs.fetch_uint_to(6, shard_pfx_len) && cs.fetch_int_to(32, workchain_id) &&
@ -2073,8 +2116,8 @@ bool ShardIdent::pack(vm::CellBuilder& cb, ton::ShardIdFull data) const {
const ShardIdent t_ShardIdent;
bool BlockIdExt::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_ShardIdent.validate_skip(cs, weak) && cs.advance(32 + 256 * 2);
bool BlockIdExt::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_ShardIdent.validate_skip(ops, cs, weak) && cs.advance(32 + 256 * 2);
}
bool BlockIdExt::unpack(vm::CellSlice& cs, ton::BlockIdExt& data) const {
@ -2107,21 +2150,21 @@ bool ShardState::skip(vm::CellSlice& cs) const {
&& Maybe<RefTo<McStateExtra>>{}.skip(cs); // custom:(Maybe ^McStateExtra)
}
bool ShardState::validate_skip(vm::CellSlice& cs, bool weak) const {
bool ShardState::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
int seq_no;
return get_tag(cs) == shard_state && cs.advance(64) // shard_state#9023afe2 blockchain_id:int32
&& t_ShardIdent.validate_skip(cs, weak) // shard_id:ShardIdent
&& t_ShardIdent.validate_skip(ops, cs, weak) // shard_id:ShardIdent
&& cs.fetch_int_to(32, seq_no) // seq_no:int32
&& seq_no >= -1 // { seq_no >= -1 }
&& cs.advance(32 + 32 + 64 + 32) // vert_seq_no:# gen_utime:uint32 gen_lt:uint64 min_ref_mc_seqno:uint32
&& t_Ref_OutMsgQueueInfo.validate_skip(cs, weak) // out_msg_queue_info:^OutMsgQueueInfo
&& cs.advance(1) // before_split:Bool
&& t_ShardAccounts.validate_skip_ref(cs, weak) // accounts:^ShardAccounts
&& t_Ref_OutMsgQueueInfo.validate_skip(ops, cs, weak) // out_msg_queue_info:^OutMsgQueueInfo
&& cs.advance(1) // before_split:Bool
&& t_ShardAccounts.validate_skip_ref(ops, cs, weak) // accounts:^ShardAccounts
&&
t_ShardState_aux.validate_skip_ref(
cs,
ops, cs,
weak) // ^[ total_balance:CurrencyCollection total_validator_fees:CurrencyCollection libraries:(HashmapE 256 LibDescr) master_ref:(Maybe BlkMasterInfo) ]
&& Maybe<RefTo<McStateExtra>>{}.validate_skip(cs, weak); // custom:(Maybe ^McStateExtra)
&& Maybe<RefTo<McStateExtra>>{}.validate_skip(ops, cs, weak); // custom:(Maybe ^McStateExtra)
}
const ShardState t_ShardState;
@ -2134,12 +2177,12 @@ bool ShardState_aux::skip(vm::CellSlice& cs) const {
&& Maybe<BlkMasterInfo>{}.skip(cs); // master_ref:(Maybe BlkMasterInfo)
}
bool ShardState_aux::validate_skip(vm::CellSlice& cs, bool weak) const {
return cs.advance(128) // overload_history:uint64 underload_history:uint64
&& t_CurrencyCollection.validate_skip(cs, weak) // total_balance:CurrencyCollection
&& t_CurrencyCollection.validate_skip(cs, weak) // total_validator_fees:CurrencyCollection
&& HashmapE{256, t_LibDescr}.validate_skip(cs, weak) // libraries:(HashmapE 256 LibDescr)
&& Maybe<BlkMasterInfo>{}.validate_skip(cs, weak); // master_ref:(Maybe BlkMasterInfo)
bool ShardState_aux::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return cs.advance(128) // overload_history:uint64 underload_history:uint64
&& t_CurrencyCollection.validate_skip(ops, cs, weak) // total_balance:CurrencyCollection
&& t_CurrencyCollection.validate_skip(ops, cs, weak) // total_validator_fees:CurrencyCollection
&& HashmapE{256, t_LibDescr}.validate_skip(ops, cs, weak) // libraries:(HashmapE 256 LibDescr)
&& Maybe<BlkMasterInfo>{}.validate_skip(ops, cs, weak); // master_ref:(Maybe BlkMasterInfo)
}
const ShardState_aux t_ShardState_aux;
@ -2150,10 +2193,10 @@ bool LibDescr::skip(vm::CellSlice& cs) const {
&& Hashmap{256, t_True}.skip(cs); // publishers:(Hashmap 256 False)
}
bool LibDescr::validate_skip(vm::CellSlice& cs, bool weak) const {
return get_tag(cs) == shared_lib_descr && cs.advance(2) // shared_lib_descr$00
&& cs.fetch_ref().not_null() // lib:^Cell
&& Hashmap{256, t_True}.validate_skip(cs, weak); // publishers:(Hashmap 256 False)
bool LibDescr::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return get_tag(cs) == shared_lib_descr && cs.advance(2) // shared_lib_descr$00
&& cs.fetch_ref().not_null() // lib:^Cell
&& Hashmap{256, t_True}.validate_skip(ops, cs, weak); // publishers:(Hashmap 256 False)
}
const LibDescr t_LibDescr;
@ -2163,9 +2206,9 @@ bool BlkPrevInfo::skip(vm::CellSlice& cs) const {
&& (!merged || t_ExtBlkRef.skip(cs)); // prev_alt:merged?ExtBlkRef
}
bool BlkPrevInfo::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_ExtBlkRef.validate_skip(cs, weak) // prev_blk_info$_ {merged:#} prev:ExtBlkRef
&& (!merged || t_ExtBlkRef.validate_skip(cs, weak)); // prev_alt:merged?ExtBlkRef
bool BlkPrevInfo::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_ExtBlkRef.validate_skip(ops, cs, weak) // prev_blk_info$_ {merged:#} prev:ExtBlkRef
&& (!merged || t_ExtBlkRef.validate_skip(ops, cs, weak)); // prev_alt:merged?ExtBlkRef
}
const BlkPrevInfo t_BlkPrevInfo_0{0};
@ -2174,8 +2217,8 @@ bool McStateExtra::skip(vm::CellSlice& cs) const {
return block::gen::t_McStateExtra.skip(cs);
}
bool McStateExtra::validate_skip(vm::CellSlice& cs, bool weak) const {
return block::gen::t_McStateExtra.validate_skip(cs, weak); // ??
bool McStateExtra::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return block::gen::t_McStateExtra.validate_skip(ops, cs, weak); // ??
}
const McStateExtra t_McStateExtra;
@ -2202,8 +2245,8 @@ bool ShardFeeCreated::skip(vm::CellSlice& cs) const {
return t_CurrencyCollection.skip(cs) && t_CurrencyCollection.skip(cs);
}
bool ShardFeeCreated::validate_skip(vm::CellSlice& cs, bool weak) const {
return t_CurrencyCollection.validate_skip(cs, weak) && t_CurrencyCollection.validate_skip(cs, weak);
bool ShardFeeCreated::validate_skip(int* ops, vm::CellSlice& cs, bool weak) const {
return t_CurrencyCollection.validate_skip(ops, cs, weak) && t_CurrencyCollection.validate_skip(ops, cs, weak);
}
bool ShardFeeCreated::null_value(vm::CellBuilder& cb) const {

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
#include "common/refcnt.hpp"
@ -59,7 +59,7 @@ struct VarUInteger final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
unsigned long long as_uint(const vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override {
@ -78,7 +78,7 @@ struct VarUIntegerPos final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
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;
@ -92,7 +92,7 @@ struct VarInteger final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
long long as_int(const vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override {
@ -107,7 +107,7 @@ struct VarIntegerNz final : TLB_Complex {
ln = 32 - td::count_leading_zeroes32(n - 1);
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
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;
@ -123,13 +123,13 @@ struct Unary final : TLB {
bool skip(vm::CellSlice& cs, int& n) const {
return validate_skip(cs, false, n);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
return cs.advance(get_size(cs));
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return skip(cs);
}
bool skip(vm::CellSlice& cs) const override {
return validate_skip(cs);
return cs.advance(get_size(cs));
}
bool validate(const vm::CellSlice& cs, bool weak = false) const override {
bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override {
return cs.have(get_size(cs));
}
};
@ -149,7 +149,7 @@ struct HmLabel final : TLB_Complex {
int n;
return skip(cs, n);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
int n;
return validate_skip(cs, weak, n);
}
@ -162,7 +162,7 @@ struct Hashmap final : TLB_Complex {
Hashmap(int _n, const TLB& _val_type) : value_type(_val_type), n(_n) {
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
struct HashmapNode final : TLB_Complex {
@ -173,7 +173,7 @@ struct HashmapNode final : TLB_Complex {
}
int get_size(const vm::CellSlice& cs) const override;
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return n > 0 ? hmn_fork : n;
}
@ -185,7 +185,7 @@ struct HashmapE final : TLB {
HashmapE(int _n, const TLB& _val_type) : root_type(_n, _val_type) {
}
int get_size(const vm::CellSlice& cs) const override;
bool validate(const vm::CellSlice& cs, bool weak = false) const override;
bool validate(int* ops, const vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(1);
}
@ -221,7 +221,7 @@ struct HashmapAug final : TLB_Complex {
HashmapAug(int _n, const AugmentationCheckData& _aug) : aug(_aug), n(_n) {
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_extra(vm::CellSlice& cs) const;
};
@ -232,7 +232,7 @@ struct HashmapAugNode final : TLB_Complex {
HashmapAugNode(int _n, const AugmentationCheckData& _aug) : aug(_aug), n(_n) {
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return n > 0 ? ahmn_fork : n;
}
@ -244,7 +244,7 @@ struct HashmapAugE final : TLB_Complex {
HashmapAugE(int _n, const AugmentationCheckData& _aug) : root_type(_n, std::move(_aug)) {
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_extra(vm::CellSlice& cs) const;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(1);
@ -252,7 +252,7 @@ struct HashmapAugE final : TLB_Complex {
};
struct Grams final : TLB_Complex {
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override;
bool store_integer_value(vm::CellBuilder& cb, const td::BigInt256& value) const override;
@ -264,7 +264,7 @@ extern const Grams t_Grams;
struct MsgAddressInt final : TLB_Complex {
enum { addr_std = 2, addr_var = 3 };
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(2);
}
@ -285,6 +285,8 @@ struct MsgAddressInt final : TLB_Complex {
bool rewrite = true) const;
bool extract_std_address(vm::CellSlice& cs, ton::WorkchainId& workchain, ton::StdSmcAddress& addr,
bool rewrite = true) const;
bool store_std_address(vm::CellBuilder& cb, ton::WorkchainId workchain, const ton::StdSmcAddress& addr) const;
Ref<vm::CellSlice> pack_std_address(ton::WorkchainId workchain, const ton::StdSmcAddress& addr) const;
};
extern const MsgAddressInt t_MsgAddressInt;
@ -301,7 +303,7 @@ extern const MsgAddressExt t_MsgAddressExt;
struct MsgAddress final : TLB_Complex {
enum { addr_none = 0, addr_ext = 1, addr_std = 2, addr_var = 3 };
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(2);
}
@ -316,8 +318,8 @@ struct ExtraCurrencyCollection final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return dict_type.get_size(cs);
}
bool validate(const vm::CellSlice& cs, bool weak) const override {
return dict_type.validate(cs, weak);
bool validate(int* ops, const vm::CellSlice& cs, bool weak) const override {
return dict_type.validate(ops, cs, weak);
}
bool null_value(vm::CellBuilder& cb) const override {
return cb.store_zeroes_bool(1);
@ -346,7 +348,7 @@ extern const ExtraCurrencyCollection t_ExtraCurrencyCollection;
struct CurrencyCollection final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
td::RefInt256 as_integer_skip(vm::CellSlice& cs) const override;
bool null_value(vm::CellBuilder& cb) const override {
return cb.store_bits_same_bool(1 + 4, false);
@ -369,7 +371,7 @@ extern const CurrencyCollection t_CurrencyCollection;
struct CommonMsgInfo final : TLB_Complex {
enum { int_msg_info = 0, ext_in_msg_info = 2, ext_out_msg_info = 3 };
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
int v = (int)cs.prefetch_ulong(2);
return v == 1 ? int_msg_info : v;
@ -400,14 +402,14 @@ struct TickTock final : TLB {
extern const TickTock t_TickTock;
struct StateInit final : TLB_Complex {
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_ticktock(vm::CellSlice& cs, int& ticktock) const;
};
extern const StateInit t_StateInit;
struct Message final : TLB_Complex {
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_info(vm::CellSlice& cs) const;
bool get_created_lt(vm::CellSlice& cs, unsigned long long& created_lt) const;
bool is_internal(const vm::CellSlice& cs) const {
@ -423,7 +425,7 @@ struct IntermediateAddress final : TLB_Complex {
enum { interm_addr_regular = 0, interm_addr_simple = 2, interm_addr_ext = 3 };
int get_size(const vm::CellSlice& cs) const override;
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool fetch_regular(vm::CellSlice& cs, int& use_dst_bits) const {
return cs.fetch_uint_to(8, use_dst_bits) && use_dst_bits <= 96;
}
@ -437,7 +439,7 @@ extern const IntermediateAddress t_IntermediateAddress;
struct MsgEnvelope final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool extract_fwd_fees_remaining(vm::CellSlice& cs) const;
struct Record {
typedef MsgEnvelope type_class;
@ -461,28 +463,28 @@ extern const RefTo<MsgEnvelope> t_Ref_MsgEnvelope;
struct StorageUsed final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const StorageUsed t_StorageUsed;
struct StorageUsedShort final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const StorageUsedShort t_StorageUsedShort;
struct StorageInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const StorageInfo t_StorageInfo;
struct AccountState final : TLB_Complex {
enum { account_uninit = 0, account_frozen = 1, account_active = 2 };
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
int t = (int)cs.prefetch_ulong(2);
return t == 3 ? account_active : t;
@ -494,7 +496,7 @@ extern const AccountState t_AccountState;
struct AccountStorage final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const;
};
@ -506,7 +508,7 @@ struct Account final : TLB_Complex {
Account(bool _allow_empty = false) : allow_empty(_allow_empty) {
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
// Ref<vm::CellSlice> get_balance(const vm::CellSlice& cs) const;
bool skip_copy_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const;
bool skip_copy_depth_balance(vm::CellBuilder& cb, vm::CellSlice& cs) const;
@ -551,8 +553,8 @@ struct ShardAccount final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance_ext(0x140, 1);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
return cs.advance(0x140) && t_Ref_Account.validate_skip(cs, weak);
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return cs.advance(0x140) && t_Ref_Account.validate_skip(ops, cs, weak);
}
static bool unpack(vm::CellSlice& cs, Record& info) {
return info.unpack(cs);
@ -567,7 +569,7 @@ extern const ShardAccount t_ShardAccount;
struct DepthBalanceInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool null_value(vm::CellBuilder& cb) const override;
bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override;
};
@ -588,8 +590,8 @@ struct ShardAccounts final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(cs, weak);
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(ops, cs, weak);
}
};
@ -613,7 +615,7 @@ extern const AccStatusChange t_AccStatusChange;
struct TrStoragePhase final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const;
bool maybe_get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const;
};
@ -622,14 +624,14 @@ extern const TrStoragePhase t_TrStoragePhase;
struct TrCreditPhase final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const TrCreditPhase t_TrCreditPhase;
struct TrComputeInternal1 final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
struct ComputeSkipReason final : TLB {
@ -637,7 +639,7 @@ struct ComputeSkipReason final : TLB {
int get_size(const vm::CellSlice& cs) const override {
return 2;
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return get_tag(cs) >= 0 && cs.advance(2);
}
int get_tag(const vm::CellSlice& cs) const override {
@ -651,7 +653,7 @@ extern const ComputeSkipReason t_ComputeSkipReason;
struct TrComputePhase final : TLB_Complex {
enum { tr_phase_compute_skipped = 0, tr_phase_compute_vm = 1 };
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(1);
}
@ -661,7 +663,7 @@ extern const TrComputePhase t_TrComputePhase;
struct TrActionPhase final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const TrActionPhase t_TrActionPhase;
@ -669,7 +671,7 @@ extern const TrActionPhase t_TrActionPhase;
struct TrBouncePhase final : TLB_Complex {
enum { tr_phase_bounce_negfunds = 0, tr_phase_bounce_nofunds = 1, tr_phase_bounce_ok = 2 };
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override;
};
@ -677,7 +679,7 @@ extern const TrBouncePhase t_TrBouncePhase;
struct SplitMergeInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const SplitMergeInfo t_SplitMergeInfo;
@ -693,7 +695,7 @@ struct TransactionDescr final : TLB_Complex {
trans_merge_install = 7
};
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override;
bool skip_to_storage_phase(vm::CellSlice& cs, bool& found) const;
bool get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const;
@ -703,14 +705,14 @@ extern const TransactionDescr t_TransactionDescr;
struct Transaction_aux final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const Transaction_aux t_Transaction_aux;
struct Transaction final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const;
bool get_descr(Ref<vm::Cell> cell, Ref<vm::Cell>& tdescr) const;
bool get_descr(vm::CellSlice& cs, Ref<vm::Cell>& tdescr) const;
@ -733,7 +735,7 @@ struct HashUpdate final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance(8 + 256 * 2);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return cs.fetch_ulong(8) == 0x72 && cs.advance(256 * 2);
}
};
@ -743,7 +745,7 @@ extern const RefTo<HashUpdate> t_Ref_HashUpdate;
struct AccountBlock final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const;
};
@ -760,7 +762,7 @@ extern const HashmapAugE t_ShardAccountBlocks; // (HashmapAugE 256 AccountBlock
struct ImportFees final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool null_value(vm::CellBuilder& cb) const override {
return cb.store_bits_same_bool(4 + 4 + 1, false);
}
@ -780,7 +782,7 @@ struct InMsg final : TLB_Complex {
msg_discard_tr = 7
};
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(3);
}
@ -800,7 +802,7 @@ struct OutMsg final : TLB_Complex {
msg_export_tr_req = 7
};
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(3);
}
@ -828,8 +830,8 @@ struct InMsgDescr final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(cs, weak);
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(ops, cs, weak);
}
};
@ -851,8 +853,8 @@ struct OutMsgDescr final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(cs, weak);
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(ops, cs, weak);
}
};
@ -865,7 +867,7 @@ struct EnqueuedMsg final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance_ext(0x10040);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, EnqueuedMsgDescr& descr) const {
return descr.unpack(cs);
}
@ -889,8 +891,8 @@ struct OutMsgQueue final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return dict_type.skip(cs);
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(cs, weak);
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override {
return dict_type.validate_skip(ops, cs, weak);
}
};
@ -908,7 +910,7 @@ extern const HashmapE t_IhrPendingInfo;
struct OutMsgQueueInfo final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const OutMsgQueueInfo t_OutMsgQueueInfo;
@ -921,6 +923,9 @@ struct ExtBlkRef final : TLB {
}
bool unpack(vm::CellSlice& cs, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const;
bool unpack(Ref<vm::CellSlice> cs_ref, ton::BlockIdExt& blkid, ton::LogicalTime* end_lt = nullptr) const;
bool store(vm::CellBuilder& cb, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const;
Ref<vm::Cell> pack_cell(const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const;
bool pack_to(Ref<vm::Cell>& cell, const ton::BlockIdExt& blkid, ton::LogicalTime end_lt) const;
};
extern const ExtBlkRef t_ExtBlkRef;
@ -941,7 +946,7 @@ struct ShardIdent final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance(get_size(cs));
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
@ -980,7 +985,7 @@ struct BlockIdExt final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override {
return cs.advance(get_size(cs));
}
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool unpack(vm::CellSlice& cs, ton::BlockIdExt& data) const;
bool pack(vm::CellBuilder& cb, const ton::BlockIdExt& data) const;
};
@ -990,7 +995,7 @@ extern const BlockIdExt t_BlockIdExt;
struct ShardState final : TLB_Complex {
enum { shard_state = (int)0x9023afe2, split_state = 0x5f327da5 };
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(32) == shard_state ? shard_state : -1;
}
@ -1000,7 +1005,7 @@ extern const ShardState t_ShardState;
struct ShardState_aux final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return 0;
}
@ -1011,7 +1016,7 @@ extern const ShardState_aux t_ShardState_aux;
struct LibDescr final : TLB_Complex {
enum { shared_lib_descr = 0 };
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override {
return (int)cs.prefetch_ulong(2);
}
@ -1024,7 +1029,7 @@ struct BlkPrevInfo final : TLB_Complex {
BlkPrevInfo(bool _merged) : merged(_merged) {
}
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const BlkPrevInfo t_BlkPrevInfo_0;
@ -1032,7 +1037,7 @@ extern const BlkPrevInfo t_BlkPrevInfo_0;
struct McStateExtra final : TLB_Complex {
enum { masterchain_state_extra = 0xcc26 };
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
};
extern const McStateExtra t_McStateExtra;
@ -1069,7 +1074,7 @@ extern const Aug_OldMcBlocksInfo aug_OldMcBlocksInfo;
struct ShardFeeCreated final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool validate_skip(int* ops, vm::CellSlice& cs, bool weak = false) const override;
bool null_value(vm::CellBuilder& cb) const override;
bool add_values(vm::CellBuilder& cb, vm::CellSlice& cs1, vm::CellSlice& cs2) const override;
};

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 "td/utils/bits.h"
#include "block/block.h"
@ -789,10 +789,11 @@ td::Status ShardState::unpack_state(ton::BlockIdExt blkid, Ref<vm::Cell> prev_st
return td::Status::Error(-666, "ShardState of "s + id_.to_str() + " does not contain a valid global_balance");
}
if (extra.r1.flags & 1) {
if (extra.r1.block_create_stats->prefetch_ulong(8) != 0x17) {
if (extra.r1.block_create_stats->prefetch_ulong(8) == 0x17) {
block_create_stats_ = std::make_unique<vm::Dictionary>(extra.r1.block_create_stats->prefetch_ref(), 256);
} else {
return td::Status::Error(-666, "ShardState of "s + id_.to_str() + " does not contain a valid BlockCreateStats");
}
block_create_stats_ = std::make_unique<vm::Dictionary>(extra.r1.block_create_stats->prefetch_ref(), 256);
} else {
block_create_stats_ = std::make_unique<vm::Dictionary>(256);
}
@ -812,11 +813,11 @@ td::Status ShardState::unpack_out_msg_queue_info(Ref<vm::Cell> out_msg_queue_inf
LOG(DEBUG) << "unpacking ProcessedUpto of our previous block " << id_.to_str();
block::gen::t_ProcessedInfo.print(std::cerr, qinfo.proc_info);
}
if (!block::gen::t_ProcessedInfo.validate_csr(qinfo.proc_info)) {
if (!block::gen::t_ProcessedInfo.validate_csr(1024, qinfo.proc_info)) {
return td::Status::Error(
-666, "ProcessedInfo in the state of "s + id_.to_str() + " is invalid according to automated validity checks");
}
if (!block::gen::t_IhrPendingInfo.validate_csr(qinfo.ihr_pending)) {
if (!block::gen::t_IhrPendingInfo.validate_csr(1024, qinfo.ihr_pending)) {
return td::Status::Error(
-666, "IhrPendingInfo in the state of "s + id_.to_str() + " is invalid according to automated validity checks");
}
@ -1035,7 +1036,7 @@ td::Status ShardState::split(ton::ShardIdFull subshard) {
LOG(DEBUG) << "splitting total_balance";
auto old_total_balance = total_balance_;
auto accounts_extra = account_dict_->get_root_extra();
if (!(accounts_extra.write().advance(5) && total_balance_.validate_unpack(accounts_extra))) {
if (!(accounts_extra.write().advance(5) && total_balance_.validate_unpack(accounts_extra, 1024))) {
LOG(ERROR) << "cannot unpack CurrencyCollection from the root of newly-split accounts dictionary";
return td::Status::Error(
-666, "error splitting total balance in account dictionary of shardchain state "s + id_.to_str());
@ -1084,16 +1085,16 @@ int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull ol
});
}
bool CurrencyCollection::validate() const {
return is_valid() && td::sgn(grams) >= 0 && validate_extra();
bool CurrencyCollection::validate(int max_cells) const {
return is_valid() && td::sgn(grams) >= 0 && validate_extra(max_cells);
}
bool CurrencyCollection::validate_extra() const {
bool CurrencyCollection::validate_extra(int max_cells) const {
if (extra.is_null()) {
return true;
}
vm::CellBuilder cb;
return cb.store_maybe_ref(extra) && block::tlb::t_ExtraCurrencyCollection.validate_ref(cb.finalize());
return cb.store_maybe_ref(extra) && block::tlb::t_ExtraCurrencyCollection.validate_ref(max_cells, cb.finalize());
}
bool CurrencyCollection::add(const CurrencyCollection& a, const CurrencyCollection& b, CurrencyCollection& c) {
@ -1264,8 +1265,8 @@ bool CurrencyCollection::unpack(Ref<vm::CellSlice> csr) {
return unpack_CurrencyCollection(std::move(csr), grams, extra) || invalidate();
}
bool CurrencyCollection::validate_unpack(Ref<vm::CellSlice> csr) {
return (csr.not_null() && block::tlb::t_CurrencyCollection.validate(*csr) &&
bool CurrencyCollection::validate_unpack(Ref<vm::CellSlice> csr, int max_cells) {
return (csr.not_null() && block::tlb::t_CurrencyCollection.validate_upto(max_cells, *csr) &&
unpack_CurrencyCollection(std::move(csr), grams, extra)) ||
invalidate();
}
@ -1592,7 +1593,7 @@ bool check_one_config_param(Ref<vm::CellSlice> cs_ref, td::ConstBitPtr key, td::
} else if (idx < 0) {
return true;
}
bool ok = block::gen::ConfigParam{idx}.validate_ref(std::move(cell));
bool ok = block::gen::ConfigParam{idx}.validate_ref(1024, std::move(cell));
if (!ok) {
LOG(ERROR) << "configuration parameter #" << idx << " is invalid";
}
@ -1745,7 +1746,7 @@ td::Status unpack_block_prev_blk_ext(Ref<vm::Cell> block_root, const ton::BlockI
block::gen::ExtBlkRef::Record mcref; // _ ExtBlkRef = BlkMasterInfo;
ton::ShardIdFull shard;
if (!(tlb::unpack_cell(block_root, blk) && tlb::unpack_cell(blk.info, info) && !info.version &&
block::tlb::t_ShardIdent.unpack(info.shard.write(), shard) && !info.vert_seq_no &&
block::tlb::t_ShardIdent.unpack(info.shard.write(), shard) &&
(!info.not_master || tlb::unpack_cell(info.master_ref, mcref)))) {
return td::Status::Error("cannot unpack block header");
}
@ -1809,6 +1810,9 @@ td::Status unpack_block_prev_blk_ext(Ref<vm::Cell> block_root, const ton::BlockI
} else {
mc_blkid = ton::BlockIdExt{ton::masterchainId, ton::shardIdAll, mcref.seq_no, mcref.root_hash, mcref.file_hash};
}
if (shard.is_masterchain() && info.vert_seqno_incr && !info.key_block) {
return td::Status::Error("non-key masterchain block cannot have vert_seqno_incr set");
}
return td::Status::OK();
}
@ -1817,7 +1821,7 @@ td::Status check_block_header(Ref<vm::Cell> block_root, const ton::BlockIdExt& i
block::gen::BlockInfo::Record info;
ton::ShardIdFull shard;
if (!(tlb::unpack_cell(block_root, blk) && tlb::unpack_cell(blk.info, info) && !info.version &&
block::tlb::t_ShardIdent.unpack(info.shard.write(), shard) && !info.vert_seq_no)) {
block::tlb::t_ShardIdent.unpack(info.shard.write(), shard))) {
return td::Status::Error("cannot unpack block header");
}
ton::BlockId hdr_id{shard, (unsigned)info.seq_no};
@ -1843,6 +1847,18 @@ td::Status check_block_header(Ref<vm::Cell> block_root, const ton::BlockIdExt& i
return td::Status::OK();
}
std::unique_ptr<vm::Dictionary> get_block_create_stats_dict(Ref<vm::Cell> state_root) {
block::gen::ShardStateUnsplit::Record info;
block::gen::McStateExtra::Record extra;
block::gen::BlockCreateStats::Record_block_create_stats cstats;
if (!(::tlb::unpack_cell(std::move(state_root), info) && info.custom->size_refs() &&
::tlb::unpack_cell(info.custom->prefetch_ref(), extra) && (extra.r1.flags & 1) &&
::tlb::csr_unpack(std::move(extra.r1.block_create_stats), cstats))) {
return {};
}
return std::make_unique<vm::Dictionary>(std::move(cstats.counters), 256);
}
std::unique_ptr<vm::AugmentedDictionary> get_prev_blocks_dict(Ref<vm::Cell> state_root) {
block::gen::ShardStateUnsplit::Record info;
block::gen::McStateExtra::Record extra_info;

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
#include "common/refcnt.hpp"
@ -163,12 +163,12 @@ struct MsgProcessedUpto {
MsgProcessedUpto(ton::ShardId _shard, ton::BlockSeqno _mcseqno, ton::LogicalTime _lt, td::ConstBitPtr _hash)
: shard(_shard), mc_seqno(_mcseqno), last_inmsg_lt(_lt), last_inmsg_hash(_hash) {
}
bool operator<(const MsgProcessedUpto& other) const& {
bool operator<(const MsgProcessedUpto& other) const & {
return shard < other.shard || (shard == other.shard && mc_seqno < other.mc_seqno);
}
bool contains(const MsgProcessedUpto& other) const&;
bool contains(const MsgProcessedUpto& other) const &;
bool contains(ton::ShardId other_shard, ton::LogicalTime other_lt, td::ConstBitPtr other_hash,
ton::BlockSeqno other_mc_seqno) const&;
ton::BlockSeqno other_mc_seqno) const &;
// NB: this is for checking whether we have already imported an internal message
bool already_processed(const EnqueuedMsgDescr& msg) const;
};
@ -323,8 +323,8 @@ struct CurrencyCollection {
grams.clear();
return false;
}
bool validate() const;
bool validate_extra() const;
bool validate(int max_cells = 1024) const;
bool validate_extra(int max_cells = 1024) const;
bool operator==(const CurrencyCollection& other) const;
bool operator!=(const CurrencyCollection& other) const {
return !operator==(other);
@ -360,7 +360,7 @@ struct CurrencyCollection {
bool fetch(vm::CellSlice& cs);
bool fetch_exact(vm::CellSlice& cs);
bool unpack(Ref<vm::CellSlice> csr);
bool validate_unpack(Ref<vm::CellSlice> csr);
bool validate_unpack(Ref<vm::CellSlice> csr, int max_cells = 1024);
Ref<vm::CellSlice> pack() const;
bool pack_to(Ref<vm::CellSlice>& csr) const {
return (csr = pack()).not_null();
@ -514,6 +514,9 @@ struct DiscountedCounter {
return last_updated == other.last_updated && total == other.total && cnt2048 <= other.cnt2048 + 1 &&
other.cnt2048 <= cnt2048 + 1 && cnt65536 <= other.cnt65536 + 1 && other.cnt65536 <= cnt65536 + 1;
}
bool modified_since(ton::UnixTime utime) const {
return last_updated >= utime;
}
bool validate();
bool increase_by(unsigned count, ton::UnixTime now);
bool fetch(vm::CellSlice& cs);
@ -629,6 +632,8 @@ td::Status unpack_block_prev_blk_try(Ref<vm::Cell> block_root, const ton::BlockI
td::Status check_block_header(Ref<vm::Cell> block_root, const ton::BlockIdExt& id,
ton::Bits256* store_shard_hash_to = nullptr);
std::unique_ptr<vm::Dictionary> get_block_create_stats_dict(Ref<vm::Cell> state_root);
std::unique_ptr<vm::AugmentedDictionary> get_prev_blocks_dict(Ref<vm::Cell> state_root);
bool get_old_mc_block_id(vm::AugmentedDictionary* prev_blocks_dict, ton::BlockSeqno seqno, ton::BlockIdExt& blkid,
ton::LogicalTime* end_lt = nullptr);

View File

@ -366,6 +366,10 @@ action_send_msg#0ec3c86d mode:(## 8)
action_set_code#ad4de08e new_code:^Cell = OutAction;
action_reserve_currency#36e6b809 mode:(## 8)
currency:CurrencyCollection = OutAction;
libref_hash$0 lib_hash:bits256 = LibRef;
libref_ref$1 library:^Cell = LibRef;
action_change_library#26fa1dd4 mode:(## 7) { mode <= 2 }
libref:LibRef = OutAction;
out_list_node$_ prev:^Cell action:OutAction = OutListNode;
//
@ -505,6 +509,7 @@ _ (HashmapAugE 32 KeyExtBlkRef KeyMaxLt) = OldMcBlocksInfo;
counters#_ last_updated:uint32 total:uint64 cnt2048:uint64 cnt65536:uint64 = Counters;
creator_info#4 mc_blocks:Counters shard_blocks:Counters = CreatorStats;
block_create_stats#17 counters:(HashmapE 256 CreatorStats) = BlockCreateStats;
block_create_stats_ext#34 counters:(HashmapAugE 256 CreatorStats uint32) = BlockCreateStats;
masterchain_state_extra#cc26
shard_hashes:ShardHashes
@ -678,3 +683,77 @@ top_block_descr#d5 proof_for:BlockIdExt signatures:(Maybe ^BlockSignatures)
// COLLATED DATA
//
top_block_descr_set#4ac789f3 collection:(HashmapE 96 ^TopBlockDescr) = TopBlockDescrSet;
//
// TVM REFLECTION
//
vm_stk_null#00 = VmStackValue;
vm_stk_tinyint#01 value:int64 = VmStackValue;
vm_stk_int#0201_ value:int257 = VmStackValue;
vm_stk_nan#02ff = VmStackValue;
vm_stk_cell#03 cell:^Cell = VmStackValue;
_ cell:^Cell st_bits:(## 10) end_bits:(## 10) { st_bits <= end_bits }
st_ref:(#<= 4) end_ref:(#<= 4) { st_ref <= end_ref } = VmCellSlice;
vm_stk_slice#04 _:VmCellSlice = VmStackValue;
vm_stk_builder#05 cell:^Cell = VmStackValue;
vm_stk_cont#06 cont:VmCont = VmStackValue;
vm_tupref_nil$_ = VmTupleRef 0;
vm_tupref_single$_ entry:^VmStackValue = VmTupleRef 1;
vm_tupref_any$_ {n:#} ref:^(VmTuple (n + 2)) = VmTupleRef (n + 2);
vm_tuple_nil$_ = VmTuple 0;
vm_tuple_tcons$_ {n:#} head:(VmTupleRef n) tail:^VmStackValue = VmTuple (n + 1);
vm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue;
vm_stack#_ depth:(## 24) stack:(VmStackList depth) = VmStack;
vm_stk_cons#_ {n:#} rest:^(VmStackList n) tos:VmStackValue = VmStackList (n + 1);
vm_stk_nil#_ = VmStackList 0;
_ cregs:(HashmapE 4 VmStackValue) = VmSaveList;
gas_limits#_ remaining:int64 _:^[ max_limit:int64 cur_limit:int64 credit:int64 ]
= VmGasLimits;
_ libraries:(HashmapE 256 ^Cell) = VmLibraries;
vm_ctl_data$_ nargs:(Maybe uint13) stack:(Maybe VmStack) save:VmSaveList
cp:(Maybe int16) = VmControlData;
vmc_std$00 cdata:VmControlData code:VmCellSlice = VmCont;
vmc_envelope$01 cdata:VmControlData next:^VmCont = VmCont;
vmc_quit$1000 exit_code:int32 = VmCont;
vmc_quit_exc$1001 = VmCont;
vmc_repeat$10100 count:uint63 body:^VmCont after:^VmCont = VmCont;
vmc_until$110000 body:^VmCont after:^VmCont = VmCont;
vmc_again$110001 body:^VmCont = VmCont;
vmc_while_cond$110010 cond:^VmCont body:^VmCont
after:^VmCont = VmCont;
vmc_while_body$110011 cond:^VmCont body:^VmCont
after:^VmCont = VmCont;
vmc_pushint$1111 value:int32 next:^VmCont = VmCont;
//
// DNS RECORDS
//
_ (HashmapE 16 ^DNSRecord) = DNS_RecordSet;
chunk_ref$_ {n:#} ref:^(TextChunks (n + 1)) = TextChunkRef (n + 1);
chunk_ref_empty$_ = TextChunkRef 0;
text_chunk$_ {n:#} len:(## 8) data:(bits (len * 8)) next:(TextChunkRef n) = TextChunks (n + 1);
text_chunk_empty$_ = TextChunks 0;
text$_ chunks:(## 8) rest:(TextChunks chunks) = Text;
dns_text#1eda _:Text = DNSRecord;
dns_next_resolver#ba93 resolver:MsgAddressInt = DNSRecord; // usually in record #-1
dns_adnl_address#ad01 adnl_addr:bits256 flags:(## 8) { flags <= 1 }
proto_list:flags . 0?ProtoList = DNSRecord; // often in record #2
proto_list_nil$0 = ProtoList;
proto_list_next$1 head:Protocol tail:ProtoList = ProtoList;
proto_http#4854 = Protocol;
dns_smc_address#9fd3 smc_addr:MsgAddressInt flags:(## 8) { flags <= 1 }
cap_list:flags . 0?SmcCapList = DNSRecord; // often in record #1
cap_list_nil$0 = SmcCapList;
cap_list_next$1 head:SmcCapability tail:SmcCapList = SmcCapList;
cap_method_seqno#5371 = SmcCapability;
cap_method_pubkey#71f4 = SmcCapability;
cap_is_wallet#2177 = SmcCapability;
cap_name#ff name:Text = SmcCapability;

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 "check-proof.h"
#include "block/block.h"
@ -219,7 +219,17 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const
}
td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const {
TRY_RESULT_PREFIX(root, vm::std_boc_deserialize(state.as_slice(), true), "cannot deserialize account state");
TRY_RESULT_PREFIX(true_root, vm::std_boc_deserialize(state.as_slice(), true), "cannot deserialize account state");
Ref<vm::Cell> root;
if (is_virtualized && true_root.not_null()) {
root = vm::MerkleProof::virtualize(true_root, 1);
if (root.is_null()) {
return td::Status::Error("account state proof is invalid");
}
} else {
root = true_root;
}
if (blk != ref_blk && ref_blk.id.seqno != ~0U) {
return td::Status::Error(PSLICE() << "obtained getAccountState() for a different reference block " << blk.to_str()
@ -241,6 +251,7 @@ td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, b
TRY_STATUS(block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt,
&res.last_trans_hash, &res.gen_utime, &res.gen_lt));
res.root = std::move(root);
res.true_root = std::move(true_root);
return res;
}

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
@ -44,10 +44,11 @@ struct AccountState {
td::BufferSlice shard_proof;
td::BufferSlice proof;
td::BufferSlice state;
bool is_virtualized{false};
struct Info {
td::Ref<vm::Cell> root;
ton::LogicalTime last_trans_lt = 0;
td::Ref<vm::Cell> root, true_root;
ton::LogicalTime last_trans_lt{0};
ton::Bits256 last_trans_hash;
ton::LogicalTime gen_lt{0};
td::uint32 gen_utime{0};

View File

@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include <cassert>
#include <algorithm>
@ -633,6 +633,88 @@ void init_words_custom(fift::Dictionary& d) {
d.def_stack_word("isWorkchainDescr? ", interpret_is_workchain_descr);
}
tlb::TypenameLookup tlb_dict;
// ( S -- T -1 or 0 ) Looks up TLB type by name
void interpret_tlb_type_lookup(vm::Stack& stack) {
auto ptr = tlb_dict.lookup(stack.pop_string());
if (ptr) {
stack.push_make_object<tlb::TlbTypeHolder>(ptr);
}
stack.push_bool(ptr);
}
td::Ref<tlb::TlbTypeHolder> pop_tlb_type(vm::Stack& stack) {
auto res = stack.pop_object<tlb::TlbTypeHolder>();
if (res.is_null()) {
throw vm::VmError{vm::Excno::type_chk, "not a TLB type"};
}
return res;
}
// ( T -- S ) Gets TLB type name
void interpret_tlb_type_name(vm::Stack& stack) {
stack.push_string((*pop_tlb_type(stack))->get_type_name());
}
// ( T -- ) Prints TLB type name
void interpret_print_tlb_type(vm::Stack& stack) {
std::cout << (*pop_tlb_type(stack))->get_type_name();
}
// ( s T -- ) Dumps (part of) slice s as a value of TLB type T
void interpret_tlb_dump_as(vm::Stack& stack) {
auto tp = pop_tlb_type(stack);
(*tp)->print(std::cout, stack.pop_cellslice());
}
// ( s T -- s' S -1 or 0 )
// Detects prefix of slice s that is a value of TLB type T, returns the remainder as s', and prints the value into String S.
void interpret_tlb_dump_to_str(vm::Stack& stack) {
auto tp = pop_tlb_type(stack);
auto cs = stack.pop_cellslice();
std::ostringstream os;
bool ok = (*tp)->print_skip(os, cs.write());
if (ok) {
stack.push(std::move(cs));
stack.push_string(os.str());
}
stack.push_bool(ok);
}
// ( s T -- s' -1 or 0 ) Skips the only prefix of slice s that can be a value of TLB type T
void interpret_tlb_skip(vm::Stack& stack) {
auto tp = pop_tlb_type(stack);
auto cs = stack.pop_cellslice();
bool ok = (*tp)->skip(cs.write());
if (ok) {
stack.push(std::move(cs));
}
stack.push_bool(ok);
}
// ( s T -- s' -1 or 0 ) Checks whether a prefix of slice s is a valid value of TLB type T, and skips it
void interpret_tlb_validate_skip(vm::Stack& stack) {
auto tp = pop_tlb_type(stack);
auto cs = stack.pop_cellslice();
bool ok = (*tp)->validate_skip_upto(1048576, cs.write());
if (ok) {
stack.push(std::move(cs));
}
stack.push_bool(ok);
}
void init_words_tlb(fift::Dictionary& d) {
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);
d.def_stack_word("tlb. ", interpret_print_tlb_type);
d.def_stack_word("tlb-dump-as ", interpret_tlb_dump_as);
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);
}
void usage(const char* progname) {
std::cerr
<< "Creates initial state for a TON blockchain, using configuration defined by Fift-language source files\n";
@ -739,6 +821,7 @@ int main(int argc, char* const argv[]) {
fift::init_words_vm(config.dictionary);
fift::init_words_ton(config.dictionary);
init_words_custom(config.dictionary);
init_words_tlb(config.dictionary);
if (script_mode) {
fift::import_cmdline_args(config.dictionary, source_list.empty() ? "" : source_list[0], argc - optind,

View File

@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "block/block.h"
#include "vm/boc.h"
@ -98,7 +98,7 @@ void test1() {
block::tlb::ShardIdent::Record shard_id;
for (int i = 0; i < 3; i++) {
std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate(csl) << std::endl;
std::cout << "ShardIdent.validate() = " << block::tlb::t_ShardIdent.validate_upto(1024, csl) << std::endl;
csl.print_rec(std::cerr);
csl.dump(std::cerr, 7);
std::cout << "ShardIdent.unpack() = " << block::tlb::t_ShardIdent.unpack(csl, shard_id) << std::endl;
@ -107,9 +107,9 @@ void test1() {
<< " shard_prefix:" << shard_id.shard_prefix << std::endl;
}
}
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip(csl) << std::endl;
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
std::cout << "ShardIdent.skip_validate() = " << block::tlb::t_ShardIdent.validate_skip_upto(1024, csl) << std::endl;
using namespace td::literals;
std::cout << "Grams.store_intval(239) = " << block::tlb::t_Grams.store_integer_value(cb, "239"_i256) << std::endl;
std::cout << "Grams.store_intval(17239) = " << block::tlb::t_Grams.store_integer_value(cb, "17239"_i256) << std::endl;
@ -120,13 +120,13 @@ void test1() {
std::cout << "Grams.store_intval(666) = " << block::tlb::t_Grams.store_integer_value(cb, "666"_i256) << std::endl;
std::cout << cb << std::endl;
cs2 = td::Ref<vm::CellSlice>{true, cb.finalize()};
std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate(*cs) << std::endl;
std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate(*cs2) << std::endl;
std::cout << "Grams.validate(cs) = " << block::tlb::t_Grams.validate_upto(1024, *cs) << std::endl;
std::cout << "Grams.validate(cs2) = " << block::tlb::t_Grams.validate_upto(1024, *cs2) << std::endl;
//
block::gen::SplitMergeInfo::Record data;
block::gen::Grams::Record data2;
std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate(*cs) << std::endl;
std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate(*cs2) << std::endl;
std::cout << "block::gen::Grams.validate(cs) = " << block::gen::t_Grams.validate_upto(1024, *cs) << std::endl;
std::cout << "block::gen::Grams.validate(cs2) = " << block::gen::t_Grams.validate_upto(1024, *cs2) << std::endl;
std::cout << "[cs = " << cs << "]" << std::endl;
bool ok = tlb::csr_unpack_inexact(cs, data);
std::cout << "block::gen::SplitMergeInfo.unpack(cs, data) = " << ok << std::endl;
@ -182,29 +182,38 @@ void test1() {
}
void test2(vm::CellSlice& cs) {
std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate(cs) << std::endl;
std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate(cs) << std::endl;
std::cout << "HashmapE(32,UInt16).validate() = " << block::tlb::HashmapE(32, block::tlb::t_uint16).validate(cs)
<< std::endl;
std::cout << "Bool.validate() = " << block::tlb::t_Bool.validate_upto(1024, cs) << std::endl;
std::cout << "UInt16.validate() = " << block::tlb::t_uint16.validate_upto(1024, cs) << std::endl;
std::cout << "HashmapE(32,UInt16).validate() = "
<< block::tlb::HashmapE(32, block::tlb::t_uint16).validate_upto(1024, cs) << std::endl;
std::cout << "block::gen::HashmapE(32,UInt16).validate() = "
<< block::gen::HashmapE{32, block::gen::t_uint16}.validate(cs) << std::endl;
<< block::gen::HashmapE{32, block::gen::t_uint16}.validate_upto(1024, cs) << std::endl;
}
void usage() {
std::cout << "usage: test-block [-S][<boc-file>]\n\tor test-block -h\n\tDumps specified blockchain block or state "
"from <boc-file>, or runs some tests\n\t-S\tDump a blockchain state\n";
std::cout << "usage: dump-block [-t<typename>][-S][<boc-file>]\n\tor dump-block -h\n\tDumps specified blockchain "
"block or state "
"from <boc-file>, or runs some tests\n\t-S\tDump a blockchain state instead of a block\n";
std::exit(2);
}
int main(int argc, char* const argv[]) {
int i;
int new_verbosity_level = VERBOSITY_NAME(INFO);
bool dump_state = false;
const char* tname = nullptr;
const tlb::TLB* type = &block::gen::t_Block;
auto zerostate = std::make_unique<block::ZerostateInfo>();
while ((i = getopt(argc, argv, "Shv:")) != -1) {
while ((i = getopt(argc, argv, "CSt:hv:")) != -1) {
switch (i) {
case 'C':
type = &block::gen::t_VmCont;
break;
case 'S':
dump_state = true;
type = &block::gen::t_ShardStateUnsplit;
break;
case 't':
tname = optarg;
type = nullptr;
break;
case 'v':
new_verbosity_level = VERBOSITY_NAME(FATAL) + (verbosity = td::to_integer<int>(td::Slice(optarg)));
@ -230,12 +239,18 @@ int main(int argc, char* const argv[]) {
vm::CellSlice cs{vm::NoVm(), boc};
cs.print_rec(std::cout);
std::cout << std::endl;
auto& type = dump_state ? (const tlb::TLB&)block::gen::t_ShardStateUnsplit : block::gen::t_Block;
std::string type_name = dump_state ? "ShardState" : "Block";
type.print_ref(std::cout, boc);
if (!type) {
tlb::TypenameLookup dict(block::gen::register_simple_types);
type = dict.lookup(tname);
if (!type) {
std::cerr << "unknown TL-B type " << tname << std::endl;
std::exit(3);
}
}
type->print_ref(std::cout, boc);
std::cout << std::endl;
bool ok = type.validate_ref(boc);
std::cout << "(" << (ok ? "" : "in") << "valid " << type_name << ")" << std::endl;
bool ok = type->validate_ref(1048576, boc);
std::cout << "(" << (ok ? "" : "in") << "valid " << *type << ")" << std::endl;
}
}
if (!done) {

View File

@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "mc-config.h"
#include "block/block.h"
@ -567,6 +567,21 @@ td::Result<GasLimitsPrices> Config::do_get_gas_limits_prices(td::Ref<vm::Cell> c
}
return res;
}
td::Result<ton::StdSmcAddress> Config::get_dns_root_addr() const {
auto cell = get_config_param(4);
if (cell.is_null()) {
return td::Status::Error(PSLICE() << "configuration parameter " << 4 << " with dns root address is absent");
}
auto cs = vm::load_cell_slice(std::move(cell));
if (cs.size() != 0x100) {
return td::Status::Error(PSLICE() << "configuration parameter " << 4 << " with dns root address has wrong size");
}
ton::StdSmcAddress res;
CHECK(cs.fetch_bits_to(res));
return res;
}
td::Result<GasLimitsPrices> Config::get_gas_limits_prices(bool is_masterchain) const {
auto id = is_masterchain ? 20 : 21;
auto cell = get_config_param(id);
@ -752,8 +767,8 @@ Ref<McShardDescr> McShardDescr::from_block(Ref<vm::Cell> block_root, Ref<vm::Cel
return {};
}
// TODO: use a suitable vm::MerkleUpdate method here
vm::CellSlice cs(vm::NoVm(), rec.state_update);
if (cs.special_type() != vm::Cell::SpecialType::MerkleUpdate) {
vm::CellSlice cs(vm::NoVmSpec(), rec.state_update);
if (!cs.is_valid() || cs.special_type() != vm::Cell::SpecialType::MerkleUpdate) {
LOG(ERROR) << "state update in a block is not a Merkle update";
return {};
}
@ -870,7 +885,7 @@ bool ShardConfig::get_shard_hash_raw_from(vm::Dictionary& dict, vm::CellSlice& c
unsigned long long z = id.shard, m = std::numeric_limits<unsigned long long>::max();
int len = id.pfx_len();
while (true) {
cs.load(vm::NoVmOrd{}, leaf ? root : std::move(root));
cs.load(vm::NoVmOrd(), leaf ? root : std::move(root));
int t = (int)cs.fetch_ulong(1);
if (t < 0) {
return false; // throw DictError ?
@ -1108,7 +1123,7 @@ std::vector<ton::BlockId> ShardConfig::get_shard_hash_ids(
std::stack<std::pair<Ref<vm::Cell>, unsigned long long>> stack;
stack.emplace(cs_ref->prefetch_ref(), ton::shardIdAll);
while (!stack.empty()) {
vm::CellSlice cs{vm::NoVm{}, std::move(stack.top().first)};
vm::CellSlice cs{vm::NoVmOrd(), std::move(stack.top().first)};
unsigned long long shard = stack.top().second;
stack.pop();
int t = (int)cs.fetch_ulong(1);
@ -1224,7 +1239,7 @@ bool ShardConfig::new_workchain(ton::WorkchainId workchain, ton::BlockSeqno reg_
cb.store_zeroes_bool(
1 + 5 +
5) // split_merge_at:FutureSplitMerge fees_collected:CurrencyCollection funds_created:CurrencyCollection
&& cb.finalize_to(cell) && block::gen::t_BinTree_ShardDescr.validate_ref(cell) &&
&& cb.finalize_to(cell) && block::gen::t_BinTree_ShardDescr.validate_ref(1024, cell) &&
shard_hashes_dict_->set_ref(td::BitArray<32>{workchain}, std::move(cell), vm::Dictionary::SetMode::Add);
}
@ -1454,7 +1469,7 @@ static bool btree_set(Ref<vm::Cell>& root, ton::ShardId shard, Ref<vm::Cell> val
}
bool ShardConfig::set_shard_info(ton::ShardIdFull shard, Ref<vm::Cell> value) {
if (!gen::t_BinTree_ShardDescr.validate_ref(value)) {
if (!gen::t_BinTree_ShardDescr.validate_ref(1024, value)) {
LOG(ERROR) << "attempting to store an invalid (BinTree ShardDescr) at shard configuration position "
<< shard.to_str();
gen::t_BinTree_ShardDescr.print_ref(std::cerr, value);
@ -1710,6 +1725,30 @@ std::vector<ton::ValidatorDescr> Config::compute_total_validator_set(int next) c
return res.move_as_ok()->export_validator_set();
}
td::Result<std::pair<ton::UnixTime, ton::UnixTime>> Config::unpack_validator_set_start_stop(Ref<vm::Cell> vset_root) {
if (vset_root.is_null()) {
return td::Status::Error("validator set absent");
}
gen::ValidatorSet::Record_validators_ext rec;
if (tlb::unpack_cell(vset_root, rec)) {
return std::pair<ton::UnixTime, ton::UnixTime>(rec.utime_since, rec.utime_until);
}
gen::ValidatorSet::Record_validators rec0;
if (tlb::unpack_cell(std::move(vset_root), rec0)) {
return std::pair<ton::UnixTime, ton::UnixTime>(rec0.utime_since, rec0.utime_until);
}
return td::Status::Error("validator set is invalid");
}
std::pair<ton::UnixTime, ton::UnixTime> Config::get_validator_set_start_stop(int next) const {
auto res = unpack_validator_set_start_stop(get_config_param(next < 0 ? 32 : (next ? 36 : 34)));
if (res.is_error()) {
return {0, 0};
} else {
return res.move_as_ok();
}
}
bool WorkchainInfo::unpack(ton::WorkchainId wc, vm::CellSlice& cs) {
workchain = ton::workchainInvalid;
if (wc == ton::workchainInvalid) {

View File

@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with TON Blockchain. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "common/refcnt.hpp"
@ -50,7 +50,7 @@ struct ValidatorDescr {
: pubkey(_pubkey), weight(_weight), cum_weight(_cum_weight) {
adnl_addr.set_zero();
}
bool operator<(td::uint64 wt_pos) const& {
bool operator<(td::uint64 wt_pos) const & {
return cum_weight < wt_pos;
}
};
@ -534,6 +534,7 @@ class Config {
bool create_stats_enabled() const {
return has_capability(ton::capCreateStatsEnabled);
}
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;
bool is_special_smartcontract(const ton::StdSmcAddress& addr) const;
@ -558,6 +559,7 @@ class Config {
const ValidatorSet* get_cur_validator_set() const {
return cur_validators_.get();
}
std::pair<ton::UnixTime, ton::UnixTime> get_validator_set_start_stop(int next = 0) const;
ton::ValidatorSessionConfig get_consensus_config() const;
bool foreach_config_param(std::function<bool(int, Ref<vm::Cell>)> scan_func) const;
Ref<WorkchainInfo> get_workchain_info(ton::WorkchainId workchain_id) const;
@ -577,6 +579,7 @@ class Config {
static td::Result<std::unique_ptr<Config>> unpack_config(Ref<vm::CellSlice> config_csr, int mode = 0);
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);
protected:
Config(int _mode) : mode(_mode) {

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 "block/transaction.h"
#include "block/block.h"
@ -23,7 +23,7 @@
#include "td/utils/bits.h"
#include "td/utils/uint128.h"
#include "ton/ton-shard.h"
#include "vm/continuation.h"
#include "vm/vm.h"
namespace block {
using td::Ref;
@ -150,7 +150,7 @@ bool Account::unpack_storage_info(vm::CellSlice& cs) {
return false;
}
} else {
due_payment = td::RefInt256{true, 0};
due_payment = td::zero_refint();
}
unsigned long long u = 0;
u |= storage_stat.cells = block::tlb::t_VarUInteger_7.as_uint(*used.cells);
@ -369,7 +369,7 @@ bool Account::init_new(ton::UnixTime now) {
now_ = now;
last_paid = 0;
storage_stat.clear();
due_payment = td::RefInt256{true, 0};
due_payment = td::zero_refint();
balance.set_zero();
if (my_addr_exact.is_null()) {
vm::CellBuilder cb;
@ -463,6 +463,7 @@ Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime re
, my_addr(_account.my_addr)
, my_addr_exact(_account.my_addr_exact)
, balance(_account.balance)
, original_balance(_account.balance)
, due_payment(_account.due_payment)
, last_paid(_account.last_paid)
, new_code(_account.code)
@ -472,6 +473,9 @@ Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime re
start_lt = std::max(req_start_lt, account.last_trans_end_lt_);
end_lt = start_lt + 1;
acc_status = (account.status == Account::acc_nonexist ? Account::acc_uninit : account.status);
if (acc_status == Account::acc_frozen) {
frozen_hash = account.state_hash;
}
}
bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig* cfg) {
@ -503,7 +507,7 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
if (ihr_delivered) {
in_fwd_fee = std::move(ihr_fee);
} else {
in_fwd_fee = td::RefInt256{true, 0};
in_fwd_fee = td::zero_refint();
msg_balance_remaining += std::move(ihr_fee);
}
if (info.created_lt >= start_lt) {
@ -543,7 +547,7 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
LOG(DEBUG) << "computed fwd fees set to zero for special account";
fees_c.first = fees_c.second = 0;
}
in_fwd_fee = td::RefInt256{true, fees_c.first};
in_fwd_fee = td::make_refint(fees_c.first);
if (balance.grams < in_fwd_fee) {
LOG(DEBUG) << "cannot pay for importing this external message";
return false;
@ -615,19 +619,19 @@ bool Transaction::prepare_storage_phase(const StoragePhaseConfig& cfg, bool forc
res->is_special = account.is_special;
last_paid = res->last_paid_updated = (res->is_special ? 0 : now);
if (to_pay.is_null() || sgn(to_pay) == 0) {
res->fees_collected = res->fees_due = td::RefInt256{true, 0};
res->fees_collected = res->fees_due = td::zero_refint();
} else if (to_pay <= balance.grams) {
res->fees_collected = to_pay;
res->fees_due = td::RefInt256{true, 0};
res->fees_due = td::zero_refint();
balance -= std::move(to_pay);
} else if (acc_status == Account::acc_frozen && !force_collect && to_pay + due_payment < cfg.delete_due_limit) {
// do not collect fee
res->last_paid_updated = (res->is_special ? 0 : account.last_paid);
res->fees_collected = res->fees_due = td::RefInt256{true, 0};
res->fees_collected = res->fees_due = td::zero_refint();
} else {
res->fees_collected = balance.grams;
res->fees_due = std::move(to_pay) - std::move(balance.grams);
balance.grams = td::RefInt256{true, 0};
balance.grams = td::zero_refint();
if (!res->is_special) {
auto total_due = res->fees_due + due_payment;
switch (acc_status) {
@ -691,19 +695,23 @@ bool ComputePhaseConfig::parse_GasLimitsPrices(Ref<vm::CellSlice> cs, td::RefInt
}
block::gen::GasLimitsPrices::Record_gas_flat_pfx flat;
if (tlb::csr_unpack(cs, flat)) {
bool ok = parse_GasLimitsPrices(std::move(flat.other), freeze_due_limit, delete_due_limit);
flat_gas_limit = flat.flat_gas_limit;
flat_gas_price = flat.flat_gas_price;
return ok;
return parse_GasLimitsPrices_internal(std::move(flat.other), freeze_due_limit, delete_due_limit,
flat.flat_gas_limit, flat.flat_gas_price);
} else {
return parse_GasLimitsPrices_internal(std::move(cs), freeze_due_limit, delete_due_limit);
}
flat_gas_limit = flat_gas_price = 0;
}
bool ComputePhaseConfig::parse_GasLimitsPrices_internal(Ref<vm::CellSlice> cs, td::RefInt256& freeze_due_limit,
td::RefInt256& delete_due_limit, td::uint64 _flat_gas_limit,
td::uint64 _flat_gas_price) {
auto f = [&](const auto& r, td::uint64 spec_limit) {
gas_limit = r.gas_limit;
special_gas_limit = spec_limit;
gas_credit = r.gas_credit;
gas_price = r.gas_price;
freeze_due_limit = td::RefInt256{true, r.freeze_due_limit};
delete_due_limit = td::RefInt256{true, r.delete_due_limit};
freeze_due_limit = td::make_refint(r.freeze_due_limit);
delete_due_limit = td::make_refint(r.delete_due_limit);
};
block::gen::GasLimitsPrices::Record_gas_prices_ext rec;
if (tlb::csr_unpack(cs, rec)) {
@ -716,15 +724,17 @@ bool ComputePhaseConfig::parse_GasLimitsPrices(Ref<vm::CellSlice> cs, td::RefInt
return false;
}
}
flat_gas_limit = _flat_gas_limit;
flat_gas_price = _flat_gas_price;
compute_threshold();
return true;
}
void ComputePhaseConfig::compute_threshold() {
gas_price256 = td::RefInt256{true, gas_price};
gas_price256 = td::make_refint(gas_price);
if (gas_limit > flat_gas_limit) {
max_gas_threshold =
td::rshift(gas_price256 * (gas_limit - flat_gas_limit), 16, 1) + td::make_refint(flat_gas_price);
td::rshift(gas_price256 * (gas_limit - flat_gas_limit), 16, 1) + td::make_bigint(flat_gas_price);
} else {
max_gas_threshold = td::make_refint(flat_gas_price);
}
@ -821,8 +831,8 @@ Ref<vm::Tuple> Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
}
auto tuple = vm::make_tuple_ref(
td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
td::make_refint(0), // actions:Integer
td::make_refint(0), // msgs_sent:Integer
td::zero_refint(), // actions:Integer
td::zero_refint(), // msgs_sent:Integer
td::make_refint(now), // unixtime:Integer
td::make_refint(account.block_lt), // block_lt:Integer
td::make_refint(start_lt), // trans_lt:Integer
@ -906,6 +916,7 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
// ...
compute_phase = std::make_unique<ComputePhase>();
ComputePhase& cp = *(compute_phase.get());
original_balance -= total_fees;
if (td::sgn(balance.grams) <= 0) {
// no gas
cp.skip_reason = ComputePhase::sk_no_gas;
@ -1004,16 +1015,15 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
}
if (cp.accepted) {
if (account.is_special) {
cp.gas_fees = td::RefInt256{true, 0};
cp.gas_fees = td::zero_refint();
} else {
cp.gas_fees = cfg.compute_gas_price(cp.gas_used);
total_fees += cp.gas_fees;
balance -= cp.gas_fees;
}
if (verbosity > 2) {
std::cerr << "gas fees: " << cp.gas_fees << " = " << cfg.gas_price256 << " * " << cp.gas_used
<< " /2^16 ; price=" << cfg.gas_price << "; remaining balance=" << balance << std::endl;
}
LOG(DEBUG) << "gas fees: " << cp.gas_fees->to_dec_string() << " = " << cfg.gas_price256->to_dec_string() << " * "
<< cp.gas_used << " /2^16 ; price=" << cfg.gas_price << "; flat rate=[" << cfg.flat_gas_price << " for "
<< cfg.flat_gas_limit << "]; remaining balance=" << balance.to_str();
CHECK(td::sgn(balance.grams) >= 0);
}
return true;
@ -1033,8 +1043,8 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
ap.action_list_hash = list->get_hash().bits();
ap.remaining_balance = balance;
ap.end_lt = end_lt;
ap.total_fwd_fees = td::RefInt256{true, 0};
ap.total_action_fees = td::RefInt256{true, 0};
ap.total_fwd_fees = td::zero_refint();
ap.total_action_fees = td::zero_refint();
ap.reserved_balance.set_zero();
int n = 0;
@ -1098,6 +1108,9 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
case block::gen::OutAction::action_reserve_currency:
err_code = try_action_reserve_currency(cs, ap, cfg);
break;
case block::gen::OutAction::action_change_library:
err_code = try_action_change_library(cs, ap, cfg);
break;
}
if (err_code) {
ap.result_code = (err_code == -1 ? 34 : err_code);
@ -1148,6 +1161,56 @@ int Transaction::try_action_set_code(vm::CellSlice& cs, ActionPhase& ap, const A
return 0;
}
int Transaction::try_action_change_library(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) {
block::gen::OutAction::Record_action_change_library rec;
if (!tlb::unpack_exact(cs, rec)) {
return -1;
}
// mode: +0 = remove library, +1 = add private library, +2 = add public library
Ref<vm::Cell> lib_ref = rec.libref->prefetch_ref();
ton::Bits256 hash;
if (lib_ref.not_null()) {
hash = lib_ref->get_hash().bits();
} else {
CHECK(rec.libref.write().fetch_ulong(1) == 0 && rec.libref.write().fetch_bits_to(hash));
}
try {
vm::Dictionary dict{new_library, 256};
if (!rec.mode) {
// remove library
dict.lookup_delete(hash);
LOG(DEBUG) << "removed " << ((rec.mode >> 1) ? "public" : "private") << " library with hash " << hash.to_hex();
} else {
auto val = dict.lookup(hash);
if (val.not_null()) {
bool is_public = val->prefetch_ulong(1);
auto ref = val->prefetch_ref();
if (hash == ref->get_hash().bits()) {
lib_ref = ref;
if (is_public == (rec.mode >> 1)) {
// library already in required state
ap.spec_actions++;
return 0;
}
}
}
if (lib_ref.is_null()) {
// library code not found
return 41;
}
vm::CellBuilder cb;
CHECK(cb.store_bool_bool(rec.mode >> 1) && cb.store_ref_bool(std::move(lib_ref)));
CHECK(dict.set_builder(hash, cb));
LOG(DEBUG) << "added " << ((rec.mode >> 1) ? "public" : "private") << " library with hash " << hash.to_hex();
}
new_library = std::move(dict).extract_root_cell();
} catch (vm::VmError& vme) {
return 42;
}
ap.spec_actions++;
return 0;
}
// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms
// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms
// bits in the root cell of a message are not included in msg.bits (lump_price pays for them)
@ -1369,7 +1432,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
info.ihr_disabled = true;
info.bounce = false;
info.bounced = false;
fwd_fee = ihr_fee = td::RefInt256{true, 0};
fwd_fee = ihr_fee = td::zero_refint();
} else {
// int_msg_info$0 constructor
if (!tlb::csr_unpack(msg.info, info) || !block::tlb::t_CurrencyCollection.validate_csr(info.value)) {
@ -1422,10 +1485,10 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
// set fees to computed values
if (fwd_fee->unsigned_fits_bits(63) && fwd_fee->to_long() < (long long)fees_c.first) {
fwd_fee = td::RefInt256{true, fees_c.first};
fwd_fee = td::make_refint(fees_c.first);
}
if (fees_c.second && ihr_fee->unsigned_fits_bits(63) && ihr_fee->to_long() < (long long)fees_c.second) {
ihr_fee = td::RefInt256{true, fees_c.second};
ihr_fee = td::make_refint(fees_c.second);
}
Ref<vm::Cell> new_msg;
@ -1442,7 +1505,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
}
if (info.ihr_disabled) {
// if IHR is disabled, IHR fees will be always zero
ihr_fee = td::RefInt256{true, 0};
ihr_fee = td::zero_refint();
}
// extract value to be carried by the message
block::CurrencyCollection req;
@ -1592,7 +1655,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) {
block::gen::OutAction::Record_action_reserve_currency rec;
if (!tlb::unpack_exact(cs, rec) || (rec.mode & ~3)) {
if (!tlb::unpack_exact(cs, rec) || (rec.mode & ~15)) {
return -1;
}
int mode = rec.mode;
@ -1603,7 +1666,21 @@ int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap,
return -1;
}
LOG(DEBUG) << "action_reserve_currency: mode=" << mode << ", reserve=" << reserve.to_str()
<< ", balance=" << ap.remaining_balance.to_str();
<< ", balance=" << ap.remaining_balance.to_str() << ", original balance=" << original_balance.to_str();
if (mode & 4) {
if (mode & 8) {
reserve = original_balance - reserve;
} else {
reserve += original_balance;
}
} else if (mode & 8) {
LOG(DEBUG) << "invalid reserve mode " << mode;
return -1;
}
if (!reserve.is_valid() || td::sgn(reserve.grams) < 0) {
LOG(DEBUG) << "cannot reserve a negative amount: " << reserve.to_str();
return -1;
}
if (reserve.grams > ap.remaining_balance.grams) {
if (mode & 2) {
reserve.grams = ap.remaining_balance.grams;
@ -1683,10 +1760,10 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
balance -= msg_balance;
CHECK(balance.is_valid());
// debit total forwarding fees from the message's balance, then split forwarding fees into our part and remaining part
msg_balance -= td::RefInt256{true, bp.fwd_fees};
msg_balance -= td::make_refint(bp.fwd_fees);
bp.fwd_fees_collected = msg_prices.get_first_part(bp.fwd_fees);
bp.fwd_fees -= bp.fwd_fees_collected;
total_fees += td::RefInt256{true, bp.fwd_fees_collected};
total_fees += td::make_refint(bp.fwd_fees_collected);
// serialize outbound message
info.created_lt = end_lt++;
info.created_at = now;
@ -1771,7 +1848,7 @@ bool Transaction::compute_state() {
// code:(Maybe ^Cell) data:(Maybe ^Cell) library:(HashmapE 256 SimpleLib)
auto frozen_state = cb2.finalize();
frozen_hash = frozen_state->get_hash().bits();
if (verbosity >= 3 * 0) { // !!!DEBUG!!!
if (verbosity >= 3 * 1) { // !!!DEBUG!!!
std::cerr << "freezing state of smart contract: ";
block::gen::t_StateInit.print_ref(std::cerr, frozen_state);
CHECK(block::gen::t_StateInit.validate_ref(frozen_state));

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
#include "common/refcnt.hpp"
@ -65,10 +65,10 @@ struct NewOutMsg {
NewOutMsg(ton::LogicalTime _lt, Ref<vm::Cell> _msg, Ref<vm::Cell> _trans)
: lt(_lt), msg(std::move(_msg)), trans(std::move(_trans)) {
}
bool operator<(const NewOutMsg& other) const& {
bool operator<(const NewOutMsg& other) const & {
return lt < other.lt || (lt == other.lt && msg->get_hash() < other.msg->get_hash());
}
bool operator>(const NewOutMsg& other) const& {
bool operator>(const NewOutMsg& other) const & {
return lt > other.lt || (lt == other.lt && other.msg->get_hash() < msg->get_hash());
}
};
@ -130,6 +130,11 @@ struct ComputePhaseConfig {
}
bool parse_GasLimitsPrices(Ref<vm::CellSlice> cs, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit);
bool parse_GasLimitsPrices(Ref<vm::Cell> cell, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit);
private:
bool parse_GasLimitsPrices_internal(Ref<vm::CellSlice> cs, td::RefInt256& freeze_due_limit,
td::RefInt256& delete_due_limit, td::uint64 flat_gas_limit = 0,
td::uint64 flat_gas_price = 0);
};
struct ActionPhaseConfig {
@ -189,10 +194,6 @@ struct ActionPhase {
Ref<vm::Cell> new_code;
td::BitArray<256> action_list_hash;
block::CurrencyCollection remaining_balance, reserved_balance;
// td::RefInt256 remaining_balance;
// Ref<vm::Cell> remaining_extra;
// td::RefInt256 reserved_balance;
// Ref<vm::Cell> reserved_extra;
std::vector<Ref<vm::Cell>> action_list; // processed in reverse order
std::vector<Ref<vm::Cell>> out_msgs;
ton::LogicalTime end_lt;
@ -314,7 +315,7 @@ struct Transaction {
const Account& account; // only `commit` method modifies the account
Ref<vm::CellSlice> my_addr, my_addr_exact; // almost the same as in account.*
ton::LogicalTime start_lt, end_lt;
block::CurrencyCollection balance;
block::CurrencyCollection balance, original_balance;
block::CurrencyCollection msg_balance_remaining;
td::RefInt256 due_payment;
td::RefInt256 in_fwd_fee, msg_fwd_fees;
@ -371,6 +372,7 @@ struct Transaction {
Ref<vm::Tuple> prepare_vm_c7(const ComputePhaseConfig& cfg) const;
bool prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputePhaseConfig& cfg) const;
int try_action_set_code(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg);
int try_action_change_library(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg);
int try_action_send_msg(const vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg, int redoing = 0);
int try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg);
bool check_replace_src_addr(Ref<vm::CellSlice>& src_addr) const;

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
#include <vector>
@ -169,6 +169,8 @@ class PropagateConstSpan {
size_t size_{0};
};
struct Normalize {};
template <class Tr = BigIntInfo>
class AnyIntView {
public:
@ -308,6 +310,10 @@ class BigIntG {
explicit BigIntG(word_t x) : n(1) {
digits[0] = x;
}
BigIntG(Normalize, word_t x) : n(1) {
digits[0] = x;
normalize_bool();
}
BigIntG(const BigIntG& x) : n(x.n) {
std::memcpy(digits, x.digits, n * sizeof(word_t));
///std::cout << "(BiCC " << (const void*)&x << "->" << (void*)this << ")";
@ -2515,6 +2521,11 @@ extern template class AnyIntView<BigIntInfo>;
extern template class BigIntG<257, BigIntInfo>;
typedef BigIntG<257, BigIntInfo> BigInt256;
template <int n = 257>
BigIntG<n, BigIntInfo> make_bigint(long long x) {
return BigIntG<n, BigIntInfo>{Normalize(), x};
}
namespace literals {
extern BigInt256 operator""_i256(const char* str, std::size_t str_len);

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 "common/refint.h"
#include <utility>
@ -38,6 +38,11 @@ RefInt256 operator+(RefInt256 x, long long y) {
return x;
}
RefInt256 operator+(RefInt256 x, const BigInt256& y) {
(x.write() += y).normalize();
return x;
}
RefInt256 operator-(RefInt256 x, RefInt256 y) {
(x.write() -= *y).normalize();
return x;
@ -48,6 +53,11 @@ RefInt256 operator-(RefInt256 x, long long y) {
return x;
}
RefInt256 operator-(RefInt256 x, const BigInt256& y) {
(x.write() -= y).normalize();
return x;
}
RefInt256 operator-(RefInt256 x) {
x.write().negate().normalize();
return x;
@ -69,6 +79,12 @@ RefInt256 operator*(RefInt256 x, long long y) {
return x;
}
RefInt256 operator*(RefInt256 x, const BigInt256& y) {
RefInt256 z{true, 0};
z.write().add_mul(*x, y).normalize();
return z;
}
RefInt256 operator/(RefInt256 x, RefInt256 y) {
RefInt256 quot{true};
x.write().mod_div(*y, quot.write());
@ -142,6 +158,11 @@ RefInt256& operator+=(RefInt256& x, long long y) {
return x;
}
RefInt256& operator+=(RefInt256& x, const BigInt256& y) {
(x.write() += y).normalize();
return x;
}
RefInt256& operator-=(RefInt256& x, RefInt256 y) {
(x.write() -= *y).normalize();
return x;
@ -152,6 +173,11 @@ RefInt256& operator-=(RefInt256& x, long long y) {
return x;
}
RefInt256& operator-=(RefInt256& x, const BigInt256& y) {
(x.write() -= y).normalize();
return x;
}
RefInt256& operator*=(RefInt256& x, RefInt256 y) {
RefInt256 z{true, 0};
z.write().add_mul(*x, *y).normalize();
@ -163,6 +189,12 @@ RefInt256& operator*=(RefInt256& x, long long y) {
return x;
}
RefInt256& operator*=(RefInt256& x, const BigInt256& y) {
RefInt256 z{true, 0};
z.write().add_mul(*x, y).normalize();
return x = z;
}
RefInt256& operator/=(RefInt256& x, RefInt256 y) {
RefInt256 quot{true};
x.write().mod_div(*y, quot.write());
@ -213,10 +245,20 @@ int sgn(RefInt256 x) {
return x->sgn();
}
extern RefInt256 make_refint(long long x) {
auto xx = td::RefInt256{true, x};
xx.unique_write().normalize();
return xx;
RefInt256 make_refint(long long x) {
return td::RefInt256{true, td::Normalize(), x};
}
RefInt256 zero_refint() {
// static RefInt256 Zero = td::RefInt256{true, 0};
// return Zero;
return td::RefInt256{true, 0};
}
RefInt256 bits_to_refint(td::ConstBitPtr bits, int n, bool sgnd) {
td::RefInt256 x{true};
x.unique_write().import_bits(bits, n, sgnd);
return x;
}
std::string dec_string(RefInt256 x) {

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
@ -33,10 +33,13 @@ typedef Ref<CntInt256> RefInt256;
extern RefInt256 operator+(RefInt256 x, RefInt256 y);
extern RefInt256 operator+(RefInt256 x, long long y);
extern RefInt256 operator+(RefInt256 x, const BigInt256& y);
extern RefInt256 operator-(RefInt256 x, RefInt256 y);
extern RefInt256 operator-(RefInt256 x, long long y);
extern RefInt256 operator-(RefInt256 x, const BigInt256& y);
extern RefInt256 operator*(RefInt256 x, RefInt256 y);
extern RefInt256 operator*(RefInt256 x, long long y);
extern RefInt256 operator*(RefInt256 x, const BigInt256& y);
extern RefInt256 operator/(RefInt256 x, RefInt256 y);
extern RefInt256 operator%(RefInt256 x, RefInt256 y);
extern RefInt256 div(RefInt256 x, RefInt256 y, int round_mode = -1);
@ -53,10 +56,13 @@ extern RefInt256 rshift(RefInt256 x, int y, int round_mode = -1);
extern RefInt256& operator+=(RefInt256& x, RefInt256 y);
extern RefInt256& operator+=(RefInt256& x, long long y);
extern RefInt256& operator+=(RefInt256& x, const BigInt256& y);
extern RefInt256& operator-=(RefInt256& x, RefInt256 y);
extern RefInt256& operator-=(RefInt256& x, long long y);
extern RefInt256& operator-=(RefInt256& x, const BigInt256& y);
extern RefInt256& operator*=(RefInt256& x, RefInt256 y);
extern RefInt256& operator*=(RefInt256& x, long long y);
extern RefInt256& operator*=(RefInt256& x, const BigInt256& y);
extern RefInt256& operator/=(RefInt256& x, RefInt256 y);
extern RefInt256& operator%=(RefInt256& x, RefInt256 y);
@ -100,8 +106,16 @@ extern int cmp(RefInt256 x, RefInt256 y);
extern int cmp(RefInt256 x, long long y);
extern int sgn(RefInt256 x);
template <typename... Args>
RefInt256 make_refint(Args&&... args) {
return td::RefInt256{true, std::forward<Args>(args)...};
}
extern RefInt256 make_refint(long long x);
extern RefInt256 zero_refint();
extern RefInt256 bits_to_refint(td::ConstBitPtr bits, int n, bool sgnd = false);
extern std::string dec_string(RefInt256 x);
extern std::string dec_string2(RefInt256&& x);
extern std::string hex_string(RefInt256 x, bool upcase = false);

View File

@ -14,12 +14,15 @@
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 "util.h"
#include <limits>
#include "td/utils/crypto.h"
#include "td/utils/base64.h"
namespace td {
std::size_t compute_base64_encoded_size(size_t bindata_size) {
@ -73,10 +76,6 @@ std::size_t buff_base64_encode(td::MutableSlice buffer, td::Slice raw, bool base
return res_size;
}
std::string str_base64_encode(std::string raw, bool base64_url) {
return str_base64_encode(td::Slice{raw}, base64_url);
}
std::string str_base64_encode(td::Slice raw, bool base64_url) {
std::size_t res_size = compute_base64_encoded_size(raw.size());
std::string s;
@ -87,10 +86,6 @@ std::string str_base64_encode(td::Slice raw, bool base64_url) {
return s;
}
bool is_valid_base64(std::string encoded, bool allow_base64_url) {
return is_valid_base64(td::Slice{encoded}, allow_base64_url);
}
bool is_valid_base64(td::Slice encoded, bool allow_base64_url) {
const unsigned char *ptr = (const unsigned char *)encoded.data(), *end = ptr + encoded.size();
if (encoded.size() & 3) {
@ -110,10 +105,6 @@ bool is_valid_base64(td::Slice encoded, bool allow_base64_url) {
return ptr == end;
}
td::int32 decoded_base64_size(std::string encoded, bool allow_base64_url) {
return decoded_base64_size(td::Slice{encoded}, allow_base64_url);
}
td::int32 decoded_base64_size(td::Slice encoded, bool allow_base64_url) {
const unsigned char *ptr = (const unsigned char *)encoded.data(), *end = ptr + encoded.size();
if (encoded.size() & 3) {
@ -172,10 +163,6 @@ std::size_t buff_base64_decode(td::MutableSlice buffer, td::Slice encoded, bool
return wptr - (unsigned char *)buffer.data();
}
td::BufferSlice base64_decode(std::string encoded, bool allow_base64_url) {
return base64_decode(td::Slice{encoded}, allow_base64_url);
}
td::BufferSlice base64_decode(td::Slice encoded, bool allow_base64_url) {
auto s = decoded_base64_size(encoded, allow_base64_url);
if (s <= 0) {
@ -190,10 +177,6 @@ td::BufferSlice base64_decode(td::Slice encoded, bool allow_base64_url) {
return res;
}
std::string str_base64_decode(std::string encoded, bool allow_base64_url) {
return str_base64_decode(td::Slice{encoded}, allow_base64_url);
}
std::string str_base64_decode(td::Slice encoded, bool allow_base64_url) {
auto s = decoded_base64_size(encoded, allow_base64_url);
if (s <= 0) {
@ -209,4 +192,45 @@ std::string str_base64_decode(td::Slice encoded, bool allow_base64_url) {
return res;
}
td::Result<std::string> adnl_id_encode(td::Slice id, bool upper_case) {
if (id.size() != 32) {
return td::Status::Error("Wrong andl id size");
}
td::uint8 buf[35];
td::MutableSlice buf_slice(buf, 35);
buf_slice[0] = 0x2d;
buf_slice.substr(1).copy_from(id);
auto hash = td::crc16(buf_slice.substr(0, 33));
buf[33] = static_cast<td::uint8>((hash >> 8) & 255);
buf[34] = static_cast<td::uint8>(hash & 255);
return td::base32_encode(buf_slice, upper_case).substr(1);
}
std::string adnl_id_encode(td::Bits256 adnl_addr, bool upper_case) {
return adnl_id_encode(adnl_addr.as_slice(), upper_case).move_as_ok();
}
td::Result<Bits256> adnl_id_decode(td::Slice id) {
if (id.size() != 55) {
return td::Status::Error("Wrong length of adnl id");
}
td::uint8 buf[56];
buf[0] = 'f';
td::MutableSlice buf_slice(buf, 56);
buf_slice.substr(1).copy_from(id);
TRY_RESULT(decoded_str, td::base32_decode(buf_slice));
auto decoded = td::Slice(decoded_str);
if (decoded[0] != 0x2d) {
return td::Status::Error("Invalid first byte");
}
auto got_hash = (decoded.ubegin()[33] << 8) | decoded.ubegin()[34];
auto hash = td::crc16(decoded.substr(0, 33));
if (hash != got_hash) {
return td::Status::Error("Hash mismatch");
}
Bits256 res;
res.as_slice().copy_from(decoded.substr(1, 32));
return res;
}
} // namespace td

View File

@ -14,29 +14,31 @@
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 "td/utils/Slice.h"
#include "td/utils/buffer.h"
#include "bitstring.h"
namespace td {
std::size_t compute_base64_encoded_size(size_t bindata_size);
std::size_t buff_base64_encode(td::MutableSlice buffer, td::Slice raw, bool base64_url = false);
std::string str_base64_encode(std::string raw, bool base64_url = false);
std::string str_base64_encode(td::Slice raw, bool base64_url = false);
bool is_valid_base64(std::string encoded, bool allow_base64_url = true);
bool is_valid_base64(td::Slice encoded, bool allow_base64_url = true);
td::int32 decoded_base64_size(std::string encoded, bool allow_base64_url = true);
td::int32 decoded_base64_size(td::Slice encoded, bool allow_base64_url = true);
std::size_t buff_base64_decode(td::MutableSlice buffer, td::Slice data, bool allow_base64_url = true);
td::BufferSlice base64_decode(std::string encoded, bool allow_base64_url = true);
td::BufferSlice base64_decode(td::Slice encoded, bool allow_base64_url = true);
std::string str_base64_decode(std::string encoded, bool allow_base64_url = true);
std::string str_base64_decode(td::Slice encoded, bool allow_base64_url = true);
//TODO: move it somewhere else
td::Result<std::string> adnl_id_encode(td::Slice id, bool upper_case = false);
std::string adnl_id_encode(Bits256 adnl_addr, bool upper_case = false);
td::Result<Bits256> adnl_id_decode(td::Slice id);
} // namespace td

View File

@ -71,6 +71,7 @@ IntCtx::Savepoint::Savepoint(IntCtx& _ctx, std::string new_filename, std::string
std::istream* new_input_stream)
: ctx(_ctx)
, old_line_no(_ctx.line_no)
, old_need_line(_ctx.need_line)
, old_filename(_ctx.filename)
, old_current_dir(_ctx.currentd_dir)
, old_input_stream(_ctx.input_stream)
@ -87,6 +88,7 @@ IntCtx::Savepoint::Savepoint(IntCtx& _ctx, std::string new_filename, std::string
IntCtx::Savepoint::~Savepoint() {
ctx.line_no = old_line_no;
ctx.need_line = old_need_line;
ctx.filename = old_filename;
ctx.currentd_dir = old_current_dir;
ctx.input_stream = old_input_stream;
@ -99,6 +101,7 @@ bool IntCtx::load_next_line() {
if (!std::getline(*input_stream, str)) {
return false;
}
need_line = false;
if (!str.empty() && str.back() == '\r') {
str.pop_back();
}
@ -111,6 +114,7 @@ bool IntCtx::is_sb() const {
}
td::Slice IntCtx::scan_word_to(char delim, bool err_endl) {
load_next_line_ifreq();
auto ptr = input_ptr;
while (*ptr && *ptr != delim) {
ptr++;
@ -121,6 +125,7 @@ td::Slice IntCtx::scan_word_to(char delim, bool err_endl) {
} else if (err_endl && delim) {
throw IntError{std::string{"end delimiter `"} + delim + "` not found"};
} else {
need_line = true;
std::swap(ptr, input_ptr);
return td::Slice{ptr, input_ptr};
}

View File

@ -68,6 +68,7 @@ struct IntCtx {
int state{0};
int include_depth{0};
int line_no{0};
bool need_line{true};
std::string filename;
std::string currentd_dir;
std::istream* input_stream{nullptr};
@ -116,6 +117,9 @@ struct IntCtx {
}
bool load_next_line();
bool load_next_line_ifreq() {
return need_line && load_next_line();
}
bool is_sb() const;
@ -126,6 +130,7 @@ struct IntCtx {
class Savepoint {
IntCtx& ctx;
int old_line_no;
bool old_need_line;
std::string old_filename;
std::string old_current_dir;
std::istream* old_input_stream;

View File

@ -23,7 +23,7 @@
exception statement from your version. If you delete this exception statement
from all source files in the program, then also delete it here.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "vm/stack.hpp"
#include <cassert>
@ -156,7 +156,7 @@ int main(int argc, char* const argv[]) {
}
fift::init_words_common(config.dictionary);
fift::init_words_vm(config.dictionary);
fift::init_words_vm(config.dictionary, true); // enable vm debug
fift::init_words_ton(config.dictionary);
if (script_mode) {

View File

@ -165,6 +165,8 @@ x{68} @Defop DEPTH
x{69} @Defop CHKDEPTH
x{6A} @Defop ONLYTOPX
x{6B} @Defop ONLYX
{ over 0= abort"first argument must be non-zero"
<b x{6C} s, rot 4 u, swap 4 u, @addopb } : BLKDROP2
// null primitives
x{6D} dup @Defop NULL @Defop PUSHNULL
@ -216,6 +218,10 @@ x{6FA0} @Defop NULLSWAPIF
x{6FA1} @Defop NULLSWAPIFNOT
x{6FA2} @Defop NULLROTRIF
x{6FA3} @Defop NULLROTRIFNOT
x{6FA4} @Defop NULLSWAPIF2
x{6FA5} @Defop NULLSWAPIFNOT2
x{6FA6} @Defop NULLROTRIF2
x{6FA7} @Defop NULLROTRIFNOT2
{ <b x{6FB} s, rot 2 u, swap 2 u, @addopb } : INDEX2
x{6FB4} @Defop CADR
x{6FB5} @Defop CDDR
@ -305,19 +311,21 @@ x{A90C} @Defop DIVMOD
x{A90D} @Defop DIVMODR
x{A90E} @Defop DIVMODC
x{A925} @Defop RSHIFTR
x{A926} @Defop RSHIFTC
x{A935} @Defop(8u+1) RSHIFTR#
x{A936} @Defop(8u+1) RSHIFTC#
x{A938} @Defop(8u+1) MODPOW2#
x{A984} @Defop MULDIV
x{A985} @Defop MULDIVR
x{A98C} @Defop MULDIVMOD
x{A9A4} @Defop MULRSHIFT
x{A9A5} @Defop MULRSHIFTR
x{A9B4} @Defop(8u+1) MULRSHIFT#
x{A9B5} @Defop(8u+1) MULRSHIFTR#
x{A9C4} @Defop LSHIFTDIV
x{A9C5} @Defop LSHIFTDIVR
x{A9D4} @Defop(8u+1) LSHIFT#DIV
x{A9D5} @Defop(8u+1) LSHIFT#DIVR
x{A9E4} @Defop MULRSHIFT
x{A9E5} @Defop MULRSHIFTR
x{A9F4} @Defop(8u+1) MULRSHIFT#
x{A9F5} @Defop(8u+1) MULRSHIFTR#
x{AA} @Defop(8u+1) LSHIFT#
x{AB} @Defop(8u+1) RSHIFT#
x{AC} @Defop LSHIFT
@ -458,6 +466,7 @@ x{CF28} @Defop STILE4
x{CF29} @Defop STULE4
x{CF2A} @Defop STILE8
x{CF2B} @Defop STULE8
x{CF30} @Defop BDEPTH
x{CF31} @Defop BBITS
x{CF32} @Defop BREFS
x{CF33} @Defop BBITREFS
@ -485,6 +494,7 @@ x{CF42} @Defop STSAME
} : STSLICECONST
x{CF81} @Defop STZERO
x{CF83} @Defop STONE
// cell deserialization (CellSlice primitives)
x{D0} @Defop CTOS
x{D1} @Defop ENDS
@ -585,6 +595,8 @@ x{D75F} @Defop PLDULE8Q
x{D760} @Defop LDZEROES
x{D761} @Defop LDONES
x{D762} @Defop LDSAME
x{D764} @Defop SDEPTH
x{D765} @Defop CDEPTH
//
// continuation / flow control primitives
x{D8} dup @Defop EXECUTE @Defop CALLX
@ -965,6 +977,11 @@ x{F4B5} @Defop SUBDICTRPGET
x{F4B6} @Defop SUBDICTIRPGET
x{F4B7} @Defop SUBDICTURPGET
x{F4BC} @Defop DICTIGETJMPZ
x{F4BD} @Defop DICTUGETJMPZ
x{F4BE} @Defop DICTIGETEXECZ
x{F4BF} @Defop DICTUGETEXECZ
//
// blockchain-specific primitives
@ -972,12 +989,17 @@ x{F800} @Defop ACCEPT
x{F801} @Defop SETGASLIMIT
x{F80F} @Defop COMMIT
x{F810} @Defop RANDU256
x{F811} @Defop RAND
x{F814} @Defop SETRAND
x{F815} dup @Defop ADDRAND @Defop RANDOMIZE
x{F82} @Defop(4u) GETPARAM
x{F823} @Defop NOW
x{F824} @Defop BLOCKLT
x{F825} @Defop LTIME
x{F826} @Defop BALANCE
x{F827} @Defop RANDSEED
x{F826} @Defop RANDSEED
x{F827} @Defop BALANCE
x{F828} @Defop MYADDR
x{F829} @Defop CONFIGROOT
x{F830} @Defop CONFIGDICT
@ -995,6 +1017,11 @@ x{F902} @Defop SHA256U
x{F910} @Defop CHKSIGNU
x{F911} @Defop CHKSIGNS
x{F940} @Defop CDATASIZEQ
x{F941} @Defop CDATASIZE
x{F942} @Defop SDATASIZEQ
x{F943} @Defop SDATASIZE
x{FA00} dup @Defop LDGRAMS @Defop LDVARUINT16
x{FA01} @Defop LDVARINT16
x{FA02} dup @Defop STGRAMS @Defop STVARUINT16
@ -1013,6 +1040,8 @@ x{FB00} @Defop SENDRAWMSG
x{FB02} @Defop RAWRESERVE
x{FB03} @Defop RAWRESERVEX
x{FB04} @Defop SETCODE
x{FB06} @Defop SETLIBCODE
x{FB07} @Defop CHANGELIB
//
// debug primitives
@ -1057,56 +1086,98 @@ x{FFF0} @Defop SETCPX
variable @proccnt
variable @proclist
variable @procdict
variable @procinfo
variable @gvarcnt
variable asm-mode 1 asm-mode !
19 constant @procdictkeylen
{ @proclist @ cons @proclist ! } : @proclistadd
{ dup @procdictkeylen fits not abort"procedure index out of range"
1 'nop does swap dup @proclistadd 0 (create)
32 constant @zcount
{ pair @proclist @ cons @proclist ! } : @proclistadd
{ @procinfo @ @procdictkeylen idict@ { 16 i@ } { 0 } cond } : @procinfo@
{ <b rot 16 i, swap @procinfo @ @procdictkeylen b>idict!
not abort"cannot add key to procedure info dictionary"
@procinfo !
} : @procinfo!
// ( x v1 v2 -- )
{ not 2 pick @procinfo@ and xor swap @procinfo! } : @procinfo~!
// ( s i f -- )
{ over @procdictkeylen fits not abort"procedure index out of range"
over swap dup @procinfo~! 2dup @proclistadd
1 'nop does swap 0 (create)
} : @declproc
{ @proccnt @ 1+ dup @proccnt ! @declproc } : @newproc
{ 0 =: main @proclist null! @proccnt 0!
{ 1 'nop does swap 0 (create) } : @declglobvar
{ @proccnt @ 1+ dup @proccnt ! 1 @declproc } : @newproc
{ @gvarcnt @ 1+ dup @gvarcnt ! @declglobvar } : @newglobvar
{ 0 =: main @proclist null! @proccnt 0! @gvarcnt 0!
{ bl word @newproc } : NEWPROC
{ bl word dup (def?) ' drop ' @newproc cond } : DECLPROC
{ bl word dup find
{ nip execute <> abort"method redefined with different id" }
{ swap @declproc }
{ swap 17 @declproc }
cond } : DECLMETHOD
"main" @proclistadd
dictnew @procdict !
{ bl word @newglobvar } : DECLGLOBVAR
"main" 0 @proclistadd
dictnew dup @procdict !
@procinfo ! 16 0 @procinfo!
} : PROGRAM{
{ over sbits < { s>c <b swap ref, b> <s } if } : @adj-long-proc
{ // i s l
@adj-long-proc swap @procdict @ @procdictkeylen
@adj-long-proc over @procdict @ @procdictkeylen
idict!+ not abort"cannot define procedure, redefined?"
@procdict !
@procdict ! 2 2 @procinfo~!
} : @def-proc
{ @procinfo @ null? not } : @have-procinfo?
{ @have-procinfo? { 4 4 @procinfo~! } { drop } cond } : @proc-inlined
{ @have-procinfo? { 8 8 @procinfo~! } { drop } cond } : @proc-called
{ 1000 @def-proc } : PROC
{ 0 @def-proc } : PROCREF
{ @procdict @ @procdictkeylen idict@ abort"procedure already defined"
} : @fail-ifdef
{ u@?+ { swap abort"first bits are not zeroes" } if } : @cut-zeroes
{ over @fail-ifdef
2 { rot @normal? rot b> <s swap @def-proc drop } does
null swap @doafter<{
2 { rot @normal? rot b> <s @zcount @cut-zeroes swap @def-proc drop } does
null swap @doafter<{ 0 @zcount u,
} : @PROC:<{
{ 1000 @PROC:<{ } : PROC:<{
{ 0 @PROC:<{ } : PROCREF:<{
{ dup @proc-called CALLDICT } dup : CALL : CALLDICT
{ dup @proc-called JMPDICT } dup : JMP : JMPDICT
{ dup @proc-called PREPAREDICT } dup : PREPARE : PREPAREDICT
{ dup @procdict @ @procdictkeylen idict@
{ nip INLINE } { CALLDICT } cond
{ swap @proc-inlined INLINE } { CALLDICT } cond
} dup : INLINECALL : INLINECALLDICT
{ 0 @procdict @ @procdictkeylen idict@ not abort"`main` procedure not defined" drop
} : @chkmaindef
{ @procdict @ @procdictkeylen idict- drop @procdict ! } : @remove-proc
{ ."Procedure `" over type ."` index=" 2 pick . ." flags=0x" dup x. cr } : @showprocinfo
// ( proc_name proc_idx f -- ) f:+1=declared, +2=defined, +4=inlined, +8=called, +16=method
{ // @showprocinfo
dup 0x1a and 2 = asm-mode @ 3 and and ?dup {
2 and {
over ."Warning: removing (inlined) procedure `" type ."` from call dictionary" cr
} if
2 pick @remove-proc
} if // remove unused procs
dup 0xc and 0xc = asm-mode @ 4 and and {
over ."Warning: inline procedure `" type ."` is not always inlined" cr
} if
dup 0x1e and 2 = asm-mode @ 8 and and {
over ."Warning: procedure `" type ."` defined but not used" cr
} if
drop 2drop
} : @chkprocdef
{ @chkmaindef
@proclist @ { dup null? not } {
uncons swap dup find not
{ +": undefined procedure name in list" abort } if
execute @procdict @ @procdictkeylen idict@ not
uncons swap unpair over find not
{ drop +": undefined procedure name in list" abort } if
drop tuck @procdict @ @procdictkeylen idict@ not
{ +": procedure declared but left undefined" abort } if
drop (forget)
drop swap 2dup @procinfo@ @chkprocdef (forget)
} while
drop @proclist null! @proccnt 0!
drop @proclist null! @procinfo null! @proccnt 0!
@procdict dup @ swap null!
} : }END
forget @proclist forget @proccnt
{ }END <{ SETCP0 swap @procdictkeylen DICTPUSHCONST DICTIGETJMP 11 THROWARG }> } : }END>
{ }END <{ SETCP0 swap @procdictkeylen DICTPUSHCONST DICTIGETJMPZ 11 THROWARG }> } : }END>
{ }END> b> } : }END>c
{ }END>c <s } : }END>s
@ -1116,6 +1187,14 @@ forget @proclist forget @proccnt
-3 constant split_prepare
-4 constant split_install
{ asm-mode 0 3 ~! } : asm-no-remove-unused
{ asm-mode 1 1 ~! } : asm-remove-unused // enabled by default
{ asm-mode 3 3 ~! } : asm-warn-remove-unused
{ asm-mode 4 4 ~! } : asm-warn-inline-mix
{ asm-mode 0 4 ~! } : asm-no-warn-inline-mix // disabled by default
{ asm-mode 8 8 ~! } : asm-warn-unused
{ asm-mode 0 8 ~! } : asm-no-warn-unused // disabled by default
// ( c -- ) add vm library for later use with runvmcode
{ <b over ref, b> <s swap hash vmlibs @ 256 udict! not abort"cannot add library" vmlibs ! } : add-lib
// ( x -- c ) make library reference cell

View File

@ -0,0 +1,21 @@
library Color
{ 27 emit } : esc
{ char " word 27 chr swap $+ 1 ' type does create } :_ make-esc"
make-esc"[0m" ^reset
make-esc"[30m" ^black
make-esc"[31m" ^red
make-esc"[32m" ^green
make-esc"[33m" ^yellow
make-esc"[34m" ^blue
make-esc"[35m" ^magenta
make-esc"[36m" ^cyan
make-esc"[37m" ^white
// bold
make-esc"[30;1m" ^Black
make-esc"[31;1m" ^Red
make-esc"[32;1m" ^Green
make-esc"[33;1m" ^Yellow
make-esc"[34;1m" ^Blue
make-esc"[35;1m" ^Magenta
make-esc"[36;1m" ^Cyan
make-esc"[37;1m" ^White

View File

@ -79,12 +79,15 @@ variable base
{ char ) word "$" swap $+ 1 { find 0= abort"undefined parameter" execute } } ::_ $(
// b s -- ?
{ sbitrefs rot brembitrefs rot >= -rot <= and } : s-fits?
// b s x -- ?
{ swap sbitrefs -rot + rot brembitrefs -rot <= -rot <= and } : s-fits-with?
{ 0 swap ! } : 0!
{ tuck @ + swap ! } : +!
{ tuck @ swap - swap ! } : -!
{ 1 swap +! } : 1+!
{ -1 swap +! } : 1-!
{ null swap ! } : null!
{ not 2 pick @ and xor swap ! } : ~!
0 tuple constant nil
{ 1 tuple } : single
{ 2 tuple } : pair
@ -111,3 +114,20 @@ variable base
{ true (atom) drop } : atom
{ bl word atom 1 'nop } ::_ `
{ hole dup 1 { @ execute } does create } : recursive
{ 0 { 1+ dup 1 ' $() does over (.) "$" swap $+ 0 (create) } rot times drop } : :$1..n
{ 10 hold } : +cr
{ 9 hold } : +tab
{ "" swap { 0 word 2dup $cmp } { rot swap $+ +cr swap } while 2drop } : scan-until-word
{ 0 word -trailing scan-until-word 1 'nop } ::_ $<<
{ 0x40 runvmx } : runvmcode
{ 0x48 runvmx } : gasrunvmcode
{ 0x43 runvmx } : runvmdict
{ 0x4b runvmx } : gasrunvmdict
{ 0x45 runvmx } : runvm
{ 0x4d runvmx } : gasrunvm
{ 0x55 runvmx } : runvmctx
{ 0x5d runvmx } : gasrunvmctx
{ 0x75 runvmx } : runvmctxact
{ 0x7d runvmx } : gasrunvmctxact
{ 0x35 runvmx } : runvmctxactq
{ 0x3d runvmx } : gasrunvmctxactq

View File

@ -0,0 +1,131 @@
library GetOpt // Simple command-line options parser
"Lists.fif" include
// May be used as follows:
// begin-options
// "h" { ."Help Message" 0 halt } short-option
// "v" { parse-int =: verbosity } short-option-arg
// "i" "--interactive" { true =: interactive } short-long-option
// parse-options
// ( l -- l') computes tail of list l if non-empty; else ()
{ dup null? ' cdr ifnot } : safe-cdr
// ( l c -- l') deletes first c elements from list l
{ ' safe-cdr swap times } : list-delete-first
// ( l n c -- l' ) deletes c elements starting from n-th in list l
recursive list-delete-range {
dup 0<= { 2drop } {
over 0<= { nip list-delete-first } {
swap 1- swap rot uncons 2swap list-delete-range cons
} cond } cond
} swap !
// ( n c -- ) deletes $n .. $(n+c-1) from the argument list $*
{ swap 1- $* @ swap rot list-delete-range $* ! } : $*del..
// ( s s' -- ? ) checks whether s' is a prefix of s
{ tuck $len over $len over >= { $| drop $= } { 2drop drop false } cond
} : $pfx?
// ( s -- ? ) checks whether s is an option (a string beginning with '-')
{ dup $len 1 > { "-" $pfx? } { drop false } cond } : is-opt?
// ( s -- ? ) checks whether s is a digit option
{ 2 $| drop 1 $| nip $>B 8 B>u@ dup 57 <= swap 48 >= and } : is-digit-opt?
0 box constant disable-digit-opts
// ( l -- s i or 0 ) finds first string in l beginning with '-'
{ 0 { 1+ over null? { 2drop 0 true } {
swap uncons over is-opt?
{ disable-digit-opts @ { over is-digit-opt? not } { true } cond } { false } cond
{ drop swap true } { nip swap false } cond
} cond } until
} : list-find-opt
// ( -- s i or 0 ) finds first option in cmdline args
{ $* @ list-find-opt } : first-opt
' second : get-opt-flags
' first : get-opt-exec
// ( s t -- ? ) checks whether short/long option s matches description t
{ third $= } : short-option-matches
{ dup get-opt-flags 4 and 0= 3 + [] $=
} : long-option-matches
// ( t -- s -1 or 0 ) extracts help message from description
{ dup get-opt-flags 4 and 0= 4 + over count over >
{ [] true } { 2drop false } cond
} : get-opt-help
// ( s l -- t -1 or 0 ) finds short/long option s in list l
{ swap 1 { swap short-option-matches } does assoc-gen
} : lookup-short-option
{ swap 1 { swap long-option-matches } does assoc-gen
} : lookup-long-option
// ( s -- s' null or s' s'' ) Splits long option --opt=arg at '='
{ dup "=" $pos 1+ ?dup { tuck $| swap rot 1- $| drop swap } { null } cond
} : split-longopt
// ( l -- f or 0 ) Extracts global option flags from first entry of l
{ dup null? { drop 0 } { car get-opt-flags -256 and } cond
} : get-global-option-flags
variable options-list
// ( l -- i or 0 )
// parses command line arguments according to option description list l
// and returns index i of first incorrect option
{ dup options-list ! get-global-option-flags
256 and disable-digit-opts !
{ first-opt dup 0= { true } {
swap dup "--" $pfx? { // i s
dup $len 2 = { drop dup 1 $*del.. 0 true } {
split-longopt swap options-list @
lookup-long-option not { drop true } { // i s' t f
dup get-opt-exec swap get-opt-flags 3 and // i s' e f'
2 pick null? { dup 1 = } { dup 0= negate } cond // i s' e f' f''
dup 1 = { 2drop 2drop true } {
{ drop nip over 1+ $() swap execute 2 $*del.. false } {
' nip ifnot execute 1 $*del.. false
} cond } cond } cond } cond } { // i s
1 $| nip {
dup $len 0= { drop 1 $*del.. false true } {
1 $| swap options-list @ // i s' s l
lookup-short-option not { drop true true } { // i s' t
dup get-opt-exec swap get-opt-flags 3 and // i s' e f'
?dup 0= { execute false } {
2 pick $len { drop execute "" false } {
2 = { nip null swap execute "" false } { // i e
nip over 1+ $() swap execute 2 $*del.. false true
} cond } cond } cond } cond } cond } until
} cond
} cond } until
} : getopt
// ( t -- ) Displays help message for one option
{ dup get-opt-flags dup 4 and 2 pick third swap {
."-" type ."/" over 3 [] type } {
dup $len { dup "--" $pfx? { ."-" } ifnot type } {
drop ."usage: " $0 type
} cond } cond
dup 3 and ?dup {
2 = { ."[=<optarg>]" } { ."=<optarg>" } cond
} if
8 and { 9 emit } ifnot
get-opt-help { type } { ."No help available" } cond cr
} : show-opt-help
// ( -- ) Displays options help message according to options-list
{ options-list @ { dup null? not } {
uncons swap show-opt-help
} while drop
} : show-options-help
// ( l -- ) Parses options and throws an error on failure
{ getopt ?dup {
$() "cannot parse command line options near `" swap $+ +"`"
show-options-help abort } if
} : run-getopt
anon constant opt-list-marker
' opt-list-marker : begin-options
{ opt-list-marker list-until-marker } : end-options
{ end-options run-getopt } : parse-options
// ( s e -- o ) Creates short/long option s with execution token e
{ 0 rot triple } dup : short-option : long-option
// ( s s' e -- o ) Creates a combined short option s and long option s' with execution token e
{ 4 2swap 4 tuple } : short-long-option
{ 1 rot triple } dup : short-option-arg : long-option-arg
{ 2 rot triple } dup : short-option-?arg : long-option-?arg
{ 5 2swap 4 tuple } : short-long-option-arg
{ 6 2swap 4 tuple } : short-long-option-?arg
// ( o s -- s' ) Adds help message to option
' , : option-help
// ( s f -- o ) Creates a generic help message
{ swap 'nop rot "" 3 roll 4 tuple } : generic-help-setopt
{ 0 generic-help-setopt } : generic-help
256 constant disable-digit-options

View File

@ -12,6 +12,8 @@ library TonUtil // TON Blockchain Fift Library
{ (number) 1- abort"integer expected" } : parse-int
{ over null? ' swap if drop } : replace-if-null
// Private key load/generate
// ( fname -- pubkey privkey )
{ dup ."Loading private key from file " type cr
@ -32,8 +34,10 @@ library TonUtil // TON Blockchain Fift Library
1 and 0=
} : parse-smc-addr
// ( x -- ) Displays a 64-digit hex number
{ 64 0x. } : 64x.
// ( wc addr -- ) Show address in <workchain>:<account> form
{ swap ._ .":" 64 0x. } : .addr
{ swap ._ .":" 64x. } : .addr
// ( wc addr flags -- ) Show address in base64url form
{ smca>$ type } : .Addr
// ( wc addr fname -- ) Save address to file in 36-byte format
@ -65,6 +69,9 @@ library TonUtil // TON Blockchain Fift Library
// ( b wc addr -- b' ) Serializes address into Builder b
{ -rot 8 i, swap 256 u, } : addr,
{ over 8 fits { rot b{100} s, -rot addr, } {
rot b{110} s, 256 9 u, rot 32 i, swap 256 u, } cond
} : Addr,
// Gram utilities
1000000000 constant Gram
@ -148,3 +155,46 @@ recursive append-long-bytes {
// ( x -- S ) serialize public key
{ 256 u>B B{3ee6} swap B+ dup crc16 16 u>B B+ B>base64 } : pubkey>$
{ pubkey>$ type } : .pubkey
// adnl address parser
{ 256 u>B B{2D} swap B+ dup crc16 16 u>B B+ } : adnl-preconv
{ swap 32 /mod dup 26 < { 65 } { 24 } cond + rot swap hold } : Base32#
{ <# ' Base32# 8 times #> } : Base32#*8
{ "" over Blen 5 / { swap 40 B>u@+ Base32#*8 nip rot swap $+ } swap times nip } : B>Base32
// ( x -- S ) Converts an adnl-address from a 256-bit integer to a string
{ adnl-preconv B>Base32 1 $| nip } : adnl>$
{ 65 - dup 0>= { -33 and dup 26 < } { 41 + dup 25 > over 32 < and } cond ?dup nip } : Base32-digit?
{ Base32-digit? not abort"not a Base32 digit" } : Base32-digit
{ 0 { over $len } { swap 1 $| -rot (char) Base32-digit swap 5 << + } while nip } : Base32-number
{ B{} { over $len } { swap 8 $| -rot Base32-number 40 u>B B+ } while nip } : Base32>B
// ( S -- x ) Converts an adnl address from a string to 256-bit integer
{ dup $len 55 <> abort"not 55 alphanumeric characters" "F" swap $+ Base32>B
33 B| 16 B>u@ over crc16 <> abort"crc16 checksum mismatch"
8 B>u@+ 0x2D <> abort"not a valid adnl address" 256 B>u@ } : $>adnl
{ 65 - dup 0>= { -33 and 10 + dup 16 < } { 17 + dup 0>= over 10 < and } cond ?dup nip } : hex-digit?
// ( S -- x -1 or 0 ) Parses a hexadecimal integer
{ dup $len {
0 {
4 << swap 1 $| -rot (char) hex-digit? // S a d -1 or S a 0
{ + over $len 0= } { drop -1 true } cond
} until
dup 0< { 2drop false } { nip true } cond
} { drop false } cond
} : hex$>u?
// ( S -- x )
{ hex$>u? not abort"not a hexadecimal number" } : hex$>u
{ dup $len 64 = { hex$>u } {
dup $len 55 = { $>adnl } {
true abort"invalid adnl address"
} cond } cond
} : parse-adnl-addr
{ adnl>$ type } : .adnl
{ bl word parse-adnl-addr 1 'nop } ::_ adnl:
// ( x a b -- a<=x<=b )
{ 2 pick >= -rot >= and } : in-range?

View File

@ -46,6 +46,9 @@ td::Result<std::string> load_Lists_fif(std::string dir = "") {
td::Result<std::string> load_Lisp_fif(std::string dir = "") {
return load_source("Lisp.fif", dir);
}
td::Result<std::string> load_GetOpt_fif(std::string dir = "") {
return load_source("GetOpt.fif", dir);
}
class MemoryFileLoader : public fift::FileLoader {
public:
@ -115,6 +118,10 @@ td::Result<fift::SourceLookup> create_source_lookup(std::string main, bool need_
TRY_RESULT(f, load_TonUtil_fif(dir));
loader->add_file("/TonUtil.fif", std::move(f));
}
{
TRY_RESULT(f, load_GetOpt_fif(dir));
loader->add_file("/GetOpt.fif", std::move(f));
}
}
if (need_lisp) {
TRY_RESULT(f, load_Lisp_fif(dir));

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 "words.h"
@ -32,7 +32,7 @@
#include "vm/cells.h"
#include "vm/cellslice.h"
#include "vm/continuation.h"
#include "vm/vm.h"
#include "vm/cp0.h"
#include "vm/dict.h"
#include "vm/boc.h"
@ -96,6 +96,10 @@ void interpret_dotstack_list(IntCtx& ctx) {
*ctx.output_stream << std::endl;
}
void interpret_dotstack_list_dump(IntCtx& ctx) {
ctx.stack.dump(*ctx.output_stream, 3);
}
void interpret_dump(IntCtx& ctx) {
ctx.stack.pop_chk().dump(*ctx.output_stream);
*ctx.output_stream << ' ';
@ -105,6 +109,10 @@ void interpret_dump_internal(vm::Stack& stack) {
stack.push_string(stack.pop_chk().to_string());
}
void interpret_list_dump_internal(vm::Stack& stack) {
stack.push_string(stack.pop_chk().to_lisp_string());
}
void interpret_print_list(IntCtx& ctx) {
ctx.stack.pop_chk().print_list(*ctx.output_stream);
*ctx.output_stream << ' ';
@ -172,9 +180,9 @@ 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();
td::BigIntG<257 * 2> tmp{0};
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
auto q = td::RefInt256{true};
auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int(std::move(q));
@ -184,26 +192,23 @@ 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();
td::BigIntG<257 * 2> tmp{0};
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y);
auto q = td::RefInt256{true};
auto q = td::make_refint();
tmp.mod_div(*z, q.unique_write(), round_mode);
q.unique_write().normalize();
auto r = td::RefInt256{true, tmp};
stack.push_int(std::move(q));
stack.push_int(std::move(r));
stack.push_int(td::make_refint(tmp));
}
void interpret_times_mod(vm::Stack& stack, int round_mode) {
auto z = stack.pop_int();
auto y = stack.pop_int();
auto x = stack.pop_int();
td::BigIntG<257 * 2> tmp{0};
typename td::BigInt256::DoubleInt tmp{0}, q;
tmp.add_mul(*x, *y);
td::BigIntG<257 * 2> q;
tmp.mod_div(*z, q, round_mode);
auto r = td::RefInt256{true, tmp};
stack.push_int(std::move(r));
stack.push_int(td::make_refint(tmp));
}
void interpret_negate(vm::Stack& stack) {
@ -245,21 +250,21 @@ void interpret_fits(vm::Stack& stack, bool sgnd) {
void interpret_pow2(vm::Stack& stack) {
int x = stack.pop_smallint_range(255);
auto r = td::RefInt256{true};
auto r = td::make_refint();
r.unique_write().set_pow2(x);
stack.push_int(r);
}
void interpret_neg_pow2(vm::Stack& stack) {
int x = stack.pop_smallint_range(256);
auto r = td::RefInt256{true};
auto r = td::make_refint();
r.unique_write().set_pow2(x).negate().normalize();
stack.push_int(r);
}
void interpret_pow2_minus1(vm::Stack& stack) {
int x = stack.pop_smallint_range(256);
auto r = td::RefInt256{true};
auto r = td::make_refint();
r.unique_write().set_pow2(x).add_tiny(-1).normalize();
stack.push_int(r);
}
@ -293,19 +298,18 @@ void interpret_times_rshift(vm::Stack& stack, int round_mode) {
int z = stack.pop_smallint_range(256);
auto y = stack.pop_int();
auto x = stack.pop_int();
td::BigIntG<257 * 2> tmp{0};
typename td::BigInt256::DoubleInt tmp{0};
tmp.add_mul(*x, *y).rshift(z, round_mode).normalize();
auto q = td::RefInt256{true, tmp};
stack.push_int(std::move(q));
stack.push_int(td::make_refint(tmp));
}
void interpret_lshift_div(vm::Stack& stack, int round_mode) {
int z = stack.pop_smallint_range(256);
auto y = stack.pop_int();
auto x = stack.pop_int();
td::BigIntG<257 * 2> tmp{*x};
typename td::BigInt256::DoubleInt tmp{*x};
tmp <<= z;
auto q = td::RefInt256{true};
auto q = td::make_refint();
tmp.mod_div(*y, q.unique_write(), round_mode);
q.unique_write().normalize();
stack.push_int(std::move(q));
@ -596,6 +600,12 @@ void interpret_str_split(vm::Stack& stack) {
stack.push_string(std::string{str, sz});
}
void interpret_str_pos(vm::Stack& stack) {
auto s2 = stack.pop_string(), s1 = stack.pop_string();
auto pos = s1.find(s2);
stack.push_smallint(pos == std::string::npos ? -1 : pos);
}
void interpret_str_reverse(vm::Stack& stack) {
std::string s = stack.pop_string();
auto it = s.begin();
@ -651,6 +661,20 @@ void interpret_utf8_str_split(vm::Stack& stack) {
}
}
void interpret_utf8_str_pos(vm::Stack& stack) {
auto s2 = stack.pop_string(), s1 = stack.pop_string();
auto pos = s1.find(s2);
if (pos == std::string::npos) {
stack.push_smallint(-1);
return;
}
int cnt = 0;
for (std::size_t i = 0; i < pos; i++) {
cnt += ((s1[i] & 0xc0) != 0x80);
}
stack.push_smallint(cnt);
}
void interpret_str_remove_trailing_int(vm::Stack& stack, int arg) {
char x = (char)(arg ? arg : stack.pop_long_range(127));
std::string s = stack.pop_string();
@ -979,8 +1003,8 @@ void interpret_store_end(vm::Stack& stack, bool special) {
void interpret_from_cell(vm::Stack& stack) {
auto cell = stack.pop_cell();
Ref<vm::CellSlice> cs{true};
if (!cs.unique_write().load(vm::NoVmOrd(), std::move(cell))) {
Ref<vm::CellSlice> cs{true, vm::NoVmOrd(), std::move(cell)};
if (!cs->is_valid()) {
throw IntError{"deserializing a special cell as ordinary"};
}
stack.push(cs);
@ -1089,7 +1113,10 @@ void interpret_fetch_ref(vm::Stack& stack, int mode) {
stack.push(std::move(cs));
}
if (mode & 1) {
Ref<vm::CellSlice> new_cs{true, vm::NoVm(), std::move(cell)};
Ref<vm::CellSlice> new_cs{true, vm::NoVmOrd(), std::move(cell)};
if (!new_cs->is_valid()) {
throw IntError{"cannot load ordinary cell"};
}
stack.push(std::move(new_cs));
} else {
stack.push_cell(std::move(cell));
@ -1484,11 +1511,12 @@ void interpret_store_dict(vm::Stack& stack) {
}
// val key dict keylen -- dict' ?
void interpret_dict_add_u(vm::Stack& stack, vm::Dictionary::SetMode mode, bool add_builder, bool sgnd) {
void interpret_dict_add(vm::Stack& stack, vm::Dictionary::SetMode mode, bool add_builder, int sgnd) {
int n = stack.pop_smallint_range(vm::Dictionary::max_key_bits);
vm::Dictionary dict{stack.pop_maybe_cell(), n};
unsigned char buffer[vm::Dictionary::max_key_bytes];
vm::BitSlice key = dict.integer_key(stack.pop_int(), n, sgnd, buffer);
vm::BitSlice key =
(sgnd >= 0) ? dict.integer_key(stack.pop_int(), n, sgnd, buffer) : stack.pop_cellslice()->prefetch_bits(n);
if (!key.is_valid()) {
throw IntError{"not enough bits for a dictionary key"};
}
@ -1502,81 +1530,91 @@ void interpret_dict_add_u(vm::Stack& stack, vm::Dictionary::SetMode mode, bool a
stack.push_bool(res);
}
void interpret_dict_get_u(vm::Stack& stack, bool sgnd) {
void interpret_dict_get(vm::Stack& stack, int sgnd, int mode) {
int n = stack.pop_smallint_range(vm::Dictionary::max_key_bits);
vm::Dictionary dict{stack.pop_maybe_cell(), n};
unsigned char buffer[vm::Dictionary::max_key_bytes];
vm::BitSlice key = dict.integer_key(stack.pop_int(), n, sgnd, buffer);
vm::BitSlice key =
(sgnd >= 0) ? dict.integer_key(stack.pop_int(), n, sgnd, buffer) : stack.pop_cellslice()->prefetch_bits(n);
if (!key.is_valid()) {
throw IntError{"not enough bits for a dictionary key"};
}
auto res = dict.lookup(std::move(key));
if (res.not_null()) {
auto res = (mode & 4 ? dict.lookup_delete(std::move(key)) : dict.lookup(std::move(key)));
if (mode & 4) {
stack.push_maybe_cell(std::move(dict).extract_root_cell());
}
bool found = res.not_null();
if (found && (mode & 2)) {
stack.push_cellslice(std::move(res));
stack.push_bool(true);
} else {
stack.push_bool(false);
}
if (mode & 1) {
stack.push_bool(found);
}
}
void interpret_dict_map(IntCtx& ctx) {
void interpret_dict_map(IntCtx& ctx, bool ext, bool sgnd) {
auto func = pop_exec_token(ctx);
int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits);
vm::Dictionary dict{ctx.stack.pop_maybe_cell(), n};
vm::Dictionary::simple_map_func_t simple_map = [&ctx, func](vm::CellBuilder& cb, Ref<vm::CellSlice> cs_ref) -> bool {
ctx.stack.push_builder(Ref<vm::CellBuilder>(cb));
ctx.stack.push_cellslice(std::move(cs_ref));
func->run(ctx);
assert(cb.is_unique());
if (!ctx.stack.pop_bool()) {
return false;
vm::Dictionary dict{ctx.stack.pop_maybe_cell(), n}, dict2{n};
for (auto entry : dict.range(false, sgnd)) {
ctx.stack.push_builder(Ref<vm::CellBuilder>{true});
if (ext) {
ctx.stack.push_int(dict.key_as_integer(entry.first, sgnd));
}
ctx.stack.push_cellslice(std::move(entry.second));
func->run(ctx);
if (ctx.stack.pop_bool()) {
if (!dict2.set_builder(entry.first, n, ctx.stack.pop_builder())) {
throw IntError{"cannot insert value into dictionary"};
}
}
Ref<vm::CellBuilder> cb_ref = ctx.stack.pop_builder();
cb = *cb_ref;
return true;
};
dict.map(std::move(simple_map));
ctx.stack.push_maybe_cell(std::move(dict).extract_root_cell());
ctx.stack.push_maybe_cell(std::move(dict2).extract_root_cell());
}
void interpret_dict_map_ext(IntCtx& ctx) {
void interpret_dict_foreach(IntCtx& ctx, bool reverse, bool sgnd) {
auto func = pop_exec_token(ctx);
int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits);
vm::Dictionary dict{ctx.stack.pop_maybe_cell(), n};
vm::Dictionary::map_func_t map_func = [&ctx, func](vm::CellBuilder& cb, Ref<vm::CellSlice> cs_ref,
td::ConstBitPtr key, int key_len) -> bool {
ctx.stack.push_builder(Ref<vm::CellBuilder>(cb));
td::RefInt256 x{true};
x.unique_write().import_bits(key, key_len, false);
ctx.stack.push_int(std::move(x));
ctx.stack.push_cellslice(std::move(cs_ref));
for (auto entry : dict.range(reverse, sgnd)) {
ctx.stack.push_int(dict.key_as_integer(entry.first, sgnd));
ctx.stack.push_cellslice(std::move(entry.second));
func->run(ctx);
assert(cb.is_unique());
if (!ctx.stack.pop_bool()) {
return false;
ctx.stack.push_bool(false);
return;
}
Ref<vm::CellBuilder> cb_ref = ctx.stack.pop_builder();
cb = *cb_ref;
return true;
};
dict.map(std::move(map_func));
ctx.stack.push_maybe_cell(std::move(dict).extract_root_cell());
ctx.stack.push_bool(true);
}
void interpret_dict_foreach(IntCtx& ctx) {
// mode: +1 = reverse, +2 = signed, +4 = strict, +8 = lookup backwards, +16 = with hint
void interpret_dict_foreach_from(IntCtx& ctx, int mode) {
if (mode < 0) {
mode = ctx.stack.pop_smallint_range(31);
}
auto func = pop_exec_token(ctx);
int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits);
vm::Dictionary dict{ctx.stack.pop_maybe_cell(), n};
vm::Dictionary::foreach_func_t foreach_func = [&ctx, func](Ref<vm::CellSlice> cs_ref, td::ConstBitPtr key,
int key_len) -> bool {
td::RefInt256 x{true};
x.unique_write().import_bits(key, key_len, false);
ctx.stack.push_int(std::move(x));
ctx.stack.push_cellslice(std::move(cs_ref));
vm::DictIterator it{dict, mode & 3};
unsigned char buffer[vm::Dictionary::max_key_bytes];
for (int s = (mode >> 4) & 1; s >= 0; --s) {
auto key = dict.integer_key(ctx.stack.pop_int(), n, mode & 2, buffer);
if (!key.is_valid()) {
throw IntError{"not enough bits for a dictionary key"};
}
it.lookup(key, mode & 4, mode & 8);
}
for (; !it.eof(); ++it) {
ctx.stack.push_int(dict.key_as_integer(it.cur_pos(), mode & 2));
ctx.stack.push_cellslice(it.cur_value());
func->run(ctx);
return ctx.stack.pop_bool();
if (!ctx.stack.pop_bool()) {
ctx.stack.push_bool(false);
return;
}
};
ctx.stack.push_bool(dict.check_for_each(std::move(foreach_func)));
ctx.stack.push_bool(true);
}
void interpret_dict_merge(IntCtx& ctx) {
@ -1584,24 +1622,33 @@ void interpret_dict_merge(IntCtx& ctx) {
int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits);
vm::Dictionary dict2{ctx.stack.pop_maybe_cell(), n};
vm::Dictionary dict1{ctx.stack.pop_maybe_cell(), n};
vm::Dictionary::simple_combine_func_t simple_combine = [&ctx, func](vm::CellBuilder& cb, Ref<vm::CellSlice> cs1_ref,
Ref<vm::CellSlice> cs2_ref) -> bool {
ctx.stack.push_builder(Ref<vm::CellBuilder>(cb));
ctx.stack.push_cellslice(std::move(cs1_ref));
ctx.stack.push_cellslice(std::move(cs2_ref));
func->run(ctx);
assert(cb.is_unique());
if (!ctx.stack.pop_bool()) {
return false;
vm::Dictionary dict3{n};
auto it1 = dict1.begin(), it2 = dict2.begin();
while (!it1.eof() || !it2.eof()) {
int c = it1.eof() ? 1 : (it2.eof() ? -1 : it1.cur_pos().compare(it2.cur_pos(), n));
bool ok = true;
if (c < 0) {
ok = dict3.set(it1.cur_pos(), n, it1.cur_value());
++it1;
} else if (c > 0) {
ok = dict3.set(it2.cur_pos(), n, it2.cur_value());
++it2;
} else {
ctx.stack.push_builder(Ref<vm::CellBuilder>{true});
ctx.stack.push_cellslice(it1.cur_value());
ctx.stack.push_cellslice(it2.cur_value());
func->run(ctx);
if (ctx.stack.pop_bool()) {
ok = dict3.set_builder(it1.cur_pos(), n, ctx.stack.pop_builder());
}
++it1;
++it2;
}
if (!ok) {
throw IntError{"cannot insert value into dictionary"};
}
Ref<vm::CellBuilder> cb_ref = ctx.stack.pop_builder();
cb = *cb_ref;
return true;
};
if (!dict1.combine_with(dict2, std::move(simple_combine))) {
throw IntError{"cannot combine dictionaries"};
}
ctx.stack.push_maybe_cell(std::move(dict1).extract_root_cell());
ctx.stack.push_maybe_cell(std::move(dict3).extract_root_cell());
}
void interpret_dict_diff(IntCtx& ctx) {
@ -1609,17 +1656,40 @@ void interpret_dict_diff(IntCtx& ctx) {
int n = ctx.stack.pop_smallint_range(vm::Dictionary::max_key_bits);
vm::Dictionary dict2{ctx.stack.pop_maybe_cell(), n};
vm::Dictionary dict1{ctx.stack.pop_maybe_cell(), n};
vm::Dictionary::scan_diff_func_t scan_value_pair =
[&ctx, func](td::ConstBitPtr key, int key_len, Ref<vm::CellSlice> cs1_ref, Ref<vm::CellSlice> cs2_ref) -> bool {
td::RefInt256 x{true};
x.unique_write().import_bits(key, key_len, false);
ctx.stack.push_int(std::move(x));
ctx.stack.push_maybe_cellslice(std::move(cs1_ref));
ctx.stack.push_maybe_cellslice(std::move(cs2_ref));
func->run(ctx);
return ctx.stack.pop_bool();
};
ctx.stack.push_bool(dict1.scan_diff(dict2, std::move(scan_value_pair)));
auto it1 = dict1.begin(), it2 = dict2.begin();
while (!it1.eof() || !it2.eof()) {
int c = it1.eof() ? 1 : (it2.eof() ? -1 : it1.cur_pos().compare(it2.cur_pos(), n));
bool run = true;
if (c < 0) {
ctx.stack.push_int(dict1.key_as_integer(it1.cur_pos()));
ctx.stack.push_cellslice(it1.cur_value());
ctx.stack.push_null();
++it1;
} else if (c > 0) {
ctx.stack.push_int(dict2.key_as_integer(it2.cur_pos()));
ctx.stack.push_null();
ctx.stack.push_cellslice(it2.cur_value());
++it2;
} else {
if (!it1.cur_value()->contents_equal(*it2.cur_value())) {
ctx.stack.push_int(dict1.key_as_integer(it1.cur_pos()));
ctx.stack.push_cellslice(it1.cur_value());
ctx.stack.push_cellslice(it2.cur_value());
} else {
run = false;
}
++it1;
++it2;
}
if (run) {
func->run(ctx);
if (!ctx.stack.pop_bool()) {
ctx.stack.push_bool(false);
return;
}
}
}
ctx.stack.push_bool(true);
}
void interpret_pfx_dict_add(vm::Stack& stack, vm::Dictionary::SetMode mode, bool add_builder) {
@ -1858,7 +1928,7 @@ int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool a
const char* str = s.c_str();
int len = (int)s.size();
int frac = -1, base, *frac_ptr = allow_frac ? &frac : nullptr;
num = td::RefInt256{true};
num = td::make_refint();
auto& x = num.unique_write();
if (len >= 4 && str[0] == '-' && str[1] == '0' && (str[2] == 'x' || str[2] == 'b')) {
if (str[2] == 'x') {
@ -1900,7 +1970,7 @@ int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool a
if (frac < 0) {
return 1;
} else {
denom = td::RefInt256{true, 1};
denom = td::make_refint(1);
while (frac-- > 0) {
if (!denom.unique_write().mul_tiny(base).normalize_bool()) {
if (throw_error) {
@ -2141,6 +2211,7 @@ class StringLogger : public td::LogInterface {
}
std::string res;
};
class OstreamLogger : public td::LogInterface {
public:
explicit OstreamLogger(std::ostream* stream) : stream_(stream) {
@ -2163,59 +2234,42 @@ std::vector<Ref<vm::Cell>> get_vm_libraries() {
}
}
void interpret_run_vm_code(IntCtx& ctx, bool with_gas) {
long long gas_limit = with_gas ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
auto cs = ctx.stack.pop_cellslice();
OstreamLogger ostream_logger(ctx.error_stream);
auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
vm::GasLimits gas{gas_limit};
int res = vm::run_vm_code(cs, ctx.stack, 0, nullptr, log, nullptr, &gas, get_vm_libraries());
ctx.stack.push_smallint(res);
if (with_gas) {
ctx.stack.push_smallint(gas.gas_consumed());
// mode: -1 = pop from stack
// +1 = same_c3 (set c3 to code)
// +2 = push_0 (push an implicit 0 before running the code)
// +4 = load c4 (persistent data) from stack and return its final value
// +8 = load gas limit from stack and return consumed gas
// +16 = load c7 (smart-contract context)
// +32 = return c5 (actions)
// +64 = log vm ops to stderr
void interpret_run_vm(IntCtx& ctx, int mode) {
if (mode < 0) {
mode = ctx.stack.pop_smallint_range(0xff);
}
}
void interpret_run_vm_dict(IntCtx& ctx, bool with_gas) {
long long gas_limit = with_gas ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
auto cs = ctx.stack.pop_cellslice();
OstreamLogger ostream_logger(ctx.error_stream);
auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
vm::GasLimits gas{gas_limit};
int res = vm::run_vm_code(cs, ctx.stack, 3, nullptr, log, nullptr, &gas, get_vm_libraries());
ctx.stack.push_smallint(res);
if (with_gas) {
ctx.stack.push_smallint(gas.gas_consumed());
bool with_data = mode & 4;
Ref<vm::Tuple> c7;
Ref<vm::Cell> data, actions;
long long gas_limit = (mode & 8) ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
if (mode & 16) {
c7 = ctx.stack.pop_tuple();
}
}
void interpret_run_vm(IntCtx& ctx, bool with_gas) {
long long gas_limit = with_gas ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
auto data = ctx.stack.pop_cell();
auto cs = ctx.stack.pop_cellslice();
OstreamLogger ostream_logger(ctx.error_stream);
auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
vm::GasLimits gas{gas_limit};
int res = vm::run_vm_code(cs, ctx.stack, 1, &data, log, nullptr, &gas, get_vm_libraries());
ctx.stack.push_smallint(res);
ctx.stack.push_cell(std::move(data));
if (with_gas) {
ctx.stack.push_smallint(gas.gas_consumed());
if (with_data) {
data = ctx.stack.pop_cell();
}
}
void interpret_run_vm_c7(IntCtx& ctx, bool with_gas) {
long long gas_limit = with_gas ? ctx.stack.pop_long_range(vm::GasLimits::infty) : vm::GasLimits::infty;
auto c7 = ctx.stack.pop_tuple();
auto data = ctx.stack.pop_cell();
auto cs = ctx.stack.pop_cellslice();
OstreamLogger ostream_logger(ctx.error_stream);
auto log = create_vm_log(ctx.error_stream ? &ostream_logger : nullptr);
auto log = create_vm_log((mode & 64) && ctx.error_stream ? &ostream_logger : nullptr);
vm::GasLimits gas{gas_limit};
int res = vm::run_vm_code(cs, ctx.stack, 1, &data, log, nullptr, &gas, get_vm_libraries(), std::move(c7));
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);
ctx.stack.push_cell(std::move(data));
if (with_gas) {
if (with_data) {
ctx.stack.push_cell(std::move(data));
}
if (mode & 32) {
ctx.stack.push_cell(std::move(actions));
}
if (mode & 8) {
ctx.stack.push_smallint(gas.gas_consumed());
}
}
@ -2328,12 +2382,57 @@ void interpret_db_run_vm_parallel(IntCtx& ctx) {
do_interpret_db_run_vm_parallel(ctx.error_stream, ctx.stack, ctx.ton_db, threads_n, tasks_n);
}
void interpret_store_vm_cont(vm::Stack& stack) {
auto vmcont = stack.pop_cont();
auto cb = stack.pop_builder();
if (!vmcont->serialize(cb.write())) {
throw IntError{"cannot serialize vm continuation"};
}
stack.push_builder(std::move(cb));
}
void interpret_fetch_vm_cont(vm::Stack& stack) {
auto cs = stack.pop_cellslice();
auto vmcont = vm::Continuation::deserialize(cs.write());
if (vmcont.is_null()) {
throw IntError{"cannot deserialize vm continuation"};
}
stack.push_cellslice(std::move(cs));
stack.push_cont(std::move(vmcont));
}
Ref<vm::Box> cmdline_args{true};
void interpret_get_fixed_cmdline_arg(vm::Stack& stack, int n) {
if (!n) {
return;
}
auto v = cmdline_args->get();
while (true) {
if (v.empty()) {
stack.push(vm::StackEntry{});
return;
}
auto t = v.as_tuple_range(2, 2);
if (t.is_null()) {
throw IntError{"invalid cmdline arg list"};
}
if (!--n) {
stack.push(t->at(0));
return;
}
v = t->at(1);
}
}
// n -- executes $n
void interpret_get_cmdline_arg(IntCtx& ctx) {
int n = ctx.stack.pop_smallint_range(999999);
char buffer[14];
sprintf(buffer, "$%d ", n);
auto entry = ctx.dictionary->lookup(std::string{buffer});
if (n) {
interpret_get_fixed_cmdline_arg(ctx.stack, n);
return;
}
auto entry = ctx.dictionary->lookup("$0 ");
if (!entry) {
throw IntError{"-?"};
} else {
@ -2341,6 +2440,19 @@ void interpret_get_cmdline_arg(IntCtx& ctx) {
}
}
void interpret_get_cmdline_arg_count(vm::Stack& stack) {
auto v = cmdline_args->get();
int cnt;
for (cnt = 0; !v.empty(); cnt++) {
auto t = v.as_tuple_range(2, 2);
if (t.is_null()) {
throw IntError{"invalid cmdline arg list"};
}
v = t->at(1);
}
stack.push_smallint(cnt);
}
void interpret_getenv(vm::Stack& stack) {
auto str = stack.pop_string();
auto value = str.size() < 1024 ? getenv(str.c_str()) : nullptr;
@ -2434,10 +2546,12 @@ void init_words_common(Dictionary& d) {
d.def_ctx_word("csr. ", interpret_dot_cellslice_rec);
d.def_ctx_word(".s ", interpret_dotstack);
d.def_ctx_word(".sl ", interpret_dotstack_list);
d.def_ctx_word(".sL ", interpret_dotstack_list_dump); // TMP
d.def_ctx_word(".dump ", interpret_dump);
d.def_ctx_word(".l ", interpret_print_list);
d.def_ctx_word(".tc ", interpret_dottc);
d.def_stack_word("(dump) ", interpret_dump_internal);
d.def_stack_word("(ldump) ", interpret_list_dump_internal);
d.def_stack_word("(.) ", interpret_dot_internal);
d.def_stack_word("(x.) ", std::bind(interpret_dothex_internal, _1, false));
d.def_stack_word("(X.) ", std::bind(interpret_dothex_internal, _1, true));
@ -2558,6 +2672,7 @@ void init_words_common(Dictionary& d) {
d.def_stack_word("$= ", interpret_str_equal);
d.def_stack_word("$cmp ", interpret_str_cmp);
d.def_stack_word("$reverse ", interpret_str_reverse);
d.def_stack_word("$pos ", interpret_str_pos);
d.def_stack_word("(-trailing) ", std::bind(interpret_str_remove_trailing_int, _1, 0));
d.def_stack_word("-trailing ", std::bind(interpret_str_remove_trailing_int, _1, ' '));
d.def_stack_word("-trailing0 ", std::bind(interpret_str_remove_trailing_int, _1, '0'));
@ -2565,6 +2680,7 @@ void init_words_common(Dictionary& d) {
d.def_stack_word("Blen ", interpret_bytes_len);
d.def_stack_word("$Len ", interpret_utf8_str_len);
d.def_stack_word("$Split ", interpret_utf8_str_split);
d.def_stack_word("$Pos ", interpret_utf8_str_pos);
d.def_ctx_word("Bx. ", std::bind(interpret_bytes_hex_print_raw, _1, true));
d.def_stack_word("B>X ", std::bind(interpret_bytes_to_hex, _1, true));
d.def_stack_word("B>x ", std::bind(interpret_bytes_to_hex, _1, false));
@ -2669,22 +2785,38 @@ void init_words_common(Dictionary& d) {
d.def_stack_word("dict, ", interpret_store_dict);
d.def_stack_word("dict@ ", std::bind(interpret_load_dict, _1, false));
d.def_stack_word("dict@+ ", std::bind(interpret_load_dict, _1, true));
d.def_stack_word("udict!+ ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Add, false, false));
d.def_stack_word("udict! ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Set, false, false));
d.def_stack_word("b>udict!+ ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Add, true, false));
d.def_stack_word("b>udict! ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Set, true, false));
d.def_stack_word("udict@ ", std::bind(interpret_dict_get_u, _1, false));
d.def_stack_word("idict!+ ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Add, false, true));
d.def_stack_word("idict! ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Set, false, true));
d.def_stack_word("b>idict!+ ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Add, true, true));
d.def_stack_word("b>idict! ", std::bind(interpret_dict_add_u, _1, vm::Dictionary::SetMode::Set, true, true));
d.def_stack_word("idict@ ", std::bind(interpret_dict_get_u, _1, true));
d.def_stack_word("sdict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, false, -1));
d.def_stack_word("sdict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, false, -1));
d.def_stack_word("b>sdict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, true, -1));
d.def_stack_word("b>sdict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, true, -1));
d.def_stack_word("sdict@ ", std::bind(interpret_dict_get, _1, -1, 3));
d.def_stack_word("sdict@- ", std::bind(interpret_dict_get, _1, -1, 7));
d.def_stack_word("sdict- ", std::bind(interpret_dict_get, _1, -1, 5));
d.def_stack_word("udict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, false, 0));
d.def_stack_word("udict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, false, 0));
d.def_stack_word("b>udict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, true, 0));
d.def_stack_word("b>udict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, true, 0));
d.def_stack_word("udict@ ", std::bind(interpret_dict_get, _1, 0, 3));
d.def_stack_word("udict@- ", std::bind(interpret_dict_get, _1, 0, 7));
d.def_stack_word("udict- ", std::bind(interpret_dict_get, _1, 0, 5));
d.def_stack_word("idict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, false, 1));
d.def_stack_word("idict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, false, 1));
d.def_stack_word("b>idict!+ ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Add, true, 1));
d.def_stack_word("b>idict! ", std::bind(interpret_dict_add, _1, vm::Dictionary::SetMode::Set, true, 1));
d.def_stack_word("idict@ ", std::bind(interpret_dict_get, _1, 1, 3));
d.def_stack_word("idict@- ", std::bind(interpret_dict_get, _1, 1, 7));
d.def_stack_word("idict- ", std::bind(interpret_dict_get, _1, 1, 5));
d.def_stack_word("pfxdict!+ ", std::bind(interpret_pfx_dict_add, _1, vm::Dictionary::SetMode::Add, false));
d.def_stack_word("pfxdict! ", std::bind(interpret_pfx_dict_add, _1, vm::Dictionary::SetMode::Set, false));
d.def_stack_word("pfxdict@ ", interpret_pfx_dict_get);
d.def_ctx_word("dictmap ", interpret_dict_map);
d.def_ctx_word("dictmapext ", interpret_dict_map_ext);
d.def_ctx_word("dictforeach ", interpret_dict_foreach);
d.def_ctx_word("dictmap ", std::bind(interpret_dict_map, _1, false, false));
d.def_ctx_word("dictmapext ", std::bind(interpret_dict_map, _1, true, false));
d.def_ctx_word("idictmapext ", std::bind(interpret_dict_map, _1, true, true));
d.def_ctx_word("dictforeach ", std::bind(interpret_dict_foreach, _1, false, false));
d.def_ctx_word("idictforeach ", std::bind(interpret_dict_foreach, _1, false, true));
d.def_ctx_word("dictforeachrev ", std::bind(interpret_dict_foreach, _1, true, false));
d.def_ctx_word("idictforeachrev ", std::bind(interpret_dict_foreach, _1, true, true));
d.def_ctx_word("dictforeachfromx ", std::bind(interpret_dict_foreach_from, _1, -1));
d.def_ctx_word("dictmerge ", interpret_dict_merge);
d.def_ctx_word("dictdiff ", interpret_dict_diff);
// slice/bitstring constants
@ -2756,6 +2888,10 @@ void init_words_common(Dictionary& d) {
d.def_ctx_word("quit ", interpret_quit);
d.def_ctx_word("bye ", interpret_bye);
d.def_stack_word("halt ", interpret_halt);
// cmdline args
d.def_stack_word("$* ", std::bind(interpret_literal, _1, vm::StackEntry{cmdline_args}));
d.def_stack_word("$# ", interpret_get_cmdline_arg_count);
d.def_ctx_word("$() ", interpret_get_cmdline_arg);
}
void init_words_ton(Dictionary& d) {
@ -2768,34 +2904,34 @@ void init_words_ton(Dictionary& d) {
d.def_stack_word("base64url>B ", std::bind(interpret_base64_to_bytes, _1, true, false));
}
void init_words_vm(Dictionary& d) {
void init_words_vm(Dictionary& d, bool enable_debug) {
using namespace std::placeholders;
vm::init_op_cp0();
vm::init_op_cp0(enable_debug);
// vm run
d.def_stack_word("vmlibs ", std::bind(interpret_literal, _1, vm::StackEntry{vm_libraries}));
d.def_ctx_word("runvmcode ", std::bind(interpret_run_vm_code, _1, false));
d.def_ctx_word("gasrunvmcode ", std::bind(interpret_run_vm_code, _1, true));
d.def_ctx_word("runvmdict ", std::bind(interpret_run_vm_dict, _1, false));
d.def_ctx_word("gasrunvmdict ", std::bind(interpret_run_vm_dict, _1, true));
d.def_ctx_word("runvm ", std::bind(interpret_run_vm, _1, false));
d.def_ctx_word("gasrunvm ", std::bind(interpret_run_vm, _1, true));
d.def_ctx_word("runvmctx ", std::bind(interpret_run_vm_c7, _1, false));
d.def_ctx_word("gasrunvmctx ", std::bind(interpret_run_vm_c7, _1, true));
// d.def_ctx_word("runvmcode ", std::bind(interpret_run_vm, _1, 0x40));
// d.def_ctx_word("runvm ", std::bind(interpret_run_vm, _1, 0x45));
d.def_ctx_word("runvmx ", std::bind(interpret_run_vm, _1, -1));
d.def_ctx_word("dbrunvm ", interpret_db_run_vm);
d.def_ctx_word("dbrunvm-parallel ", interpret_db_run_vm_parallel);
d.def_stack_word("vmcont, ", interpret_store_vm_cont);
d.def_stack_word("vmcont@ ", interpret_fetch_vm_cont);
}
void import_cmdline_args(Dictionary& d, std::string arg0, int n, const char* const argv[]) {
using namespace std::placeholders;
LOG(DEBUG) << "import_cmdlist_args(" << arg0 << "," << n << ")";
d.def_stack_word("$0 ", std::bind(interpret_literal, _1, vm::StackEntry{arg0}));
for (int i = 0; i < n; i++) {
char buffer[14];
sprintf(buffer, "$%d ", i + 1);
d.def_stack_word(buffer, std::bind(interpret_literal, _1, vm::StackEntry{argv[i]}));
vm::StackEntry list;
for (int i = n - 1; i >= 0; i--) {
list = vm::StackEntry::cons(vm::StackEntry{argv[i]}, list);
}
cmdline_args->set(std::move(list));
for (int i = 1; i <= n; i++) {
char buffer[14];
sprintf(buffer, "$%d ", i);
d.def_stack_word(buffer, std::bind(interpret_get_fixed_cmdline_arg, _1, i));
}
d.def_stack_word("$# ", std::bind(interpret_const, _1, n));
d.def_ctx_word("$() ", interpret_get_cmdline_arg);
}
std::pair<td::RefInt256, td::RefInt256> numeric_value_ext(std::string s, bool allow_frac = true) {

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
#include "Dictionary.h"
@ -33,7 +33,7 @@ struct Quit {
struct SkipToEof {};
void init_words_common(Dictionary& dictionary);
void init_words_vm(Dictionary& dictionary);
void init_words_vm(Dictionary& dictionary, bool debug_enabled = false);
void init_words_ton(Dictionary& dictionary);
void import_cmdline_args(Dictionary& d, std::string arg0, int n, const char* const argv[]);

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 "func.h"
@ -138,7 +138,7 @@ void VarDescr::show(std::ostream& os, const char* name) const {
}
void VarDescr::set_const(long long value) {
return set_const(td::RefInt256{true, value});
return set_const(td::make_refint(value));
}
void VarDescr::set_const(td::RefInt256 value) {
@ -169,7 +169,7 @@ void VarDescr::set_const(td::RefInt256 value) {
}
void VarDescr::set_const_nan() {
set_const(td::RefInt256{true});
set_const(td::make_refint());
}
void VarDescr::operator|=(const VarDescr& y) {
@ -323,6 +323,20 @@ void Op::show(std::ostream& os, const std::vector<TmpVar>& vars, std::string pfx
show_var_list(os, right, vars);
os << std::endl;
break;
case _Tuple:
os << pfx << dis << "MKTUPLE ";
show_var_list(os, left, vars);
os << " := ";
show_var_list(os, right, vars);
os << std::endl;
break;
case _UnTuple:
os << pfx << dis << "UNTUPLE ";
show_var_list(os, left, vars);
os << " := ";
show_var_list(os, right, vars);
os << std::endl;
break;
case _IntConst:
os << pfx << dis << "CONST ";
show_var_list(os, left, vars);
@ -343,6 +357,12 @@ void Op::show(std::ostream& os, const std::vector<TmpVar>& vars, std::string pfx
show_var_list(os, left, vars);
os << " := " << (fun_ref ? fun_ref->name() : "(null)") << std::endl;
break;
case _SetGlob:
os << pfx << dis << "SETGLOB ";
os << (fun_ref ? fun_ref->name() : "(null)") << " := ";
show_var_list(os, right, vars);
os << std::endl;
break;
case _Repeat:
os << pfx << dis << "REPEAT ";
show_var_list(os, left, vars);

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 "func.h"
@ -29,6 +29,7 @@ namespace funC {
void CodeBlob::simplify_var_types() {
for (TmpVar& var : vars) {
TypeExpr::remove_indirect(var.v_type);
var.v_type->recompute_width();
}
}
@ -354,7 +355,9 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
case _IntConst:
case _GlobVar:
case _Call:
case _CallInd: {
case _CallInd:
case _Tuple:
case _UnTuple: {
// left = EXEC right;
if (!next_var_info.count_used(left) && is_pure()) {
// all variables in `left` are not needed
@ -365,6 +368,13 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
}
return std_compute_used_vars();
}
case _SetGlob: {
// GLOB = right
if (right.empty() && edit) {
disable();
}
return std_compute_used_vars(right.empty());
}
case _Let: {
// left = right
std::size_t cnt = next_var_info.count_used(left);
@ -431,26 +441,25 @@ bool Op::compute_used_vars(const CodeBlob& code, bool edit) {
}
case _While: {
// while (block0 || left) block1;
// ... { block0 left block1 } block0 left next
VarDescrList after_cond_first{next_var_info};
after_cond_first += left;
code.compute_used_code_vars(block0, after_cond_first, false);
VarDescrList new_var_info{block0->var_info};
// ... block0 left { block1 block0 left } next
VarDescrList new_var_info{next_var_info};
bool changes = false;
do {
code.compute_used_code_vars(block1, block0->var_info, changes);
VarDescrList after_cond{block1->var_info};
VarDescrList after_cond{new_var_info};
after_cond += left;
code.compute_used_code_vars(block0, after_cond, changes);
code.compute_used_code_vars(block1, block0->var_info, changes);
std::size_t n = new_var_info.size();
new_var_info += block0->var_info;
new_var_info += block1->var_info;
new_var_info.clear_last();
if (changes) {
break;
}
changes = (new_var_info.size() == n);
} while (changes <= edit);
return set_var_info(std::move(new_var_info));
new_var_info += left;
code.compute_used_code_vars(block0, new_var_info, edit);
return set_var_info(block0->var_info);
}
case _Until: {
// until (block0 || left);
@ -532,8 +541,11 @@ bool prune_unreachable(std::unique_ptr<Op>& ops) {
switch (op.cl) {
case Op::_IntConst:
case Op::_GlobVar:
case Op::_SetGlob:
case Op::_Call:
case Op::_CallInd:
case Op::_Tuple:
case Op::_UnTuple:
case Op::_Import:
reach = true;
break;
@ -695,7 +707,6 @@ VarDescrList Op::fwd_analyze(VarDescrList values) {
values.add_newval(left[0]).set_const(int_const);
break;
}
case _GlobVar:
case _Call: {
prepare_args(values);
auto func = dynamic_cast<const SymValAsmFunc*>(fun_ref->value);
@ -718,12 +729,17 @@ VarDescrList Op::fwd_analyze(VarDescrList values) {
}
break;
}
case _Tuple:
case _UnTuple:
case _GlobVar:
case _CallInd: {
for (var_idx_t i : left) {
values.add_newval(i);
}
break;
}
case _SetGlob:
break;
case _Let: {
std::vector<VarDescr> old_val;
assert(left.size() == right.size());
@ -833,6 +849,9 @@ bool Op::mark_noreturn() {
case _Import:
case _IntConst:
case _Let:
case _Tuple:
case _UnTuple:
case _SetGlob:
case _GlobVar:
case _CallInd:
case _Call:

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 "parser/srcread.h"
#include "func.h"
@ -121,12 +121,49 @@ AsmOp AsmOp::BlkDrop(int a) {
return AsmOp::Custom(os.str(), a, 0);
}
AsmOp AsmOp::BlkDrop2(int a, int b) {
if (!b) {
return BlkDrop(a);
}
std::ostringstream os;
os << a << " " << b << " BLKDROP2";
return AsmOp::Custom(os.str(), a + b, b);
}
AsmOp AsmOp::BlkReverse(int a, int b) {
std::ostringstream os;
os << a << " " << b << " REVERSE";
return AsmOp::Custom(os.str(), a + b, a + b);
}
AsmOp AsmOp::Tuple(int a) {
switch (a) {
case 1:
return AsmOp::Custom("SINGLE", 1, 1);
case 2:
return AsmOp::Custom("PAIR", 2, 1);
case 3:
return AsmOp::Custom("TRIPLE", 3, 1);
}
std::ostringstream os;
os << a << " TUPLE";
return AsmOp::Custom(os.str(), a, 1);
}
AsmOp AsmOp::UnTuple(int a) {
switch (a) {
case 1:
return AsmOp::Custom("UNSINGLE", 1, 1);
case 2:
return AsmOp::Custom("UNPAIR", 1, 2);
case 3:
return AsmOp::Custom("UNTRIPLE", 1, 3);
}
std::ostringstream os;
os << a << " UNTUPLE";
return AsmOp::Custom(os.str(), 1, a);
}
AsmOp AsmOp::IntConst(td::RefInt256 x) {
if (x->signed_fits_bits(8)) {
return AsmOp::Const(dec_string(std::move(x)) + " PUSHINT");
@ -325,6 +362,8 @@ bool apply_op(StackTransform& trans, const AsmOp& op) {
return trans.apply_pop(op.a);
case AsmOp::a_const:
return !op.a && op.b == 1 && trans.apply_push_newconst();
case AsmOp::a_custom:
return op.is_gconst() && trans.apply_push_newconst();
default:
return false;
}

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 "func.h"
@ -27,8 +27,8 @@ using namespace std::literals::string_literals;
*
*/
int glob_func_cnt, undef_func_cnt;
std::vector<SymDef*> glob_func;
int glob_func_cnt, undef_func_cnt, glob_var_cnt;
std::vector<SymDef*> glob_func, glob_vars;
SymDef* predefine_builtin_func(std::string name, TypeExpr* func_type) {
sym_idx_t name_idx = sym::symbols.lookup(name, 1);
@ -44,30 +44,49 @@ SymDef* predefine_builtin_func(std::string name, TypeExpr* func_type) {
}
template <typename T>
void define_builtin_func(std::string name, TypeExpr* func_type, const T& func, bool impure = false) {
SymDef* define_builtin_func(std::string name, TypeExpr* func_type, const T& func, bool impure = false) {
SymDef* def = predefine_builtin_func(name, func_type);
def->value = new SymValAsmFunc{func_type, func, impure};
return def;
}
template <typename T>
void define_builtin_func(std::string name, TypeExpr* func_type, const T& func, std::initializer_list<int> arg_order,
std::initializer_list<int> ret_order = {}, bool impure = false) {
SymDef* define_builtin_func(std::string name, TypeExpr* func_type, const T& func, std::initializer_list<int> arg_order,
std::initializer_list<int> ret_order = {}, bool impure = false) {
SymDef* def = predefine_builtin_func(name, func_type);
def->value = new SymValAsmFunc{func_type, func, arg_order, ret_order, impure};
return def;
}
void define_builtin_func(std::string name, TypeExpr* func_type, const AsmOp& macro,
std::initializer_list<int> arg_order, std::initializer_list<int> ret_order = {},
bool impure = false) {
SymDef* define_builtin_func(std::string name, TypeExpr* func_type, const AsmOp& macro,
std::initializer_list<int> arg_order, std::initializer_list<int> ret_order = {},
bool impure = false) {
SymDef* def = predefine_builtin_func(name, func_type);
def->value = new SymValAsmFunc{func_type, make_simple_compile(macro), arg_order, ret_order, impure};
return def;
}
bool SymValAsmFunc::compile(AsmOpList& dest, std::vector<VarDescr>& in, std::vector<VarDescr>& out) const {
SymDef* force_autoapply(SymDef* def) {
if (def) {
auto val = dynamic_cast<SymVal*>(def->value);
if (val) {
val->auto_apply = true;
}
}
return def;
}
template <typename... Args>
SymDef* define_builtin_const(std::string name, TypeExpr* const_type, Args&&... args) {
return force_autoapply(
define_builtin_func(name, TypeExpr::new_map(TypeExpr::new_unit(), const_type), std::forward<Args>(args)...));
}
bool SymValAsmFunc::compile(AsmOpList& dest, std::vector<VarDescr>& out, std::vector<VarDescr>& in) const {
if (simple_compile) {
return dest.append(simple_compile(in, out));
return dest.append(simple_compile(out, in));
} else if (ext_compile) {
return ext_compile(dest, in, out);
return ext_compile(dest, out, in);
} else {
return false;
}
@ -317,6 +336,12 @@ AsmOp exec_arg_op(std::string op, td::RefInt256 arg, int args, int retv) {
return AsmOp::Custom(os.str(), args, retv);
}
AsmOp exec_arg2_op(std::string op, long long imm1, long long imm2, int args, int retv) {
std::ostringstream os;
os << imm1 << ' ' << imm2 << ' ' << op;
return AsmOp::Custom(os.str(), args, retv);
}
AsmOp push_const(td::RefInt256 x) {
return AsmOp::IntConst(std::move(x));
}
@ -603,7 +628,7 @@ AsmOp compile_mod(std::vector<VarDescr>& res, std::vector<VarDescr>& args, int r
if ((*y.int_const == 1 || *y.int_const == -1) && x.always_finite()) {
x.unused();
y.unused();
r.set_const(td::RefInt256{true, 0});
r.set_const(td::zero_refint());
return push_const(r.int_const);
}
int k = is_pos_pow2(y.int_const);
@ -740,7 +765,7 @@ AsmOp compile_cond_throw(std::vector<VarDescr>& res, std::vector<VarDescr>& args
x.unused();
return skip_cond ? exec_arg_op("THROW", x.int_const, 0, 0) : exec_arg_op("THROW"s + suff, x.int_const, 1, 0);
} else {
return skip_cond ? exec_op("THROWANY", 1, 0) : exec_arg_op("THROWANY"s + suff, 2, 0);
return skip_cond ? exec_op("THROWANY", 1, 0) : exec_op("THROWANY"s + suff, 2, 0);
}
}
@ -918,11 +943,11 @@ void define_builtins() {
define_builtin_func("_<=_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 6));
define_builtin_func("_>=_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 3));
define_builtin_func("_<=>_", arith_bin_op, std::bind(compile_cmp_int, _1, _2, 7));
define_builtin_func("true", Int, /* AsmOp::Const("TRUE") */ std::bind(compile_bool_const, _1, _2, true));
define_builtin_func("false", Int, /* AsmOp::Const("FALSE") */ std::bind(compile_bool_const, _1, _2, false));
define_builtin_const("true", Int, /* AsmOp::Const("TRUE") */ std::bind(compile_bool_const, _1, _2, true));
define_builtin_const("false", Int, /* AsmOp::Const("FALSE") */ std::bind(compile_bool_const, _1, _2, false));
// define_builtin_func("null", Null, AsmOp::Const("PUSHNULL"));
define_builtin_func("nil", Tuple, AsmOp::Const("PUSHNULL"));
define_builtin_func("Nil", Tuple, AsmOp::Const("NIL"));
define_builtin_const("nil", Tuple, AsmOp::Const("PUSHNULL"));
define_builtin_const("Nil", Tuple, AsmOp::Const("NIL"));
define_builtin_func("null?", TypeExpr::new_forall({X}, TypeExpr::new_map(X, Int)), compile_is_null);
define_builtin_func("throw", impure_un_op, compile_throw, true);
define_builtin_func("throw_if", impure_bin_op, std::bind(compile_cond_throw, _1, _2, true), true);
@ -949,7 +974,7 @@ void define_builtins() {
define_builtin_func("~touch2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(XY, TypeExpr::new_tensor({XY, Unit}))),
AsmOp::Nop());
define_builtin_func("~dump", TypeExpr::new_forall({X}, TypeExpr::new_map(X, TypeExpr::new_tensor({X, Unit}))),
AsmOp::Custom("s0 DUMP", 1, 1));
AsmOp::Custom("s0 DUMP", 1, 1), true);
define_builtin_func("run_method0", TypeExpr::new_map(Int, Unit),
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true);
define_builtin_func("run_method1", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)),

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 "func.h"
@ -84,7 +84,9 @@ void Stack::forget_const() {
void Stack::issue_pop(int i) {
validate(i);
o << AsmOp::Pop(i);
if (output_enabled()) {
o << AsmOp::Pop(i);
}
at(i) = get(0);
s.pop_back();
modified();
@ -92,7 +94,9 @@ void Stack::issue_pop(int i) {
void Stack::issue_push(int i) {
validate(i);
o << AsmOp::Push(i);
if (output_enabled()) {
o << AsmOp::Push(i);
}
s.push_back(get(i));
modified();
}
@ -101,7 +105,9 @@ void Stack::issue_xchg(int i, int j) {
validate(i);
validate(j);
if (i != j && get(i) != get(j)) {
o << AsmOp::Xchg(i, j);
if (output_enabled()) {
o << AsmOp::Xchg(i, j);
}
std::swap(at(i), at(j));
modified();
}
@ -183,6 +189,10 @@ void Stack::enforce_state(const StackLayout& req_stack) {
if (i < depth() && s[i].first == x) {
continue;
}
while (depth() > 0 && std::find(req_stack.cbegin(), req_stack.cend(), get(0).first) == req_stack.cend()) {
// current TOS entry is unused in req_stack, drop it
issue_pop(0);
}
int j = find(x);
if (j >= depth() - i) {
issue_push(j);
@ -292,27 +302,61 @@ bool Op::generate_code_step(Stack& stack) {
}
return true;
}
case _GlobVar: {
assert(left.size() == 1);
auto p = next_var_info[left[0]];
if (!p || p->is_unused() || disabled()) {
case _GlobVar:
if (dynamic_cast<const SymValGlobVar*>(fun_ref->value)) {
bool used = false;
for (auto i : left) {
auto p = next_var_info[i];
if (p && !p->is_unused()) {
used = true;
}
}
if (!used || disabled()) {
return true;
}
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
stack.o << AsmOp::Custom(name + " GETGLOB", 0, 1);
if (left.size() != 1) {
assert(left.size() <= 15);
stack.o << AsmOp::UnTuple((int)left.size());
}
for (auto i : left) {
stack.push_new_var(i);
}
return true;
} else {
assert(left.size() == 1);
auto p = next_var_info[left[0]];
if (!p || p->is_unused() || disabled()) {
return true;
}
stack.o << "CONT:<{";
stack.o.indent();
auto func = dynamic_cast<SymValAsmFunc*>(fun_ref->value);
if (func) {
// TODO: create and compile a true lambda instead of this (so that arg_order and ret_order would work correctly)
std::vector<VarDescr> args0, res;
TypeExpr::remove_indirect(func->sym_type);
assert(func->get_type()->is_map());
auto wr = func->get_type()->args.at(0)->get_width();
auto wl = func->get_type()->args.at(1)->get_width();
assert(wl >= 0 && wr >= 0);
for (int i = 0; i < wl; i++) {
res.emplace_back(0);
}
for (int i = 0; i < wr; i++) {
args0.emplace_back(0);
}
func->compile(stack.o, res, args0); // compile res := f (args0)
} else {
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size());
}
stack.o.undent();
stack.o << "}>";
stack.push_new_var(left.at(0));
return true;
}
auto func = dynamic_cast<const SymValAsmFunc*>(fun_ref->value);
if (func) {
std::vector<VarDescr> res;
res.reserve(left.size());
for (var_idx_t i : left) {
res.emplace_back(i);
}
func->compile(stack.o, res, args); // compile res := f (args)
} else {
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size());
}
stack.push_new_var(left[0]);
return true;
}
case _Let: {
assert(left.size() == right.size());
int i = 0;
@ -352,6 +396,32 @@ bool Op::generate_code_step(Stack& stack) {
}
return true;
}
case _Tuple:
case _UnTuple: {
if (disabled()) {
return true;
}
std::vector<bool> last;
for (var_idx_t x : right) {
last.push_back(var_info[x] && var_info[x]->is_last());
}
stack.rearrange_top(right, std::move(last));
stack.opt_show();
int k = (int)stack.depth() - (int)right.size();
assert(k >= 0);
if (cl == _Tuple) {
stack.o << AsmOp::Tuple((int)right.size());
assert(left.size() == 1);
} else {
stack.o << AsmOp::UnTuple((int)left.size());
assert(right.size() == 1);
}
stack.s.resize(k);
for (int i = 0; i < (int)left.size(); i++) {
stack.push_new_var(left.at(i));
}
return true;
}
case _Call:
case _CallInd: {
if (disabled()) {
@ -395,7 +465,9 @@ bool Op::generate_code_step(Stack& stack) {
assert(stack.s[k + i].first == right1[i]);
}
if (cl == _CallInd) {
stack.o << exec_arg_op("CALLARGS", (int)right.size() - 1, (int)right.size(), (int)left.size());
// TODO: replace with exec_arg2_op()
stack.o << exec_arg2_op("CALLXARGS", (int)right.size() - 1, (int)left.size(), (int)right.size(),
(int)left.size());
} else {
auto func = dynamic_cast<const SymValAsmFunc*>(fun_ref->value);
if (func) {
@ -420,6 +492,32 @@ bool Op::generate_code_step(Stack& stack) {
}
return true;
}
case _SetGlob: {
assert(fun_ref && dynamic_cast<const SymValGlobVar*>(fun_ref->value));
std::vector<bool> last;
for (var_idx_t x : right) {
last.push_back(var_info[x] && var_info[x]->is_last());
}
stack.rearrange_top(right, std::move(last));
stack.opt_show();
int k = (int)stack.depth() - (int)right.size();
assert(k >= 0);
for (int i = 0; i < (int)right.size(); i++) {
if (stack.s[k + i].first != right[i]) {
std::cerr << stack.o;
}
assert(stack.s[k + i].first == right[i]);
}
if (right.size() > 1) {
stack.o << AsmOp::Tuple((int)right.size());
}
if (!right.empty()) {
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
stack.o << AsmOp::Custom(name + " SETGLOB", 1, 0);
}
stack.s.resize(k);
return true;
}
case _If: {
if (block0->is_empty() && block1->is_empty()) {
return true;
@ -448,7 +546,9 @@ bool Op::generate_code_step(Stack& stack) {
}
stack.o << "IF:<{";
stack.o.indent();
Stack stack_copy{stack};
Stack stack_copy{stack}, stack_target{stack};
stack_target.disable_output();
stack_target.drop_vars_except(next->var_info);
block0->generate_code_all(stack_copy);
stack_copy.drop_vars_except(var_info);
stack_copy.opt_show();
@ -457,7 +557,8 @@ bool Op::generate_code_step(Stack& stack) {
stack.o << "}>";
return true;
}
stack_copy.drop_vars_except(next->var_info);
// stack_copy.drop_vars_except(next->var_info);
stack_copy.enforce_state(stack_target.vars());
stack_copy.opt_show();
if (stack_copy.vars() == stack.vars()) {
stack.o.undent();
@ -487,7 +588,9 @@ bool Op::generate_code_step(Stack& stack) {
}
stack.o << "IFNOT:<{";
stack.o.indent();
Stack stack_copy{stack};
Stack stack_copy{stack}, stack_target{stack};
stack_target.disable_output();
stack_target.drop_vars_except(next->var_info);
block1->generate_code_all(stack_copy);
stack_copy.drop_vars_except(var_info);
stack_copy.opt_show();
@ -497,7 +600,8 @@ bool Op::generate_code_step(Stack& stack) {
stack.merge_const(stack_copy);
return true;
}
stack_copy.drop_vars_except(next->var_info);
// stack_copy.drop_vars_except(next->var_info);
stack_copy.enforce_state(stack_target.vars());
stack_copy.opt_show();
if (stack_copy.vars() == stack.vars()) {
stack.o.undent();

View File

@ -130,6 +130,11 @@ int generate_output() {
*outs << func_val->method_id << " DECLMETHOD " << name << "\n";
}
}
for (SymDef* gvar_sym : glob_vars) {
assert(dynamic_cast<SymValGlobVar*>(gvar_sym->value));
std::string name = sym::symbols.get_name(gvar_sym->sym_idx);
*outs << std::string(indent * 2, ' ') << "DECLGLOBVAR " << name << "\n";
}
int errors = 0;
for (SymDef* func_sym : glob_func) {
try {

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
#include <vector>
@ -36,7 +36,7 @@ namespace funC {
extern int verbosity;
extern bool op_rewrite_comments;
constexpr int optimize_depth = 12;
constexpr int optimize_depth = 20;
enum Keyword {
_Eof = -1,
@ -97,9 +97,11 @@ enum Keyword {
_Forall,
_Asm,
_Impure,
_Global,
_Extern,
_Inline,
_InlineRef,
_AutoApply,
_MethodId,
_Operator,
_Infix,
@ -133,7 +135,7 @@ class IdSc {
*/
struct TypeExpr {
enum te_type { te_Unknown, te_Var, te_Indirect, te_Atomic, te_Tensor, te_Map, te_Type, te_ForAll } constr;
enum te_type { te_Unknown, te_Var, te_Indirect, te_Atomic, te_Tensor, te_Tuple, te_Map, te_Type, te_ForAll } constr;
enum {
_Int = Keyword::_Int,
_Cell = Keyword::_Cell,
@ -159,6 +161,9 @@ struct TypeExpr {
: constr(_constr), value((int)list.size()), args(std::move(list)) {
compute_width();
}
TypeExpr(te_type _constr, TypeExpr* elem0) : constr(_constr), value(1), args{elem0} {
compute_width();
}
TypeExpr(te_type _constr, TypeExpr* elem0, std::vector<TypeExpr*> list)
: constr(_constr), value((int)list.size() + 1), args{elem0} {
args.insert(args.end(), list.begin(), list.end());
@ -181,6 +186,12 @@ struct TypeExpr {
bool is_var() const {
return constr == te_Var;
}
bool is_map() const {
return constr == te_Map;
}
bool is_tuple() const {
return constr == te_Tuple;
}
bool has_fixed_width() const {
return minw == maxw;
}
@ -222,6 +233,15 @@ struct TypeExpr {
static TypeExpr* new_tensor(TypeExpr* te1, TypeExpr* te2, TypeExpr* te3) {
return new_tensor({te1, te2, te3});
}
static TypeExpr* new_tuple(TypeExpr* arg0) {
return new TypeExpr{te_Tuple, arg0};
}
static TypeExpr* new_tuple(std::vector<TypeExpr*> list, bool red = false) {
return new_tuple(new_tensor(std::move(list), red));
}
static TypeExpr* new_tuple(std::initializer_list<TypeExpr*> list) {
return new_tuple(new_tensor(std::move(list)));
}
static TypeExpr* new_var() {
return new TypeExpr{te_Var, --type_vars, 1};
}
@ -498,8 +518,11 @@ struct Op {
_Let,
_IntConst,
_GlobVar,
_SetGlob,
_Import,
_Return,
_Tuple,
_UnTuple,
_If,
_While,
_Until,
@ -694,6 +717,7 @@ struct SymVal : sym::SymValBase {
TypeExpr* sym_type;
td::RefInt256 method_id;
bool impure;
bool auto_apply{false};
short flags; // +1 = inline, +2 = inline_ref
SymVal(int _type, int _idx, TypeExpr* _stype = nullptr, bool _impure = false)
: sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure), flags(0) {
@ -745,8 +769,20 @@ struct SymValType : sym::SymValBase {
}
};
extern int glob_func_cnt, undef_func_cnt;
extern std::vector<SymDef*> glob_func;
struct SymValGlobVar : sym::SymValBase {
TypeExpr* sym_type;
int out_idx{0};
SymValGlobVar(int val, TypeExpr* gvtype, int oidx = 0)
: sym::SymValBase(_GlobVar, val), sym_type(gvtype), out_idx(oidx) {
}
~SymValGlobVar() override = default;
TypeExpr* get_type() const {
return sym_type;
}
};
extern int glob_func_cnt, undef_func_cnt, glob_var_cnt;
extern std::vector<SymDef*> glob_func, glob_vars;
/*
*
@ -771,10 +807,12 @@ struct Expr {
_Apply,
_VarApply,
_TypeApply,
_Tuple,
_MkTuple,
_Tensor,
_Const,
_Var,
_Glob,
_GlobVar,
_Letop,
_LetFirst,
_Hole,
@ -824,6 +862,12 @@ struct Expr {
bool is_type() const {
return flags & _IsType;
}
bool is_type_apply() const {
return cls == _TypeApply;
}
bool is_mktuple() const {
return cls == _MkTuple;
}
void chk_rvalue(const Lexem& lem) const;
void chk_lvalue(const Lexem& lem) const;
void chk_type(const Lexem& lem) const;
@ -836,7 +880,8 @@ struct Expr {
}
int define_new_vars(CodeBlob& code);
int predefine_vars();
std::vector<var_idx_t> pre_compile(CodeBlob& code) const;
std::vector<var_idx_t> pre_compile(CodeBlob& code, bool lval = false) const;
static std::vector<var_idx_t> pre_compile_let(CodeBlob& code, Expr* lhs, Expr* rhs, const SrcLocation& here);
var_idx_t new_tmp(CodeBlob& code) const;
std::vector<var_idx_t> new_tmp_vect(CodeBlob& code) const {
return {new_tmp(code)};
@ -860,6 +905,7 @@ struct AsmOp {
int t{a_none};
int indent{0};
int a, b, c;
bool gconst{false};
std::string op;
struct SReg {
int idx;
@ -878,6 +924,7 @@ struct AsmOp {
AsmOp(int _t, int _a, int _b) : t(_t), a(_a), b(_b) {
}
AsmOp(int _t, int _a, int _b, std::string _op) : t(_t), a(_a), b(_b), op(std::move(_op)) {
compute_gconst();
}
AsmOp(int _t, int _a, int _b, int _c) : t(_t), a(_a), b(_b), c(_c) {
}
@ -886,6 +933,9 @@ struct AsmOp {
void out(std::ostream& os) const;
void out_indent_nl(std::ostream& os, bool no_nl = false) const;
std::string to_string() const;
void compute_gconst() {
gconst = (is_custom() && (op == "PUSHNULL" || op == "NEWC" || op == "NEWB" || op == "TRUE" || op == "FALSE"));
}
bool is_nop() const {
return t == a_none && op.empty();
}
@ -925,6 +975,9 @@ struct AsmOp {
*y = b;
return is_xchg();
}
bool is_xchg_short() const {
return is_xchg() && (a <= 1 || b <= 1);
}
bool is_swap() const {
return is_xchg(0, 1);
}
@ -932,7 +985,7 @@ struct AsmOp {
return t == a_const && !a && b == 1;
}
bool is_gconst() const {
return (t == a_const || t == a_custom) && !a && b == 1;
return !a && b == 1 && (t == a_const || gconst);
}
static AsmOp Nop() {
return AsmOp(a_none);
@ -985,6 +1038,7 @@ struct AsmOp {
static AsmOp BlkSwap(int a, int b);
static AsmOp BlkPush(int a, int b);
static AsmOp BlkDrop(int a);
static AsmOp BlkDrop2(int a, int b);
static AsmOp BlkReverse(int a, int b);
static AsmOp make_stk2(int a, int b, const char* str, int delta);
static AsmOp make_stk3(int a, int b, int c, const char* str, int delta);
@ -1005,6 +1059,8 @@ struct AsmOp {
return AsmOp(a_custom, args, retv, custom_op);
}
static AsmOp Parse(std::string custom_op, int args, int retv = 1);
static AsmOp Tuple(int a);
static AsmOp UnTuple(int a);
};
inline std::ostream& operator<<(std::ostream& os, const AsmOp& op) {
@ -1155,6 +1211,7 @@ struct StackTransform {
bool apply_push(int i);
bool apply_pop(int i = 0);
bool apply_push_newconst();
bool apply_blkpop(int k);
bool apply(const StackTransform& other); // this = this * other
bool preapply(const StackTransform& other); // this = other * this
// c := a * b
@ -1211,12 +1268,22 @@ struct StackTransform {
}
bool is_xchg(int i, int j) const;
bool is_xchg(int* i, int* j) const;
bool is_xchg_xchg(int i, int j, int k, int l) const;
bool is_xchg_xchg(int* i, int* j, int* k, int* l) const;
bool is_push(int i) const;
bool is_push(int* i) const;
bool is_pop(int i) const;
bool is_pop(int* i) const;
bool is_pop_pop(int i, int j) const;
bool is_pop_pop(int* i, int* j) const;
bool is_rot() const;
bool is_rotrev() const;
bool is_push_rot(int i) const;
bool is_push_rot(int* i) const;
bool is_push_rotrev(int i) const;
bool is_push_rotrev(int* i) const;
bool is_push_xchg(int i, int j, int k) const;
bool is_push_xchg(int* i, int* j, int* k) const;
bool is_xchg2(int i, int j) const;
bool is_xchg2(int* i, int* j) const;
bool is_xcpu(int i, int j) const;
@ -1241,11 +1308,23 @@ struct StackTransform {
bool is_blkpush(int i, int j) const;
bool is_blkpush(int* i, int* j) const;
bool is_blkdrop(int* i) const;
bool is_blkdrop2(int i, int j) const;
bool is_blkdrop2(int* i, int* j) const;
bool is_reverse(int i, int j) const;
bool is_reverse(int* i, int* j) const;
bool is_nip_seq(int i, int j = 0) const;
bool is_nip_seq(int* i) const;
bool is_nip_seq(int* i, int* j) const;
bool is_pop_blkdrop(int i, int k) const;
bool is_pop_blkdrop(int* i, int* k) const;
bool is_2pop_blkdrop(int i, int j, int k) const;
bool is_2pop_blkdrop(int* i, int* j, int* k) const;
bool is_const_rot(int c) const;
bool is_const_rot(int* c) const;
bool is_const_pop(int c, int i) const;
bool is_const_pop(int* c, int* i) const;
bool is_push_const(int i, int c) const;
bool is_push_const(int* i, int* c) const;
void show(std::ostream& os, int mode = 0) const;
@ -1282,11 +1361,12 @@ struct Optimizer {
AsmOpCons* op_cons_[n];
int offs_[n];
StackTransform tr_[n];
int mode_{0};
Optimizer() {
}
Optimizer(bool debug) : debug_(debug) {
Optimizer(bool debug, int mode = 0) : debug_(debug), mode_(mode) {
}
Optimizer(AsmOpConsList code, bool debug = false) : Optimizer(debug) {
Optimizer(AsmOpConsList code, bool debug = false, int mode = 0) : Optimizer(debug, mode) {
set_code(std::move(code));
}
void set_code(AsmOpConsList code_);
@ -1302,19 +1382,28 @@ struct Optimizer {
void show_head() const;
void show_left() const;
void show_right() const;
bool is_const_push_swap() const;
bool rewrite_const_push_swap();
bool find_const_op(int* op_idx, int cst);
bool is_push_const(int* i, int* c) const;
bool rewrite_push_const(int i, int c);
bool is_const_push_xchgs();
bool rewrite_const_push_xchgs();
bool simple_rewrite(int p, AsmOp&& new_op);
bool simple_rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2);
bool simple_rewrite(AsmOp&& new_op) {
return simple_rewrite(p_, std::move(new_op));
bool is_const_rot(int* c) const;
bool rewrite_const_rot(int c);
bool is_const_pop(int* c, int* i) const;
bool rewrite_const_pop(int c, int i);
bool rewrite(int p, AsmOp&& new_op);
bool rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2);
bool rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3);
bool rewrite(AsmOp&& new_op) {
return rewrite(p_, std::move(new_op));
}
bool simple_rewrite(AsmOp&& new_op1, AsmOp&& new_op2) {
return simple_rewrite(p_, std::move(new_op1), std::move(new_op2));
bool rewrite(AsmOp&& new_op1, AsmOp&& new_op2) {
return rewrite(p_, std::move(new_op1), std::move(new_op2));
}
bool simple_rewrite_nop();
bool rewrite(AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3) {
return rewrite(p_, std::move(new_op1), std::move(new_op2), std::move(new_op3));
}
bool rewrite_nop();
bool is_pred(const std::function<bool(const StackTransform&)>& pred, int min_p = 2);
bool is_same_as(const StackTransform& trans, int min_p = 2);
bool is_rot();
@ -1325,9 +1414,14 @@ struct Optimizer {
bool is_2swap();
bool is_2over();
bool is_xchg(int* i, int* j);
bool is_xchg_xchg(int* i, int* j, int* k, int* l);
bool is_push(int* i);
bool is_pop(int* i);
bool is_pop_pop(int* i, int* j);
bool is_nop();
bool is_push_rot(int* i);
bool is_push_rotrev(int* i);
bool is_push_xchg(int* i, int* j, int* k);
bool is_xchg2(int* i, int* j);
bool is_xcpu(int* i, int* j);
bool is_puxc(int* i, int* j);
@ -1343,19 +1437,22 @@ struct Optimizer {
bool is_blkswap(int* i, int* j);
bool is_blkpush(int* i, int* j);
bool is_blkdrop(int* i);
bool is_blkdrop2(int* i, int* j);
bool is_reverse(int* i, int* j);
bool is_nip_seq(int* i, int* j);
bool is_pop_blkdrop(int* i, int* k);
bool is_2pop_blkdrop(int* i, int* j, int* k);
AsmOpConsList extract_code();
};
AsmOpConsList optimize_code_head(AsmOpConsList op_list);
AsmOpConsList optimize_code(AsmOpConsList op_list);
AsmOpConsList optimize_code_head(AsmOpConsList op_list, int mode = 0);
AsmOpConsList optimize_code(AsmOpConsList op_list, int mode);
void optimize_code(AsmOpList& ops);
struct Stack {
StackLayoutExt s;
AsmOpList& o;
enum { _StkCmt = 1, _CptStkCmt = 2, _DisableOpt = 4, _Shown = 256, _Garbage = -0x10000 };
enum { _StkCmt = 1, _CptStkCmt = 2, _DisableOpt = 4, _DisableOut = 128, _Shown = 256, _Garbage = -0x10000 };
int mode;
Stack(AsmOpList& _o, int _mode = 0) : o(_o), mode(_mode) {
}
@ -1381,6 +1478,15 @@ struct Stack {
var_const_idx_t get(int i) const {
return at(i);
}
bool output_disabled() const {
return mode & _DisableOut;
}
bool output_enabled() const {
return !output_disabled();
}
void disable_output() {
mode |= _DisableOut;
}
StackLayout vars() const;
int find(var_idx_t var, int from = 0) const;
int find(var_idx_t var, int from, int to) const;
@ -1470,7 +1576,7 @@ struct SymValAsmFunc : SymValFunc {
std::initializer_list<int> ret_order = {}, bool impure = false)
: SymValFunc(-1, ft, arg_order, ret_order, impure), ext_compile(std::move(_compile)) {
}
bool compile(AsmOpList& dest, std::vector<VarDescr>& in, std::vector<VarDescr>& out) const;
bool compile(AsmOpList& dest, std::vector<VarDescr>& out, std::vector<VarDescr>& in) const;
};
// defined in builtins.cpp
@ -1478,6 +1584,7 @@ AsmOp exec_arg_op(std::string op, long long arg);
AsmOp exec_arg_op(std::string op, long long arg, int args, int retv = 1);
AsmOp exec_arg_op(std::string op, td::RefInt256 arg);
AsmOp exec_arg_op(std::string op, td::RefInt256 arg, int args, int retv = 1);
AsmOp exec_arg2_op(std::string op, long long imm1, long long imm2, int args, int retv = 1);
AsmOp push_const(td::RefInt256 x);
void define_builtins();

View File

@ -14,10 +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
*/
#include "func.h"
using namespace std::literals::string_literals;
namespace funC {
/*
@ -164,7 +166,8 @@ bool Expr::deduce_type(const Lexem& lem) {
int Expr::define_new_vars(CodeBlob& code) {
switch (cls) {
case _Tuple:
case _Tensor:
case _MkTuple:
case _TypeApply: {
int res = 0;
for (const auto& x : args) {
@ -189,7 +192,8 @@ int Expr::define_new_vars(CodeBlob& code) {
int Expr::predefine_vars() {
switch (cls) {
case _Tuple:
case _Tensor:
case _MkTuple:
case _TypeApply: {
int res = 0;
for (const auto& x : args) {
@ -201,6 +205,7 @@ int Expr::predefine_vars() {
if (!sym) {
assert(val < 0 && here.defined());
sym = sym::define_symbol(~val, false, here);
// std::cerr << "predefining variable " << sym::symbols.get_name(~val) << std::endl;
if (!sym) {
throw src::ParseError{here, std::string{"redefined variable `"} + sym::symbols.get_name(~val) + "`"};
}
@ -216,12 +221,51 @@ var_idx_t Expr::new_tmp(CodeBlob& code) const {
return code.create_tmp_var(e_type, &here);
}
std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
std::vector<var_idx_t> Expr::pre_compile_let(CodeBlob& code, Expr* lhs, Expr* rhs, const SrcLocation& here) {
while (lhs->is_type_apply()) {
lhs = lhs->args.at(0);
}
while (rhs->is_type_apply()) {
rhs = rhs->args.at(0);
}
if (lhs->is_mktuple()) {
if (rhs->is_mktuple()) {
return pre_compile_let(code, lhs->args.at(0), rhs->args.at(0), here);
}
auto right = rhs->pre_compile(code);
TypeExpr::remove_indirect(rhs->e_type);
auto unpacked_type = rhs->e_type->args.at(0);
std::vector<var_idx_t> tmp{code.create_tmp_var(unpacked_type, &rhs->here)};
code.emplace_back(lhs->here, Op::_UnTuple, tmp, std::move(right));
auto tvar = new Expr{_Var};
tvar->set_val(tmp[0]);
tvar->set_location(rhs->here);
tvar->e_type = unpacked_type;
pre_compile_let(code, lhs->args.at(0), tvar, here);
return tmp;
}
auto right = rhs->pre_compile(code);
if (lhs->cls == Expr::_GlobVar) {
assert(lhs->sym);
auto& op = code.emplace_back(here, Op::_SetGlob, std::vector<var_idx_t>{}, right, lhs->sym);
op.flags |= Op::_Impure;
} else {
auto left = lhs->pre_compile(code, true);
code.emplace_back(here, Op::_Let, std::move(left), right);
}
return right;
}
std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, bool lval) const {
if (lval && !(cls == _Tensor || cls == _Var || cls == _Hole || cls == _TypeApply)) {
std::cerr << "lvalue expression constructor is " << cls << std::endl;
throw src::Fatal{"cannot compile lvalue expression with unknown constructor"};
}
switch (cls) {
case _Tuple: {
case _Tensor: {
std::vector<var_idx_t> res;
for (const auto& x : args) {
auto add = x->pre_compile(code);
auto add = x->pre_compile(code, lval);
res.insert(res.end(), add.cbegin(), add.cend());
}
return res;
@ -253,7 +297,7 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
return rvect;
}
case _TypeApply:
return args[0]->pre_compile(code);
return args[0]->pre_compile(code, lval);
case _Var:
case _Hole:
return {val};
@ -282,25 +326,29 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
code.emplace_back(here, Op::_IntConst, rvect, intval);
return rvect;
}
case _Glob: {
case _Glob:
case _GlobVar: {
auto rvect = new_tmp_vect(code);
code.emplace_back(here, Op::_GlobVar, rvect, std::vector<var_idx_t>{}, sym);
return rvect;
}
case _Letop: {
auto right = args[1]->pre_compile(code);
auto left = args[0]->pre_compile(code);
code.emplace_back(here, Op::_Let, std::move(left), right);
return right;
return pre_compile_let(code, args.at(0), args.at(1), here);
}
case _LetFirst: {
auto rvect = new_tmp_vect(code);
auto right = args[1]->pre_compile(code);
auto left = args[0]->pre_compile(code);
auto left = args[0]->pre_compile(code, true);
left.push_back(rvect[0]);
code.emplace_back(here, Op::_Let, std::move(left), std::move(right));
return rvect;
}
case _MkTuple: {
auto left = new_tmp_vect(code);
auto right = args[0]->pre_compile(code);
code.emplace_back(here, Op::_Tuple, left, std::move(right));
return left;
}
case _CondExpr: {
auto cond = args[0]->pre_compile(code);
assert(cond.size() == 1);

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 "func.h"
@ -46,6 +46,8 @@ void define_keywords() {
.add_kw_char(';')
.add_kw_char('(')
.add_kw_char(')')
.add_kw_char('[')
.add_kw_char(']')
.add_kw_char('{')
.add_kw_char('}')
.add_kw_char('=')
@ -113,10 +115,12 @@ void define_keywords() {
.add_keyword("forall", Kw::_Forall);
sym::symbols.add_keyword("extern", Kw::_Extern)
.add_keyword("global", Kw::_Global)
.add_keyword("asm", Kw::_Asm)
.add_keyword("impure", Kw::_Impure)
.add_keyword("inline", Kw::_Inline)
.add_keyword("inline_ref", Kw::_InlineRef)
.add_keyword("auto_apply", Kw::_AutoApply)
.add_keyword("method_id", Kw::_MethodId)
.add_keyword("operator", Kw::_Operator)
.add_keyword("infix", Kw::_Infix)

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 "func.h"
@ -134,18 +134,70 @@ bool Optimizer::say(std::string str) const {
return true;
}
bool Optimizer::is_const_push_swap() const {
return l_ >= 3 && op_[0]->is_gconst() && op_[1]->is_push() && op_[1]->a >= 1 && op_[2]->is_swap();
bool Optimizer::find_const_op(int* op_idx, int cst) {
for (int i = 0; i < l2_; i++) {
if (op_[i]->is_gconst() && tr_[i].get(0) == cst) {
*op_idx = i;
return true;
}
}
return false;
}
bool Optimizer::is_push_const(int* i, int* c) const {
return pb_ >= 3 && pb_ <= l2_ && tr_[pb_ - 1].is_push_const(i, c);
}
// PUSHCONST c ; PUSH s(i+1) ; SWAP -> PUSH s(i) ; PUSHCONST c
bool Optimizer::rewrite_const_push_swap() {
p_ = 3;
bool Optimizer::rewrite_push_const(int i, int c) {
p_ = pb_;
q_ = 2;
int idx = -1;
if (!(p_ >= 2 && find_const_op(&idx, c) && idx < p_)) {
return false;
}
show_left();
oq_[1] = std::move(op_[0]);
oq_[0] = std::move(op_[1]);
(oq_[0]->a)--;
oq_[1] = std::move(op_[idx]);
oq_[0] = std::move(op_[!idx]);
*oq_[0] = AsmOp::Push(i);
show_right();
return true;
}
bool Optimizer::is_const_rot(int* c) const {
return pb_ >= 3 && pb_ <= l2_ && tr_[pb_ - 1].is_const_rot(c);
}
bool Optimizer::rewrite_const_rot(int c) {
p_ = pb_;
q_ = 2;
int idx = -1;
if (!(p_ >= 2 && find_const_op(&idx, c) && idx < p_)) {
return false;
}
show_left();
oq_[0] = std::move(op_[idx]);
oq_[1] = std::move(op_[!idx]);
*oq_[1] = AsmOp::Custom("ROT", 3, 3);
show_right();
return true;
}
bool Optimizer::is_const_pop(int* c, int* i) const {
return pb_ >= 3 && pb_ <= l2_ && tr_[pb_ - 1].is_const_pop(c, i);
}
bool Optimizer::rewrite_const_pop(int c, int i) {
p_ = pb_;
q_ = 2;
int idx = -1;
if (!(p_ >= 2 && find_const_op(&idx, c) && idx < p_)) {
return false;
}
show_left();
oq_[0] = std::move(op_[idx]);
oq_[1] = std::move(op_[!idx]);
*oq_[1] = AsmOp::Pop(i);
show_right();
return true;
}
@ -236,7 +288,7 @@ bool Optimizer::rewrite_const_push_xchgs() {
return true;
}
bool Optimizer::simple_rewrite(int p, AsmOp&& new_op) {
bool Optimizer::rewrite(int p, AsmOp&& new_op) {
assert(p > 0 && p <= l_);
p_ = p;
q_ = 1;
@ -247,7 +299,7 @@ bool Optimizer::simple_rewrite(int p, AsmOp&& new_op) {
return true;
}
bool Optimizer::simple_rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2) {
bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2) {
assert(p > 1 && p <= l_);
p_ = p;
q_ = 2;
@ -260,7 +312,22 @@ bool Optimizer::simple_rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2) {
return true;
}
bool Optimizer::simple_rewrite_nop() {
bool Optimizer::rewrite(int p, AsmOp&& new_op1, AsmOp&& new_op2, AsmOp&& new_op3) {
assert(p > 2 && p <= l_);
p_ = p;
q_ = 3;
show_left();
oq_[0] = std::move(op_[0]);
*oq_[0] = new_op1;
oq_[1] = std::move(op_[1]);
*oq_[1] = new_op2;
oq_[2] = std::move(op_[2]);
*oq_[2] = new_op3;
show_right();
return true;
}
bool Optimizer::rewrite_nop() {
assert(p_ > 0 && p_ <= l_);
q_ = 0;
show_left();
@ -326,6 +393,13 @@ bool Optimizer::is_xchg(int* i, int* j) {
return is_pred([i, j](const auto& t) { return t.is_xchg(i, j) && ((*i < 16 && *j < 16) || (!*i && *j < 256)); });
}
bool Optimizer::is_xchg_xchg(int* i, int* j, int* k, int* l) {
return is_pred([i, j, k, l](const auto& t) {
return t.is_xchg_xchg(i, j, k, l) && (*i < 2 && *j < (*i ? 16 : 256) && *k < 2 && *l < (*k ? 16 : 256));
}) &&
(!(p_ == 2 && op_[0]->is_xchg(*i, *j) && op_[1]->is_xchg(*k, *l)));
}
bool Optimizer::is_push(int* i) {
return is_pred([i](const auto& t) { return t.is_push(i) && *i < 256; });
}
@ -334,6 +408,23 @@ bool Optimizer::is_pop(int* i) {
return is_pred([i](const auto& t) { return t.is_pop(i) && *i < 256; });
}
bool Optimizer::is_pop_pop(int* i, int* j) {
return is_pred([i, j](const auto& t) { return t.is_pop_pop(i, j) && *i < 256 && *j < 256; }, 3);
}
bool Optimizer::is_push_rot(int* i) {
return is_pred([i](const auto& t) { return t.is_push_rot(i) && *i < 16; }, 3);
}
bool Optimizer::is_push_rotrev(int* i) {
return is_pred([i](const auto& t) { return t.is_push_rotrev(i) && *i < 16; }, 3);
}
bool Optimizer::is_push_xchg(int* i, int* j, int* k) {
return is_pred([i, j, k](const auto& t) { return t.is_push_xchg(i, j, k) && *i < 16 && *j < 16 && *k < 16; }) &&
!(p_ == 2 && op_[0]->is_push() && op_[1]->is_xchg());
}
bool Optimizer::is_xchg2(int* i, int* j) {
return is_pred([i, j](const auto& t) { return t.is_xchg2(i, j) && *i < 16 && *j < 16; });
}
@ -367,7 +458,8 @@ bool Optimizer::is_xcpu2(int* i, int* j, int* k) {
}
bool Optimizer::is_puxc2(int* i, int* j, int* k) {
return is_pred([i, j, k](const auto& t) { return t.is_puxc2(i, j, k) && *i < 16 && *j < 15 && *k < 15; });
return is_pred(
[i, j, k](const auto& t) { return t.is_puxc2(i, j, k) && *i < 16 && *j < 15 && *k < 15 && *j + *k != -1; });
}
bool Optimizer::is_puxcpu(int* i, int* j, int* k) {
@ -394,6 +486,10 @@ bool Optimizer::is_blkdrop(int* i) {
return is_pred([i](const auto& t) { return t.is_blkdrop(i) && *i > 0 && *i < 16; });
}
bool Optimizer::is_blkdrop2(int* i, int* j) {
return is_pred([i, j](const auto& t) { return t.is_blkdrop2(i, j) && *i > 0 && *i < 16 && *j > 0 && *j < 16; });
}
bool Optimizer::is_reverse(int* i, int* j) {
return is_pred([i, j](const auto& t) { return t.is_reverse(i, j) && *i >= 2 && *i <= 17 && *j < 16; });
}
@ -402,6 +498,16 @@ bool Optimizer::is_nip_seq(int* i, int* j) {
return is_pred([i, j](const auto& t) { return t.is_nip_seq(i, j) && *i >= 3 && *i <= 15; });
}
bool Optimizer::is_pop_blkdrop(int* i, int* k) {
return is_pred([i, k](const auto& t) { return t.is_pop_blkdrop(i, k) && *i >= *k && *k >= 2 && *k <= 15; }, 3);
}
bool Optimizer::is_2pop_blkdrop(int* i, int* j, int* k) {
return is_pred(
[i, j, k](const auto& t) { return t.is_2pop_blkdrop(i, j, k) && *i >= *k && *j >= *k && *k >= 2 && *k <= 15; },
3);
}
bool Optimizer::compute_stack_transforms() {
StackTransform trans;
for (int i = 0; i < l_; i++) {
@ -448,34 +554,41 @@ bool Optimizer::find_at_least(int pb) {
p_ = q_ = 0;
pb_ = pb;
// show_stack_transforms();
int i = -100, j = -100, k = -100;
return (is_const_push_swap() && 3 >= pb && rewrite_const_push_swap()) || (is_nop() && simple_rewrite_nop()) ||
(is_const_push_xchgs() && rewrite_const_push_xchgs()) ||
(is_xchg(&i, &j) && simple_rewrite(AsmOp::Xchg(i, j))) || (is_push(&i) && simple_rewrite(AsmOp::Push(i))) ||
(is_pop(&i) && simple_rewrite(AsmOp::Pop(i))) || (is_rot() && simple_rewrite(AsmOp::Custom("ROT", 3, 3))) ||
(is_rotrev() && simple_rewrite(AsmOp::Custom("-ROT", 3, 3))) ||
(is_2dup() && simple_rewrite(AsmOp::Custom("2DUP", 2, 4))) ||
(is_2swap() && simple_rewrite(AsmOp::Custom("2SWAP", 2, 4))) ||
(is_2over() && simple_rewrite(AsmOp::Custom("2OVER", 2, 4))) ||
(is_tuck() && simple_rewrite(AsmOp::Custom("TUCK", 2, 3))) ||
(is_2drop() && simple_rewrite(AsmOp::Custom("2DROP", 2, 0))) ||
(is_xchg2(&i, &j) && simple_rewrite(AsmOp::Xchg2(i, j))) ||
(is_xcpu(&i, &j) && simple_rewrite(AsmOp::XcPu(i, j))) ||
(is_puxc(&i, &j) && simple_rewrite(AsmOp::PuXc(i, j))) ||
(is_push2(&i, &j) && simple_rewrite(AsmOp::Push2(i, j))) ||
(is_blkswap(&i, &j) && simple_rewrite(AsmOp::BlkSwap(i, j))) ||
(is_blkpush(&i, &j) && simple_rewrite(AsmOp::BlkPush(i, j))) ||
(is_blkdrop(&i) && simple_rewrite(AsmOp::BlkDrop(i))) ||
(is_reverse(&i, &j) && simple_rewrite(AsmOp::BlkReverse(i, j))) ||
(is_nip_seq(&i, &j) && simple_rewrite(AsmOp::Xchg(i, j), AsmOp::BlkDrop(i))) ||
(is_xchg3(&i, &j, &k) && simple_rewrite(AsmOp::Xchg3(i, j, k))) ||
(is_xc2pu(&i, &j, &k) && simple_rewrite(AsmOp::Xc2Pu(i, j, k))) ||
(is_xcpuxc(&i, &j, &k) && simple_rewrite(AsmOp::XcPuXc(i, j, k))) ||
(is_xcpu2(&i, &j, &k) && simple_rewrite(AsmOp::XcPu2(i, j, k))) ||
(is_puxc2(&i, &j, &k) && simple_rewrite(AsmOp::PuXc2(i, j, k))) ||
(is_puxcpu(&i, &j, &k) && simple_rewrite(AsmOp::PuXcPu(i, j, k))) ||
(is_pu2xc(&i, &j, &k) && simple_rewrite(AsmOp::Pu2Xc(i, j, k))) ||
(is_push3(&i, &j, &k) && simple_rewrite(AsmOp::Push3(i, j, k)));
int i, j, k, l, c;
return (is_push_const(&i, &c) && rewrite_push_const(i, c)) || (is_nop() && rewrite_nop()) ||
(!(mode_ & 1) && is_const_rot(&c) && rewrite_const_rot(c)) ||
(is_const_push_xchgs() && rewrite_const_push_xchgs()) || (is_const_pop(&c, &i) && rewrite_const_pop(c, i)) ||
(is_xchg(&i, &j) && rewrite(AsmOp::Xchg(i, j))) || (is_push(&i) && rewrite(AsmOp::Push(i))) ||
(is_pop(&i) && rewrite(AsmOp::Pop(i))) || (is_pop_pop(&i, &j) && rewrite(AsmOp::Pop(i), AsmOp::Pop(j))) ||
(is_xchg_xchg(&i, &j, &k, &l) && rewrite(AsmOp::Xchg(i, j), AsmOp::Xchg(k, l))) ||
(!(mode_ & 1) &&
((is_rot() && rewrite(AsmOp::Custom("ROT", 3, 3))) || (is_rotrev() && rewrite(AsmOp::Custom("-ROT", 3, 3))) ||
(is_2dup() && rewrite(AsmOp::Custom("2DUP", 2, 4))) ||
(is_2swap() && rewrite(AsmOp::Custom("2SWAP", 2, 4))) ||
(is_2over() && rewrite(AsmOp::Custom("2OVER", 2, 4))) ||
(is_tuck() && rewrite(AsmOp::Custom("TUCK", 2, 3))) ||
(is_2drop() && rewrite(AsmOp::Custom("2DROP", 2, 0))) || (is_xchg2(&i, &j) && rewrite(AsmOp::Xchg2(i, j))) ||
(is_xcpu(&i, &j) && rewrite(AsmOp::XcPu(i, j))) || (is_puxc(&i, &j) && rewrite(AsmOp::PuXc(i, j))) ||
(is_push2(&i, &j) && rewrite(AsmOp::Push2(i, j))) || (is_blkswap(&i, &j) && rewrite(AsmOp::BlkSwap(i, j))) ||
(is_blkpush(&i, &j) && rewrite(AsmOp::BlkPush(i, j))) || (is_blkdrop(&i) && rewrite(AsmOp::BlkDrop(i))) ||
(is_push_rot(&i) && rewrite(AsmOp::Push(i), AsmOp::Custom("ROT"))) ||
(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_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)))) ||
(is_xchg3(&i, &j, &k) && rewrite(AsmOp::Xchg3(i, j, k))) ||
(is_xc2pu(&i, &j, &k) && rewrite(AsmOp::Xc2Pu(i, j, k))) ||
(is_xcpuxc(&i, &j, &k) && rewrite(AsmOp::XcPuXc(i, j, k))) ||
(is_xcpu2(&i, &j, &k) && rewrite(AsmOp::XcPu2(i, j, k))) ||
(is_puxc2(&i, &j, &k) && rewrite(AsmOp::PuXc2(i, j, k))) ||
(is_puxcpu(&i, &j, &k) && rewrite(AsmOp::PuXcPu(i, j, k))) ||
(is_pu2xc(&i, &j, &k) && rewrite(AsmOp::Pu2Xc(i, j, k))) ||
(is_push3(&i, &j, &k) && rewrite(AsmOp::Push3(i, j, k)))));
}
bool Optimizer::find() {
@ -500,17 +613,17 @@ bool Optimizer::optimize() {
return f;
}
AsmOpConsList optimize_code_head(AsmOpConsList op_list) {
Optimizer opt(std::move(op_list), op_rewrite_comments);
AsmOpConsList optimize_code_head(AsmOpConsList op_list, int mode) {
Optimizer opt(std::move(op_list), op_rewrite_comments, mode);
opt.optimize();
return opt.extract_code();
}
AsmOpConsList optimize_code(AsmOpConsList op_list) {
AsmOpConsList optimize_code(AsmOpConsList op_list, int mode) {
std::vector<std::unique_ptr<AsmOp>> v;
while (op_list) {
if (!op_list->car->is_comment()) {
op_list = optimize_code_head(std::move(op_list));
op_list = optimize_code_head(std::move(op_list), mode);
}
if (op_list) {
v.push_back(std::move(op_list->car));
@ -524,11 +637,13 @@ AsmOpConsList optimize_code(AsmOpConsList op_list) {
}
void optimize_code(AsmOpList& ops) {
std::unique_ptr<AsmOpCons> op_list;
AsmOpConsList op_list;
for (auto it = ops.list_.rbegin(); it < ops.list_.rend(); ++it) {
op_list = AsmOpCons::cons(std::make_unique<AsmOp>(std::move(*it)), std::move(op_list));
}
op_list = optimize_code(std::move(op_list));
for (int mode : {1, 1, 1, 1, 0, 0, 0, 0}) {
op_list = optimize_code(std::move(op_list), mode);
}
ops.list_.clear();
while (op_list) {
ops.list_.push_back(std::move(*(op_list->car)));

View File

@ -14,10 +14,11 @@
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 "func.h"
#include "td/utils/crypto.h"
#include "common/refint.h"
#include <fstream>
namespace sym {
@ -99,14 +100,21 @@ TypeExpr* parse_type1(Lexer& lex) {
lex.cur().error_at("`", "` is not a type identifier");
}
}
lex.expect('(');
if (lex.tp() == ')') {
int c;
if (lex.tp() == '[') {
lex.next();
return TypeExpr::new_unit();
c = ']';
} else {
lex.expect('(');
c = ')';
}
if (lex.tp() == c) {
lex.next();
return c == ')' ? TypeExpr::new_unit() : TypeExpr::new_tuple({});
}
auto t1 = parse_type(lex);
if (lex.tp() != ',') {
lex.expect(')');
lex.expect(c);
return t1;
}
std::vector<TypeExpr*> tlist{1, t1};
@ -114,8 +122,8 @@ TypeExpr* parse_type1(Lexer& lex) {
lex.next();
tlist.push_back(parse_type(lex));
}
lex.expect(')');
return TypeExpr::new_tensor(std::move(tlist));
lex.expect(c);
return c == ')' ? TypeExpr::new_tensor(std::move(tlist)) : TypeExpr::new_tuple(std::move(tlist));
}
TypeExpr* parse_type(Lexer& lex) {
@ -174,6 +182,53 @@ FormalArg parse_formal_arg(Lexer& lex, int fa_idx) {
return std::make_tuple(arg_type, new_sym_def, loc);
}
void parse_global_var_decl(Lexer& lex) {
TypeExpr* var_type = 0;
SrcLocation loc = lex.cur().loc;
if (lex.tp() == '_') {
lex.next();
var_type = TypeExpr::new_hole();
loc = lex.cur().loc;
} else if (lex.tp() != _Ident) {
var_type = parse_type(lex);
} else {
auto sym = sym::lookup_symbol(lex.cur().val);
if (sym && dynamic_cast<SymValType*>(sym->value)) {
auto val = dynamic_cast<SymValType*>(sym->value);
lex.next();
var_type = val->get_type();
} else {
var_type = TypeExpr::new_hole();
}
}
if (lex.tp() != _Ident) {
lex.expect(_Ident, "global variable name");
}
loc = lex.cur().loc;
SymDef* sym_def = sym::define_global_symbol(lex.cur().val, false, loc);
if (!sym_def) {
lex.cur().error_at("cannot define global symbol `", "`");
}
if (sym_def->value) {
auto val = dynamic_cast<SymValGlobVar*>(sym_def->value);
if (!val) {
lex.cur().error_at("symbol `", "` cannot be redefined as a global variable");
}
try {
unify(var_type, val->sym_type);
} catch (UnifyError& ue) {
std::ostringstream os;
os << "cannot unify new type " << var_type << " of global variable `" << sym_def->name()
<< "` with its previous type " << val->sym_type << ": " << ue;
lex.cur().error(os.str());
}
} else {
sym_def->value = new SymValGlobVar{glob_var_cnt++, var_type};
glob_vars.push_back(sym_def);
}
lex.next();
}
FormalArgList parse_formal_args(Lexer& lex) {
FormalArgList args;
lex.expect('(', "formal argument list");
@ -205,6 +260,18 @@ TypeExpr* extract_total_arg_type(const FormalArgList& arg_list) {
return TypeExpr::new_tensor(std::move(type_list));
}
void parse_global_var_decls(Lexer& lex) {
lex.expect(_Global);
while (true) {
parse_global_var_decl(lex);
if (lex.tp() != ',') {
break;
}
lex.expect(',');
}
lex.expect(';');
}
SymValCodeFunc* make_new_glob_func(SymDef* func_sym, TypeExpr* func_type, bool impure = false) {
SymValCodeFunc* res = new SymValCodeFunc{glob_func_cnt, func_type, impure};
func_sym->value = res;
@ -239,30 +306,54 @@ bool check_global_func(const Lexem& cur, sym_idx_t func_name = 0) {
}
}
Expr* make_func_apply(Expr* fun, Expr* x) {
Expr* res;
if (fun->cls == Expr::_Glob) {
if (x->cls == Expr::_Tensor) {
res = new Expr{Expr::_Apply, fun->sym, x->args};
} else {
res = new Expr{Expr::_Apply, fun->sym, {x}};
}
res->flags = Expr::_IsRvalue | (fun->flags & Expr::_IsImpure);
} else {
res = new Expr{Expr::_VarApply, {fun, x}};
res->flags = Expr::_IsRvalue;
}
return res;
}
Expr* parse_expr(Lexer& lex, CodeBlob& code, bool nv = false);
// parse ( E { , E } ) | () | id | num | _
// parse ( E { , E } ) | () | [ E { , E } ] | [] | id | num | _
Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
if (lex.tp() == '(') {
if (lex.tp() == '(' || lex.tp() == '[') {
bool tf = (lex.tp() == '[');
int clbr = (tf ? ']' : ')');
SrcLocation loc{lex.cur().loc};
lex.next();
if (lex.tp() == ')') {
if (lex.tp() == clbr) {
lex.next();
Expr* res = new Expr{Expr::_Tuple, {}};
Expr* res = new Expr{Expr::_Tensor, {}};
res->flags = Expr::_IsRvalue;
res->here = loc;
res->e_type = TypeExpr::new_unit();
if (tf) {
res = new Expr{Expr::_MkTuple, {res}};
res->flags = Expr::_IsRvalue;
res->here = loc;
res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type);
}
return res;
}
Expr* res = parse_expr(lex, code, nv);
if (lex.tp() != ',') {
lex.expect(')');
lex.expect(clbr);
return res;
}
std::vector<TypeExpr*> type_list;
type_list.push_back(res->e_type);
int f = res->flags;
res = new Expr{Expr::_Tuple, {res}};
res = new Expr{Expr::_Tensor, {res}};
while (lex.tp() == ',') {
lex.next();
auto x = parse_expr(lex, code, nv);
@ -275,8 +366,14 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
}
res->here = loc;
res->flags = f;
res->e_type = TypeExpr::new_tensor(std::move(type_list));
lex.expect(')');
res->e_type = TypeExpr::new_tensor(std::move(type_list), !tf);
if (tf) {
res = new Expr{Expr::_MkTuple, {res}};
res->flags = f;
res->here = loc;
res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type);
}
lex.expect(clbr);
return res;
}
int t = lex.tp();
@ -306,7 +403,7 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
lex.next();
return res;
}
if (t == _Int || t == _Cell || t == _Slice || t == _Builder || t == _Cont || t == _Type) {
if (t == _Int || t == _Cell || t == _Slice || t == _Builder || t == _Cont || t == _Type || t == _Tuple) {
Expr* res = new Expr{Expr::_Type, lex.cur().loc};
res->flags = Expr::_IsType;
res->e_type = TypeExpr::new_atomic(t);
@ -323,6 +420,16 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
lex.next();
return res;
}
if (sym && dynamic_cast<SymValGlobVar*>(sym->value)) {
auto val = dynamic_cast<SymValGlobVar*>(sym->value);
Expr* res = new Expr{Expr::_GlobVar, lex.cur().loc};
res->e_type = val->get_type();
res->sym = sym;
res->flags = Expr::_IsLvalue | Expr::_IsRvalue | Expr::_IsImpure;
lex.next();
return res;
}
bool auto_apply = false;
Expr* res = new Expr{Expr::_Var, lex.cur().loc};
if (nv) {
res->val = ~lex.cur().val;
@ -344,6 +451,7 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
} else if (val->type == SymVal::_Func) {
res->e_type = val->get_type();
res->cls = Expr::_Glob;
auto_apply = val->auto_apply;
} else if (val->idx < 0) {
lex.cur().error_at("accessing variable `", "` being defined");
} else {
@ -354,6 +462,12 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
// std::cerr << "accessing symbol " << lex.cur().str << " : " << res->e_type << (val->impure ? " (impure)" : " (pure)") << std::endl;
res->flags = Expr::_IsLvalue | Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0);
}
if (auto_apply) {
int impure = res->flags & Expr::_IsImpure;
delete res;
res = new Expr{Expr::_Apply, sym, {}};
res->flags = Expr::_IsRvalue | impure;
}
res->deduce_type(lex.cur());
lex.next();
return res;
@ -362,26 +476,10 @@ Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
return nullptr;
}
Expr* make_func_apply(Expr* fun, Expr* x) {
Expr* res;
if (fun->cls == Expr::_Glob) {
if (x->cls == Expr::_Tuple) {
res = new Expr{Expr::_Apply, fun->sym, x->args};
} else {
res = new Expr{Expr::_Apply, fun->sym, {x}};
}
res->flags = Expr::_IsRvalue | (fun->flags & Expr::_IsImpure);
} else {
res = new Expr{Expr::_VarApply, {fun, x}};
res->flags = Expr::_IsRvalue;
}
return res;
}
// parse E { E }
Expr* parse_expr90(Lexer& lex, CodeBlob& code, bool nv) {
Expr* res = parse_expr100(lex, code, nv);
while (lex.tp() == '(' || (lex.tp() == _Ident && !is_special_ident(lex.cur().val))) {
while (lex.tp() == '(' || lex.tp() == '[' || (lex.tp() == _Ident && !is_special_ident(lex.cur().val))) {
if (res->is_type()) {
Expr* x = parse_expr100(lex, code, true);
x->chk_lvalue(lex.cur()); // chk_lrvalue() ?
@ -446,7 +544,7 @@ Expr* parse_expr80(Lexer& lex, CodeBlob& code, bool nv) {
lex.next();
auto x = parse_expr100(lex, code, false);
x->chk_rvalue(lex.cur());
if (x->cls == Expr::_Tuple) {
if (x->cls == Expr::_Tensor) {
res = new Expr{Expr::_Apply, name, {obj}};
res->args.insert(res->args.end(), x->args.begin(), x->args.end());
} else {
@ -1168,8 +1266,9 @@ void parse_func_def(Lexer& lex) {
}
if (val->method_id.is_null()) {
val->method_id = std::move(method_id);
} else if (val->method_id != method_id) {
lex.cur().error("integer method identifier for `"s + func_name.str + "` changed to a different value");
} else if (td::cmp(val->method_id, method_id) != 0) {
lex.cur().error("integer method identifier for `"s + func_name.str + "` changed from " +
val->method_id->to_dec_string() + " to a different value " + method_id->to_dec_string());
}
}
if (f) {
@ -1191,9 +1290,13 @@ void parse_func_def(Lexer& lex) {
bool parse_source(std::istream* is, const src::FileDescr* fdescr) {
src::SourceReader reader{is, fdescr};
Lexer lex{reader, true};
Lexer lex{reader, true, ";,()[] ~."};
while (lex.tp() != _Eof) {
parse_func_def(lex);
if (lex.tp() == _Global) {
parse_global_var_decls(lex);
} else {
parse_func_def(lex);
}
}
return true;
}

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 "func.h"
@ -334,6 +334,13 @@ bool StackTransform::apply_pop(int i) {
}
}
bool StackTransform::apply_blkpop(int k) {
if (!is_valid() || k < 0) {
return invalidate();
}
return !k || (touch(k - 1) && shift(k));
}
bool StackTransform::equal(const StackTransform &other, bool relaxed) const {
if (!is_valid() || !other.is_valid()) {
return false;
@ -394,6 +401,57 @@ bool StackTransform::is_xchg(int *i, int *j) const {
return true;
}
bool StackTransform::is_xchg_xchg(int i, int j, int k, int l) const {
if (is_valid() && !d && n <= 4 && (i | j | k | l) >= 0) {
StackTransform t;
return t.apply_xchg(i, j) && t.apply_xchg(k, l) && t <= *this;
} else {
return false;
}
}
bool StackTransform::is_xchg_xchg(int *i, int *j, int *k, int *l) const {
if (!is_valid() || d || n > 4 || !dp || !is_permutation()) {
return false;
}
if (!n) {
*i = *j = *k = *l = 0;
return true;
}
if (n <= 2) {
*k = *l = 0;
return is_xchg(i, j);
}
if (n == 3) {
// rotation: a -> b -> c -> a
int a = A[0].first;
int b = A[0].second;
int s = (b == A[2].first ? 2 : 1);
int c = A[s].second;
if (b != A[s].first || c != A[3 - s].first || a != A[3 - s].second) {
return false;
}
// implement as XCHG s(a),s(c) ; XCHG s(a),s(b)
*i = *k = a;
*j = c;
*l = b;
return is_xchg_xchg(*i, *j, *k, *l);
}
*i = A[0].first;
*j = A[0].second;
if (get(*j) != *i) {
return false;
}
for (int s = 1; s < 4; s++) {
if (A[s].first != *j) {
*k = A[s].first;
*l = A[s].second;
return get(*l) == *k && is_xchg_xchg(*i, *j, *k, *l);
}
}
return false;
}
bool StackTransform::is_push(int i) const {
return is_valid() && d == -1 && n == 1 && A[0].first == -1 && A[0].second == i;
}
@ -411,6 +469,7 @@ bool StackTransform::is_push(int *i) const {
// 0 2 3 4 .. = pop1
// 1 0 3 4 .. = pop2
// 1 2 0 4 .. = pop3
// POP s(i) : 1 2 ... i-1 0 i+1 ... ; d=1, n=1, {(i,0)}
bool StackTransform::is_pop(int i) const {
if (!is_valid() || d != 1 || n > 1 || i < 0) {
return false;
@ -436,6 +495,38 @@ bool StackTransform::is_pop(int *i) const {
return false;
}
// POP s(i) ; POP s(j) : 2 ... i-1 0 i+1 ... j 1 j+2 ... ; d=2, n=2, {(i,0),(j+1,1)} if i <> j+1
bool StackTransform::is_pop_pop(int i, int j) const {
if (is_valid() && d == 2 && n <= 2 && i >= 0 && j >= 0) {
StackTransform t;
return t.apply_pop(i) && t.apply_pop(j) && t <= *this;
} else {
return false;
}
}
bool StackTransform::is_pop_pop(int *i, int *j) const {
if (!is_valid() || d != 2 || n > 2) {
return false;
}
if (!n) {
*i = *j = 0; // 2DROP
} else if (n == 2) {
*i = A[0].first - A[0].second;
*j = A[1].first - A[1].second;
if (A[0].second > A[1].second) {
std::swap(*i, *j);
}
} else if (!A[0].second) {
*i = A[0].first;
*j = 0;
} else {
*i = 0;
*j = A[0].first - 1;
}
return is_pop_pop(*i, *j);
}
const StackTransform StackTransform::rot{2, 0, 1, 3};
const StackTransform StackTransform::rot_rev{1, 2, 0, 3};
@ -447,6 +538,53 @@ bool StackTransform::is_rotrev() const {
return equal(rot_rev, true);
}
// PUSH i ; ROT == 1 i 0 2 3
bool StackTransform::is_push_rot(int i) const {
return is_valid() && d == -1 && i >= 0 && is_trivial_after(3) && get(0) == 1 && get(1) == i && get(2) == 0;
}
bool StackTransform::is_push_rot(int *i) const {
return is_valid() && (*i = get(1)) >= 0 && is_push_rot(*i);
}
// PUSH i ; -ROT == 0 1 i 2 3
bool StackTransform::is_push_rotrev(int i) const {
return is_valid() && d == -1 && i >= 0 && is_trivial_after(3) && get(0) == 0 && get(1) == 1 && get(2) == i;
}
bool StackTransform::is_push_rotrev(int *i) const {
return is_valid() && (*i = get(2)) >= 0 && is_push_rotrev(*i);
}
// PUSH s(i) ; XCHG s(j),s(k) --> i 0 1 .. i ..
// PUSH s(i) ; XCHG s(0),s(k) --> k-1 0 1 .. k-2 i k ..
bool StackTransform::is_push_xchg(int i, int j, int k) const {
StackTransform t;
return is_valid() && d == -1 && n <= 3 && t.apply_push(i) && t.apply_xchg(j, k) && t <= *this;
}
bool StackTransform::is_push_xchg(int *i, int *j, int *k) const {
if (!(is_valid() && d == -1 && n <= 3 && n > 0)) {
return false;
}
int s = get(0);
if (s < 0) {
return false;
}
*i = s;
*j = 0;
if (n == 1) {
*k = 0;
} else if (n == 2) {
*k = s + 1;
*i = get(s + 1);
} else {
*j = A[1].first + 1;
*k = A[2].first + 1;
}
return is_push_xchg(*i, *j, *k);
}
// XCHG s1,s(i) ; XCHG s0,s(j)
bool StackTransform::is_xchg2(int i, int j) const {
StackTransform t;
@ -465,10 +603,9 @@ bool StackTransform::is_xchg2(int *i, int *j) const {
if (*i < 0 || *j < 0) {
return false;
}
if (n != 3) {
return is_xchg2(*i, *j);
}
if (*i) {
if (n == 2 && !*i) {
*j = *i; // XCHG s0,s1 = XCHG2 s0,s0
} else if (n == 3 && *i) {
// XCHG2 s(i),s(i) = XCHG s1,s(i) ; XCHG s0,s(i) : 0->1, 1->i
*j = *i;
} // XCHG2 s0,s(i) = XCHG s0,s1 ; XCHG s0,s(i) : 0->i, 1->0
@ -735,6 +872,28 @@ bool StackTransform::is_blkdrop(int *i) const {
return false;
}
// 0 1 .. j-1 j+i j+i+1 ...
bool StackTransform::is_blkdrop2(int i, int j) const {
if (!is_valid() || d != i || i <= 0 || j < 0 || dp < i + j || n != j || !is_trivial_after(j)) {
return false;
}
for (int s = 0; s < j; s++) {
if (get(s) != s) {
return false;
}
}
return true;
}
bool StackTransform::is_blkdrop2(int *i, int *j) const {
if (is_valid() && is_blkdrop2(d, n)) {
*i = d;
*j = n;
return true;
}
return false;
}
// equivalent to i times PUSH s(j)
bool StackTransform::is_blkpush(int *i, int *j) const {
if (!is_valid() || d >= 0) {
@ -800,6 +959,77 @@ bool StackTransform::is_nip_seq(int *i, int *j) const {
}
}
// POP s(i); BLKDROP k (usually for i >= k >= 0)
bool StackTransform::is_pop_blkdrop(int i, int k) const {
StackTransform t;
return is_valid() && d == k + 1 && t.apply_pop(i) && t.apply_blkpop(k) && t <= *this;
}
// POP s(i); BLKDROP k == XCHG s0,s(i); BLKDROP k+1 for i >= k >= 0
// k+1 k+2 .. i-1 0 i+1 ..
bool StackTransform::is_pop_blkdrop(int *i, int *k) const {
if (is_valid() && n == 1 && d > 0 && !A[0].second) {
*k = d - 1;
*i = A[0].first;
return is_pop_blkdrop(*i, *k);
} else {
return false;
}
}
// POP s(i); POP s(j); BLKDROP k (usually for i<>j >= k >= 0)
bool StackTransform::is_2pop_blkdrop(int i, int j, int k) const {
StackTransform t;
return is_valid() && d == k + 2 && t.apply_pop(i) && t.apply_pop(j) && t.apply_blkpop(k) && t <= *this;
}
// POP s(i); POP s(j); BLKDROP k == XCHG s0,s(i); XCHG s1,s(j+1); BLKDROP k+2 (usually for i<>j >= k >= 2)
// k+2 k+3 .. i-1 0 i+1 ... j 1 j+2 ...
bool StackTransform::is_2pop_blkdrop(int *i, int *j, int *k) const {
if (is_valid() && n == 2 && d >= 2 && A[0].second + A[1].second == 1) {
*k = d - 2;
int t = (A[0].second > 0);
*i = A[t].first;
*j = A[1 - t].first - 1;
return is_2pop_blkdrop(*i, *j, *k);
} else {
return false;
}
}
// PUSHCONST c ; ROT == 1 -1000 0 2 3
bool StackTransform::is_const_rot(int c) const {
return is_valid() && d == -1 && is_trivial_after(3) && get(0) == 1 && c <= c_start && get(1) == c && get(2) == 0;
}
bool StackTransform::is_const_rot(int *c) const {
return is_valid() && (*c = get(1)) <= c_start && is_const_rot(*c);
}
// PUSHCONST c ; POP s(i) == 0 1 .. i-1 -1000 i+1 ...
bool StackTransform::is_const_pop(int c, int i) const {
return is_valid() && !d && n == 1 && i > 0 && c <= c_start && get(i - 1) == c;
}
bool StackTransform::is_const_pop(int *c, int *i) const {
if (is_valid() && !d && n == 1 && A[0].second <= c_start) {
*i = A[0].first + 1;
*c = A[0].second;
return is_const_pop(*c, *i);
} else {
return false;
}
}
// PUSH i ; PUSHCONST c == c i 0 1 2 ...
bool StackTransform::is_push_const(int i, int c) const {
return is_valid() && d == -2 && c <= c_start && i >= 0 && is_trivial_after(2) && get(0) == c && get(1) == i;
}
bool StackTransform::is_push_const(int *i, int *c) const {
return is_valid() && d == -2 && n == 2 && is_push_const(*i = get(1), *c = get(0));
}
void StackTransform::show(std::ostream &os, int mode) const {
if (!is_valid()) {
os << "<invalid>";

View File

@ -0,0 +1,9 @@
_ f(int a, int x) {
int y = 0;
int z = 0;
while ((y = x * x) > a) {
x -= 1;
z = 1;
}
return (y, z);
}

View File

@ -0,0 +1,28 @@
_ f(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, int cnt, cell credits, cell vdict, int elect) {
return (ds, elect, credits);
}
_ g(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, int cnt, cell credits, int elect) {
return (ds, elect, credits);
}
_ h(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, cell credits, int elect) {
return (ds, elect, credits);
}
_ h2(slice ds, int total_weight, int elect_at, cell frozen, int total_stakes, cell credits, int elect) {
return (ds, credits, elect);
}
_ h3(int pubkey, int adnl_addr, int stake, int tot_weight, tuple vinfo) {
return (pubkey, tot_weight, stake, vinfo);
}
_ z(int a, int b) {
return (b, 0, a);
}
_ z2(int a, int b) {
return (0, a, b);
}

View File

@ -0,0 +1,20 @@
var calc_root(m) {
int base = 1;
repeat(70) { base *= 10; }
var (a, b, c) = (1, 0, - m);
var (p1, q1, p2, q2) = (1, 0, 0, 1);
do {
int k = -1;
var (a1, b1, c1) = (0, 0, 0);
do {
k += 1;
(a1, b1, c1) = (a, b, c);
c += b;
c += b += a;
} until (c > 0);
(a, b, c) = (- c1, - b1, - a1);
(p1, q1) = (k * p1 + q1, p1);
(p2, q2) = (k * p2 + q2, p2);
} until (p1 > base);
return (p1, q1, p2, q2);
}

View File

@ -0,0 +1,20 @@
var twice(f, x) {
return f (f x);
}
_ sqr(x) {
return x * x;
}
var main(x) {
var f = sqr;
return twice(f, x) * f(x);
}
var pow6(x) {
return twice(sqr, x) * sqr(x);
}
_ q() {
return false;
}

View File

@ -0,0 +1,37 @@
global int x, y, z;
global (cell, slice) y;
global ((int, int) -> int) op;
_ get() {
var t = z + 1;
return x;
}
_ pre_next() {
return x + 1;
}
() init() impure {
;; global x;
x = 0;
}
int next() impure {
;; global x;
return x += 1;
}
_ set_y(x, w) {
y = (w, x);
}
_ get_y() impure {
return y;
}
int main(int c) {
init();
c += next();
return c + pre_next();
}

View File

@ -0,0 +1,10 @@
global ((int, int) -> int) op;
int check_assoc(int a, int b, int c) {
return op(op(a, b), c) == op(a, op(b, c));
}
int main() {
op = _+_;
return check_assoc(2, 3, 9);
}

View File

@ -0,0 +1,7 @@
_ check_assoc(op, a, b, c) {
return op(op(a, b), c) == op(a, op(b, c));
}
int main() {
return check_assoc(_+_, 2, 3, 9);
}

View File

@ -0,0 +1,22 @@
int check_signatures(msg_hash, signatures, signers, bitmask_size) impure {
var bitmask = 0;
var id = -1;
do {
(id, var signature, var f) = signatures.udict_get_next?(32, id);
if (f){
var sig = signature.preload_bits(512);
var public_key = -1;
do {
(public_key, var cs, var _found) = signers.udict_get_next?(256, public_key);
if (_found){
if (check_signature(msg_hash, sig, public_key)){
var signer_index = cs~load_uint(bitmask_size);
bitmask = bitmask | (1 << (signer_index - 1));
}
}
} until (~ _found);
;; signature~touch();
}
} until (~ f);
return bitmask;
}

View File

@ -0,0 +1,8 @@
_ g(s) {
var (z, t) = (17, s);
while (z > 0) {
t = s;
z -= 1;
}
return ~ t;
}

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 "func.h"
@ -47,6 +47,12 @@ void TypeExpr::compute_width() {
maxw = w_inf;
}
break;
case te_Tuple:
minw = maxw = 1;
for (TypeExpr* arg : args) {
arg->compute_width();
}
break;
case te_Indirect:
minw = args[0]->minw;
maxw = args[0]->maxw;
@ -84,6 +90,14 @@ bool TypeExpr::recompute_width() {
}
return true;
}
case te_Tuple: {
for (TypeExpr* arg : args) {
if (arg->minw > 1 || arg->maxw < 1 || arg->minw > arg->maxw) {
return false;
}
}
return true;
}
default:
return false;
}
@ -233,7 +247,9 @@ std::ostream& TypeExpr::print(std::ostream& os, int lex_level) {
}
}
case te_Tensor: {
os << "(";
if (lex_level > -127) {
os << "(";
}
auto c = args.size();
if (c) {
for (const auto& x : args) {
@ -243,7 +259,25 @@ std::ostream& TypeExpr::print(std::ostream& os, int lex_level) {
}
}
}
return os << ")";
if (lex_level > -127) {
os << ")";
}
return os;
}
case te_Tuple: {
os << "[";
auto c = args.size();
if (c == 1 && args[0]->constr == te_Tensor) {
args[0]->print(os, -127);
} else if (c) {
for (const auto& x : args) {
x->print(os);
if (--c) {
os << ", ";
}
}
}
return os << "]";
}
case te_Map: {
assert(args.size() == 2);
@ -312,7 +346,7 @@ void check_update_widths(TypeExpr* te1, TypeExpr* te2) {
check_width_compat(te1, te2);
te1->minw = te2->minw = std::max(te1->minw, te2->minw);
te1->maxw = te2->maxw = std::min(te1->maxw, te2->maxw);
assert(te1->minw <= te2->minw);
assert(te1->minw <= te1->maxw);
}
void unify(TypeExpr*& te1, TypeExpr*& te2) {

View File

@ -32,7 +32,7 @@ namespace sym {
typedef int var_idx_t;
struct SymValBase {
enum { _Param, _Var, _Func, _Typename };
enum { _Param, _Var, _Func, _Typename, _GlobVar };
int type;
int idx;
SymValBase(int _type, int _idx) : type(_type), idx(_idx) {

View File

@ -242,3 +242,7 @@ dictnew constant special-dict
register_smc
Masterchain swap 6 .Addr cr
} : create-wallet0
{ dup tlb-type-lookup { nip } { "unknown TLB type " swap $+ abort } cond } : $>tlb
{ bl word $>tlb 1 'nop } ::_ tlb:
{ <b swap vmcont, b> <s tlb:VmCont tlb-dump-as } : vmcont.

View File

@ -0,0 +1,115 @@
#!/usr/bin/fift -s
"TonUtil.fif" include
"GetOpt.fif" include
{ show-options-help 1 halt } : usage
"dns-msg-body.boc" =: savefile
begin-options
" <auto-dns-addr> [-o<savefile-boc>] (add|update|prolong) <subdomain> <expire-in-sec> ... " +cr +tab
+"Creates the internal message body containing a request to automatic DNS smart contract <auto-dns-addr> created by new-auto-dns.fif, "
+"to be sent later with a suitable payment from a wallet to <auto-dns-addr>, and saves it into <savefile-boc> ('" savefile $+ +"' by default). "
+"The operation to be performed is one of" +cr +tab
+"add <subdomain> <expire-in-sec> { owner <smc-addr> | cat <cat-id> (smc <smc-addr> | next <next-resolver-smc-addr> | adnl <adnl-addr> | text <string>) }" +cr +tab
+"update <subdomain> <expire-in-sec> { owner <smc-addr> | cat <cat-id> (smc <smc-addr> | next <next-resolver-smc-addr> | adnl <adnl-addr> | text <string>) }" +cr +tab
+"prolong <subdomain> <expire-in-sec>"
disable-digit-options generic-help-setopt
"o" "--output" { =: savefile } short-long-option-arg
"Sets output file for generated initialization message ('" savefile $+ +"' by default)" option-help
"h" "--help" { usage } short-long-option
"Shows a help message" option-help
parse-options
$# 4 < ' usage if
4 :$1..n
$1 true parse-load-address =: bounce 2=: dest-addr
$2 dup =: main-op-name atom =: main-op
$3 dup =: subdomain $len 127 > abort"subdomain name too long"
$4 parse-int dup 30 1<< < { now + } if =: expire-at
{ $* @ dup null? { second $@ ! } { drop } cond } : @skip
{ $* @ null? } : @end?
{ $* @ uncons $* ! } : @next
{ @next drop } 4 times
main-op dup `add eq? over `update eq? or swap `prolong eq? or
{ "unknown main operation '" main-op-name $+ +"'; one of 'add', 'update' or 'prolong' expected" abort } ifnot
main-op `prolong eq? not =: need-params
$# 4 > need-params <> abort"extra parameters, or no parameters for chosen main operation"
variable Values dictnew Values !
// ( i c -- )
{ over 0= abort"category cannot be zero"
<b swap ref, swap Values @ 16 b>idict!+ not abort"duplicate category id"
Values !
} : register-value
{ @end? abort"category number expected" @next (number) 1 <> abort"category must be integer"
dup 16 fits not abort"category does not fit into 16 bit integer"
dup 0= abort"category must be non-zero"
} : parse-cat-num
{ @end? abort"smart contract address expected"
@next false parse-load-address drop
} : cl-parse-smc-addr
{ @end? abort"adnl address expected"
@next parse-adnl-addr
} : cl-parse-adnl-addr
{ <b x{9fd3} s, -rot Addr, 0 8 u, b> } : serialize-smc-addr
{ <b x{ba93} s, -rot Addr, b> } : serialize-next-resolver
{ <b x{ad01} s, swap 256 u, 0 8 u, b> } : serialize-adnl-addr
{ <b x{1eda01} s, over $len 8 u, swap $, b> } : serialize-text
{ @end? abort"subdomain record value expected" @next
dup "smc" $= { drop cl-parse-smc-addr serialize-smc-addr } {
dup "next" $= { drop cl-parse-smc-addr serialize-next-resolver } {
dup "adnl" $= { drop cl-parse-adnl-addr serialize-adnl-addr } {
dup "text" $= { drop @next serialize-text } {
"unknown record type "' swap $+ +"'" abort
} cond } cond } cond } cond
} : parse-value
{ @next dup "owner" $= { drop -2 cl-parse-smc-addr serialize-smc-addr } {
dup "cat" $= { drop parse-cat-num parse-value } {
"unknown action '" swap $+ +"'" abort
} cond } cond
register-value
} : parse-action
{ { @end? not } { parse-action } while } : parse-actions
parse-actions
// ( S -- S1 .. Sn n )
{ 1 swap { dup "." $pos dup 0>= } { $| 1 $| nip rot 1+ swap } while drop swap
} : split-by-dots
// ( S -- s )
{ dup $len dup 0= abort"subdomain cannot be empty" 126 > abort"subdomain too long"
dup 0 chr $pos 1+ abort"subdomain contains null characters"
split-by-dots <b { // ... S b
swap dup $len 0= abort"empty subdomain component" $, 0 8 u,
} rot times b> <s
} : subdomain>s
main-op ( _( `add 0x72656764 ) _( `update 0x75706464 ) _( `prolong 0x70726f6c ) )
assq-val not abort"unknown main operation"
=: op-id
."Automatic DNS smart contract address = " dest-addr 2dup .addr cr 6 .Addr cr
."Action: " main-op .l subdomain type space expire-at . cr
."Operation code: 0x" op-id 8 0X. cr
."Value: "
Values @ dup null? { drop ."(none)" } { <s csr. } cond cr
<b op-id 32 u, expire-at 32 u, Values @ dict, b> =: actions-builder
// create an internal message
now 32 << actions-builder hashu 32 1<<1- and + =: query_id
<b op-id 32 i, query_id 64 u,
subdomain subdomain>s tuck sbits 8 / 7 i, swap s,
main-op `prolong eq? { Values @ ref, } ifnot
expire-at 32 u, b>
dup ."Internal message body is: " <s csr. cr
2 boc+>B dup Bx. cr
."Query_id is " query_id dup . ."= 0x" X. cr
savefile tuck B>file
."(Saved to file " type .")" cr

View File

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

View File

@ -13,12 +13,13 @@ PROGRAM{
DECLPROC perform_action
DECLPROC get_validator_descr
DECLPROC unpack_validator_descr
DECLPROC create_new_entry
DECLPROC unpack_suggestion
DECLPROC pack_suggestion
DECLPROC new_proposal
DECLPROC unpack_proposal
DECLPROC pack_proposal
DECLPROC register_vote
DECLPROC recv_external
DECLPROC run_ticktock
85143 DECLMETHOD seqno
set_conf_param PROC:<{
// index value
c4 PUSH // index value _3
@ -38,24 +39,16 @@ PROGRAM{
//
c4 PUSH // _1
CTOS // cs
LDREF // _6 cs
32 LDU // _6 _8 cs
256 LDU // cfg_dict stored_seqno public_key cs
DUP // cfg_dict stored_seqno public_key cs cs
SEMPTY // cfg_dict stored_seqno public_key cs _15
IF:<{ // cfg_dict stored_seqno public_key cs
NEWDICT // cfg_dict stored_seqno public_key cs _16
}>ELSE<{ // cfg_dict stored_seqno public_key cs
LDDICT // cfg_dict stored_seqno public_key _16 cs
SWAP // cfg_dict stored_seqno public_key cs _16
}> // cfg_dict stored_seqno public_key cs vote_dict
SWAP // cfg_dict stored_seqno public_key vote_dict cs
LDREF // _4 cs
32 LDU // _4 _6 cs
256 LDU // _4 _6 _9 cs
LDDICT // res res res res cs
ENDS
}>
store_data PROC:<{
// cfg_dict stored_seqno public_key vote_dict
NEWC // cfg_dict stored_seqno public_key vote_dict _4
s1 s4 XCHG // vote_dict stored_seqno public_key cfg_dict _4
s0 s3 XCHG
NEWC // vote_dict stored_seqno public_key cfg_dict _4
STREF // vote_dict stored_seqno public_key _5
s1 s2 XCHG // vote_dict public_key stored_seqno _5
32 STU // vote_dict public_key _7
@ -69,19 +62,17 @@ PROGRAM{
CTOS // cs
8 LDU // _4 cs
SWAP // cs _4
-17 ADDCONST // cs _8
-2 PUSHINT // cs _8 _9=-2
AND // cs _10
9 THROWIF
18 EQINT // cs _8
9 THROWIFNOT
32 LDU // utime_since cs
32 LDU // utime_since utime_until cs
16 LDU // utime_since utime_until total cs
16 LDU // utime_since utime_until total _44 _43
16 LDU // utime_since utime_until total _42 _41
DROP // utime_since utime_until total main
DUP // utime_since utime_until total main main
0 GTINT // utime_since utime_until total main _30
0 GTINT // utime_since utime_until total main _28
9 THROWIFNOT
GEQ // utime_since utime_until _33
GEQ // utime_since utime_until _31
9 THROWIFNOT
}>
send_answer PROC:<{
@ -139,8 +130,7 @@ PROGRAM{
1314280276 PUSHINT // s_addr src_addr tag query_id in_msg tag _29=1314280276
EQUAL // s_addr src_addr tag query_id in_msg _30
IFJMP:<{ // s_addr src_addr tag query_id in_msg
s2 POP // s_addr src_addr in_msg query_id
SWAP // s_addr src_addr query_id in_msg
1 2 BLKDROP2 // s_addr src_addr query_id in_msg
LDREF // s_addr src_addr query_id vset in_msg
ENDS
1 PUSHINT // s_addr src_addr query_id vset _36=1
@ -162,17 +152,17 @@ PROGRAM{
s2 POP // s_addr vset query_id
OVER // s_addr vset query_id vset
check_validator_set CALLDICT // s_addr vset query_id t_since t_until
OVER
NOW // s_addr vset query_id t_since t_until t_since t
NOW // s_addr vset query_id t_since t_until t
s2 s(-1) PUXC // s_addr vset query_id t_since t_until t_since t
GREATER // s_addr vset query_id t_since t_until _53
s0 s2 XCHG // s_addr vset query_id _53 t_until t_since
GREATER // s_addr vset query_id _53 _54
AND // s_addr vset query_id ok
}>ELSE<{
s0 s2 XCHG // s_addr vset query_id ok
}>
s0 s2 XCHG // s_addr ok query_id vset
}> // s_addr ok query_id vset
s0 s2 XCHG // s_addr vset query_id ok
IFJMP:<{ // s_addr vset query_id
36 PUSHINT // s_addr vset query_id _56=36
36 PUSHINT
ROT // s_addr query_id _56=36 vset
set_conf_param CALLDICT
4000730955 PUSHINT // s_addr query_id _58=4000730955
@ -248,23 +238,24 @@ PROGRAM{
SETCODE
c3 PUSH // cfg_dict public_key new_code cs old_code
s0 s2 XCHG // cfg_dict public_key old_code cs new_code
CTOS // cfg_dict public_key old_code cs _25
BLESS // cfg_dict public_key old_code cs _26
c3 POP
SWAP // cfg_dict public_key cs old_code
after_code_upgrade CALLDICT
0 THROW
}> // cfg_dict public_key action cs
OVER
1348619041 PUSHINT // cfg_dict public_key action cs action _29=1348619041
EQUAL // cfg_dict public_key action cs _30
1348619041 PUSHINT // cfg_dict public_key action cs action _31=1348619041
EQUAL // cfg_dict public_key action cs _32
IFJMP:<{ // cfg_dict public_key action cs
NIP
NIP // cfg_dict cs
2 1 BLKDROP2 // cfg_dict cs
256 LDU // cfg_dict public_key cs
ENDS
}> // cfg_dict public_key action cs
OVER
1313074949 PUSHINT // cfg_dict public_key action cs action _35=1313074949
EQUAL // cfg_dict public_key action cs _36
1313074949 PUSHINT // cfg_dict public_key action cs action _37=1313074949
EQUAL // cfg_dict public_key action cs _38
IFJMP:<{ // cfg_dict public_key action cs
NIP // cfg_dict public_key cs
change_elector_code CALLDICT
@ -281,18 +272,26 @@ PROGRAM{
IFJMP:<{ // idx vset
2DROP //
PUSHNULL // _5
0 PUSHINT // _5 _6=0
}> // idx vset
CTOS // idx cs
104 PUSHINT // idx cs _17
8 LDU // idx _10 cs
SWAP // idx cs _10
18 EQINT // idx cs _14
40 THROWIFNOT
96 PUSHINT // idx cs _23
SDSKIPFIRST // idx cs
NEWC // idx cs _20
SWAP // idx _20 cs
STSLICER // idx _21
ENDC // idx dict
16 PUSHINT // idx dict _25=16
64 LDU // idx total_weight cs
NEWC // idx total_weight cs _30
SWAP // idx total_weight _30 cs
STSLICER // idx total_weight _31
ENDC // idx total_weight dict
s1 s2 XCHG
16 PUSHINT // total_weight idx dict _35=16
DICTUGET
NULLSWAPIFNOT // _27 _28
DROP // value
NULLSWAPIFNOT // total_weight _41 _42
DROP // total_weight value
SWAP // value total_weight
}>
unpack_validator_descr PROC:<{
// cs
@ -312,30 +311,22 @@ PROGRAM{
64 LDU // _18 _31 _30
DROP // _18 _21
}>
create_new_entry PROC:<{
new_proposal PROC:<{
// cs
0 PUSHINT // cs _1=0
DUP // cs _1=0 _2=0
FALSE // cs _1=0 _2=0 _3
NEWC // cs _1=0 _2=0 _3 _4
1 STI // cs _1=0 _2=0 _6
64 STU // cs _1=0 _8
256 STU // cs _10
SWAP // _10 cs
STSLICER // _11
ENDC // _12
CTOS // _13
PUSHNULL // cs _1
0 PUSHINT // cs _1 _2=0
s0 s1 s2 XCPUXC // _1 _2=0 _3=0 cs
}>
unpack_suggestion PROC:<{
unpack_proposal PROC:<{
// cs
LDDICT // _1 cs
64 LDU // _1 _3 cs
256 LDU // _1 _3 _6 cs
}>
pack_suggestion PROC:<{
pack_proposal PROC:<{
// voters sum_weight vset_id body
NEWC // voters sum_weight vset_id body _4
s1 s4 XCHG // body sum_weight vset_id voters _4
s0 s3 XCHG
NEWC // body sum_weight vset_id voters _4
STDICT // body sum_weight vset_id _5
s1 s2 XCHG // body vset_id sum_weight _5
64 STU // body vset_id _7
@ -344,31 +335,87 @@ PROGRAM{
STSLICER // _10
}>
register_vote PROC:<{
// vote_dict action cs idx weight
2DROP // vote_dict action cs
SWAP
1 PUSHINT // vote_dict cs action _9=1
AND // vote_dict cs _10
IF:<{ // vote_dict cs
DUP // vote_dict cs cs
HASHSU // vote_dict cs _11
NIP // vote_dict hash
OVER
8 PUSHPOW2 // vote_dict hash vote_dict _13=256
// vote_dict action cs idx weight total_weight cur_vset_id
s0 s5 XCHG
1 PUSHINT // vote_dict cur_vset_id cs idx weight total_weight action _13=1
AND // vote_dict cur_vset_id cs idx weight total_weight _14
IF:<{ // vote_dict cur_vset_id cs idx weight total_weight
s3 PUSH // vote_dict cur_vset_id cs idx weight total_weight cs
HASHSU // vote_dict cur_vset_id cs idx weight total_weight hash
s0 s6 PUSH2
8 PUSHPOW2 // vote_dict cur_vset_id cs idx weight total_weight hash hash vote_dict _16=256
DICTUGET
NULLSWAPIFNOT // vote_dict _23 _24
NIP // vote_dict found?
IFNOT:<{ // vote_dict
}> // vote_dict
}>ELSE<{ // vote_dict cs
256 PLDU // vote_dict hash
OVER
8 PUSHPOW2 // vote_dict hash vote_dict _19=256
NULLSWAPIFNOT // vote_dict cur_vset_id cs idx weight total_weight hash entry found?
}>ELSE<{ // vote_dict cur_vset_id cs idx weight total_weight
s3 PUSH // vote_dict cur_vset_id cs idx weight total_weight cs
256 PLDU // vote_dict cur_vset_id cs idx weight total_weight hash
s0 s6 PUSH2
8 PUSHPOW2 // vote_dict cur_vset_id cs idx weight total_weight hash hash vote_dict _20=256
DICTUGET
NULLSWAPIFNOT // vote_dict _25 _26
NIP // vote_dict found?
NULLSWAPIFNOT // vote_dict cur_vset_id cs idx weight total_weight hash entry found?
DUP // vote_dict cur_vset_id cs idx weight total_weight hash entry found? found?
42 THROWIFNOT
}>
IF:<{ // vote_dict cur_vset_id cs idx weight total_weight hash entry
s5 POP // vote_dict cur_vset_id entry idx weight total_weight hash
s0 s4 XCHG // vote_dict cur_vset_id hash idx weight total_weight entry
unpack_proposal INLINECALLDICT // vote_dict cur_vset_id hash idx weight total_weight _65 _66 _67 _68
}>ELSE<{ // vote_dict cur_vset_id cs idx weight total_weight hash entry
DROP // vote_dict cur_vset_id cs idx weight total_weight hash
PUSHNULL // vote_dict cur_vset_id cs idx weight total_weight hash _30
s5 s0 s6 XC2PU
0 PUSHINT
s0 s1 s3 XCHG3 // vote_dict cur_vset_id hash idx weight total_weight _65 _66 _67 _68
}> // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight vset_id body
s1 s8 XCPU // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body vset_id cur_vset_id
NEQ // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body _32
IF:<{ // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body
NIP
PUSHNULL
s2 POP
0 PUSHINT
SWAP // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight=0 body
}> // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body
s5 s2 PUSH2
16 PUSHINT // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body idx voters _37=16
DICTUGET
NULLSWAPIFNOT // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body _73 _74
NIP // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body found?
IFJMP:<{ // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body
8 BLKDROP // vote_dict
PUSHNULL // vote_dict _60
}> // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body
32 PUSHINT // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body _40=32
NEWC // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body _40=32 _41
NOW // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body _40=32 _41 _42
STUX // vote_dict cur_vset_id hash idx weight total_weight voters sum_weight body _43
s0 s6 s3 XCHG3
16 PUSHINT // vote_dict cur_vset_id hash body weight total_weight sum_weight _43 idx voters _44=16
DICTUSETB // vote_dict cur_vset_id hash body weight total_weight sum_weight voters
s0 s3 XCHG // vote_dict cur_vset_id hash body voters total_weight sum_weight weight
ADD // vote_dict cur_vset_id hash body voters total_weight sum_weight
DUP // vote_dict cur_vset_id hash body voters total_weight sum_weight sum_weight
3 MULCONST // vote_dict cur_vset_id hash body voters total_weight sum_weight _48
s0 s2 XCHG // vote_dict cur_vset_id hash body voters _48 sum_weight total_weight
1 LSHIFT# // vote_dict cur_vset_id hash body voters _48 sum_weight _50
s1 s2 XCHG // vote_dict cur_vset_id hash body voters sum_weight _48 _50
GREATER // vote_dict cur_vset_id hash body voters sum_weight _51
IFJMP:<{ // vote_dict cur_vset_id hash body voters sum_weight
2DROP
1 2 BLKDROP2
s0 s2 XCHG
8 PUSHPOW2 // body hash vote_dict _53=256
DICTUDEL // body _75 _76
DROP // body vote_dict
SWAP // vote_dict body
}> // vote_dict cur_vset_id hash body voters sum_weight
2SWAP
s1 s4 XCHG // vote_dict hash voters sum_weight cur_vset_id body
pack_proposal INLINECALLDICT // vote_dict hash _56
s0 s2 XCHG
8 PUSHPOW2 // _56 hash vote_dict _57=256
DICTUSETB // vote_dict
PUSHNULL // vote_dict _59
}>
recv_external PROC:<{
// in_msg
@ -395,29 +442,49 @@ PROGRAM{
s0 s3 XCHG // signature in_msg action vote_dict public_key cfg_dict stored_seqno cs
16 LDU // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs
OVER // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs idx
get_validator_descr INLINECALLDICT // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs vdescr
unpack_validator_descr INLINECALLDICT // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs val_pubkey weight
s0 s9 XCHG // signature weight action vote_dict public_key cfg_dict stored_seqno idx cs val_pubkey in_msg
HASHSU // signature weight action vote_dict public_key cfg_dict stored_seqno idx cs val_pubkey _44
s0 s10 s10 XCHG3 // cs weight action vote_dict public_key cfg_dict stored_seqno idx _44 signature val_pubkey
CHKSIGNU // cs weight action vote_dict public_key cfg_dict stored_seqno idx _45
get_validator_descr INLINECALLDICT // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs vdescr total_weight
SWAP // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs total_weight vdescr
unpack_validator_descr INLINECALLDICT // signature in_msg action vote_dict public_key cfg_dict stored_seqno idx cs total_weight val_pubkey weight
s0 s10 XCHG // signature weight action vote_dict public_key cfg_dict stored_seqno idx cs total_weight val_pubkey in_msg
HASHSU // signature weight action vote_dict public_key cfg_dict stored_seqno idx cs total_weight val_pubkey _45
s0 s11 s11 XCHG3 // total_weight weight action vote_dict public_key cfg_dict stored_seqno idx cs _45 signature val_pubkey
CHKSIGNU // total_weight weight action vote_dict public_key cfg_dict stored_seqno idx cs _46
34 THROWIFNOT
ACCEPT
SWAP // cs weight action vote_dict public_key cfg_dict idx stored_seqno
INC // cs weight action vote_dict public_key cfg_dict idx stored_seqno
s2 s0 s3 PUSH3
s7 PUSH // cs weight action vote_dict public_key cfg_dict idx stored_seqno cfg_dict stored_seqno public_key vote_dict
s0 s2 XCHG // total_weight weight action vote_dict public_key cfg_dict cs idx stored_seqno
INC // total_weight weight action vote_dict public_key cfg_dict cs idx stored_seqno
s3 s0 s4 PUSH3
s8 PUSH // total_weight weight action vote_dict public_key cfg_dict cs idx stored_seqno cfg_dict stored_seqno public_key vote_dict
store_data INLINECALLDICT
COMMIT
s3 s5 XCHG
s7 s1 s6 XCHG3 // cfg_dict stored_seqno public_key vote_dict action cs idx weight
register_vote CALLDICT // cfg_dict stored_seqno public_key vote_dict
34 PUSHINT // total_weight weight action vote_dict public_key cfg_dict cs idx stored_seqno _54=34
CONFIGOPTPARAM // total_weight weight action vote_dict public_key cfg_dict cs idx stored_seqno _55
HASHCU // total_weight weight action vote_dict public_key cfg_dict cs idx stored_seqno _56
s5 s7 XCHG
s3 s4 XCHG
s2 s3 XCHG
s8 s9 s0 XCHG3 // stored_seqno cfg_dict public_key vote_dict action cs idx weight total_weight _56
register_vote CALLDICT // stored_seqno cfg_dict public_key vote_dict accepted
s3 s4 s2 PUSH3
s4 PUSH // stored_seqno cfg_dict public_key vote_dict accepted cfg_dict stored_seqno public_key vote_dict
store_data INLINECALLDICT
DUP // stored_seqno cfg_dict public_key vote_dict accepted accepted
ISNULL // stored_seqno cfg_dict public_key vote_dict accepted _59
IFNOT:<{ // stored_seqno cfg_dict public_key vote_dict accepted
32 LDU // stored_seqno cfg_dict public_key vote_dict _60 accepted
s3 s4 XCHG
s2 s4 XCHG // stored_seqno vote_dict cfg_dict public_key _60 accepted
perform_action CALLDICT // stored_seqno vote_dict cfg_dict public_key
s3 s0 s3 XCHG3 // cfg_dict stored_seqno public_key vote_dict
store_data INLINECALLDICT
}>ELSE<{
5 BLKDROP //
}>
}> // signature in_msg action vote_dict cs cfg_dict stored_seqno public_key
s0 s6 XCHG // signature public_key action vote_dict cs cfg_dict stored_seqno in_msg
HASHSU // signature public_key action vote_dict cs cfg_dict stored_seqno _55
s0 s7 s6 XC2PU // stored_seqno public_key action vote_dict cs cfg_dict _55 signature public_key
CHKSIGNU // stored_seqno public_key action vote_dict cs cfg_dict _56
HASHSU // signature public_key action vote_dict cs cfg_dict stored_seqno _66
s0 s7 s6 XC2PU // stored_seqno public_key action vote_dict cs cfg_dict _66 signature public_key
CHKSIGNU // stored_seqno public_key action vote_dict cs cfg_dict _67
34 THROWIFNOT
ACCEPT
s0 s5 XCHG // cfg_dict public_key action vote_dict cs stored_seqno
@ -453,16 +520,15 @@ PROGRAM{
IF:<{ // cfg_dict cs kl=32 next_vset ds
8 LDU // cfg_dict cs kl=32 next_vset tag ds
32 PLDU // cfg_dict cs kl=32 next_vset tag since
SWAP // cfg_dict cs kl=32 next_vset since tag
17 EQINT // cfg_dict cs kl=32 next_vset since _26
NOW // cfg_dict cs kl=32 next_vset since _26 _27
s1 s2 XCHG // cfg_dict cs kl=32 next_vset _26 since _27
GEQ // cfg_dict cs kl=32 next_vset _26 _28
NOW // cfg_dict cs kl=32 next_vset tag since _25
LEQ // cfg_dict cs kl=32 next_vset tag _26
SWAP // cfg_dict cs kl=32 next_vset _26 tag
18 EQINT // cfg_dict cs kl=32 next_vset _26 _28
AND // cfg_dict cs kl=32 next_vset _29
IF:<{ // cfg_dict cs kl=32 next_vset
SWAP
34 PUSHINT
s0 s4 s4 XC2PU // kl=32 cs next_vset _32=34 cfg_dict kl=32
ROT
s4 s4 XCPU // kl=32 cs next_vset _32=34 cfg_dict kl=32
DICTISETGETOPTREF // kl=32 cs cfg_dict cur_vset
s3 s1 s0 PUXCPU // kl=32 cs cur_vset _35=32 cfg_dict kl=32
DICTISETGETOPTREF // kl=32 cs _51 _52
@ -471,18 +537,17 @@ PROGRAM{
s0 s1 s3 XCHG3 // cs _38=36 cfg_dict kl=32
DICTIDEL // cs _53 _54
DROP // cs cfg_dict
SWAP // cfg_dict cs
}>ELSE<{
s2 s3 XCHG
2DROP // cs cfg_dict
2DROP // cfg_dict cs
}>
}>ELSE<{
s3 s4 XCHG
3 BLKDROP // cs cfg_dict
3 BLKDROP // cfg_dict cs
}>
}>ELSE<{
s2 s3 XCHG
2DROP // cs cfg_dict
2DROP // cfg_dict cs
}>
SWAP
NEWC // cs cfg_dict _40
STREF // cs _41
SWAP // _41 cs
@ -490,4 +555,10 @@ PROGRAM{
ENDC // _43
c4 POP
}>
seqno PROC:<{
//
c4 PUSH // _0
CTOS // _1
32 PLDU // _3
}>
}END>c

View File

@ -0,0 +1 @@
with_tvm_code("dns-auto", "te6ccgECLgEABhoAART/APSkE/S88sgLAQIBIAIDAgFIBAUBIvIw2zwxmPgAhB/4I/AD4V8ELQICzQYHAgEgGRoCASAICQIBIBMUAvdCDXScEgkl8D4AHQ0wMBcbCSXwPg+kAwIPpEA9MfIZJfBuFwIddJwj+UMNM/Ad5UFAJvA/hhIIMesJJfBeAgqxfAQ46ENFnbPOAgghByZWdkuiGCEHByb2y6qgCgIYIQdXBkZLqqAaABghBnb2djuqoCoCCWXwWEH/AF4YCgsARVAm8kCMjMF/QAFfQAyx1QA/oCUAP6AlAD+gISyx/LH8ntVIA/bbPCXQ0gcKvQnT/zBQCL0YsZpfCIIQ7m93bvAF4CeCEENoUHK6jhcwNgLTH/oA+gD6ANFvBEBEBQPwA3DwBuA0NAWCEENEZWy6jq8kbpJfBZYEA3F/8Afi2zwQRV8FbpiCEO50ZW3wBeH4QW8jghDva2F5WXCBAKDwBOAtLQwD/qPbPCbACI4ZMDU1NjYD0h8wEDUQNHEB8AeCEO9rYXnwBeAI9AQhbpsx0wUhwAACqgLXGJ0B0CDXSwGm+ICHsLEC4iKZMiB41yLXCwcC3wKaXwyCEO5vXDDwBeD4I20gcFRwBCDXSak2AorkMAHCBJtfD1uCEO92XDDwBeAswwEtDQ4ADF8FhB/wBQCEbTbTBwHAAFEzoQOONDMi10lScNcj+QKrH1MMgQDg9A5voY4ZbBLTH1MXvp3U0X4BgBD0DZE1kTDikTDiAZEw4gPeBP4kBE8TEREB2zwglQ5fDvAF4DApwwKOPQPUMCBujjV+IYAQ9A2OFdAg10mBARu+8p/XCxKCCAT+nLryn5Ew4iCAEPSEb6VsISGAEPSMb6VsIbDyn9+SMyLiJW8kI5xfD18DghDTT0ZG8AXhJBA3Wds8K8MEFbAUoA6DHaEuuYrgDyoQEQCsBG5SQLCYXwSCEO5vdGbgIm6ZXwOCEO5vLTKw4DOCEOJhZDIC0CDXSYEBG7mUECNfA+DTEgGCCAT+nL2UECNfA+BsEtIH1wv/Ar0CvbGWghDub3du4HAAFF8OghDncjxw8AUB4CnAAo5FMzhRd6BSgLyaXwuCEPNlcm/wBeBTdqDIyx/MVCCVgQDg9EMGqt9QCKAEqt9SQKBQRIMH9FswyEBEgwf0QwNFVHHwB/AG4CnAAYrgA18DBsAEjhUGyMsfFcxQcoEA4PRDUFQTcfAH8AbgXwoSAHA5OQFuml8LghDhbHJl8AXhF6AgyMsfFsxUIISBAOD0QySq31AIscgCgwf0Q1BDtggVQwRx8AfwBgIBIBUWAgEgFxgARRwgBjIywVQB88WWPoCFctqE8sfyz8hwv+Syx+RMeLJAfsAgABc+EFvIxAjcIBA8ASAAJx0+wL4QW8jghDva2F5WXCDBvAEgAPE+CMipjxSQLYJUhC5k1vwA+AyJIMH9IZvpTKTURKwjlQzIqvfUwK5jj8wIqk431MGgQDg9A5voY4S1wsfI7uZUAaBAOD0WzAFkTDikVviUCSDB/RbMCCDB/SGb6UyIZMgq9+ShB/iBqWVRRUDcALiEDYQNFnoW/ADgAgEgGxwCASAfIAENuHWts8XwOCkCAUgdHgIZs7E2zwzEDREBNs8oICkqAQ2xZrbPF8DgKwIBWCEiAT26MM+CMS2zwDlF8EcG3hkn8z3wHXSSKVWYAQ9GrgMoKwIBWCMkAgFqJygCASAlJgEQq+74I9s8XwMrAQ2nhbZ4Jr4HKQEPp6W2eCBGvgcpAQ2nx7Z4Br4HKQIPpTG2eNhFtnkpKgAo7UTQ1DH0BDH0BDHTHfoA+gD6ADAAMAKAZPlBMgTXSaoAgQDAoBSgA6YCqAKooAH2IddLIXewsfJeIJZfA3BtIW3hInjXItcLB55wyFAEzxYTywfJ0AKmCN4gwAiWXwNwbSFt4O1E0NQx9AQwbX8lBKsCjjID0wcBwACOKCDXSVJg1yP5AqsfI4EA4PQOb6GOECDXCx8mvpYyMyLXSQORMOKRMOLeA+RsIjIgLAAsbpZfA3BtIW3g0x/UMCLAAFBD1yNDMAA07UTQ1PQE9ATTHfoA+gD6AFUwbwQB0x/THzA=");

View File

@ -0,0 +1,949 @@
// automatically generated from `smartcont/stdlib.fc` `smartcont/dns-auto-code.fc`
PROGRAM{
DECLPROC load_data
DECLPROC load_prices
DECLPROC store_data
DECLPROC send_message
DECLPROC send_error
DECLPROC send_ok
DECLPROC housekeeping
DECLPROC calcprice_internal
DECLPROC check_owner
DECLPROC perform_ctl_op
DECLPROC recv_internal
DECLPROC recv_external
DECLPROC dnsdictlookup
123660 DECLMETHOD dnsresolve
87450 DECLMETHOD getexpirationx
110574 DECLMETHOD getexpiration
67418 DECLMETHOD getstdperiod
109522 DECLMETHOD getppr
108994 DECLMETHOD getppc
113123 DECLMETHOD getppb
113304 DECLMETHOD calcprice
85700 DECLMETHOD calcregprice
DECLGLOBVAR query_info
load_data PROCREF:<{
//
c4 PUSH // _1
CTOS // cs
LDREF // _3 cs
LDDICT // _3 _5 cs
LDDICT // _3 _5 _7 cs
30 LDU // _3 _5 _7 _10 cs
LDGRAMS // _3 _5 _7 _10 _13 cs
LDGRAMS // _3 _5 _7 _10 _13 _15 cs
LDGRAMS // _3 _5 _7 _10 _13 _15 _17 cs
4 -ROLL // _3 _5 _7 cs _10 _13 _15 _17
4 TUPLE // _3 _5 _7 cs _9
SWAP // _3 _5 _7 _9 cs
32 LDU // _3 _5 _7 _9 _19 cs
32 LDU // _3 _5 _7 _9 _19 _42 _41
DROP // _3 _5 _7 _9 _19 _22
}>
load_prices PROCREF:<{
//
c4 PUSH // _1
CTOS // cs
LDREF // _19 _18
NIP // cs
LDDICT // _21 _20
NIP // cs
LDDICT // _23 _22
NIP // cs
30 LDU // _9 cs
LDGRAMS // _9 _12 cs
LDGRAMS // _9 _12 _14 cs
LDGRAMS // _9 _12 _14 _31 _30
DROP // _9 _12 _14 _16
}>
store_data PROC:<{
// ctl dd gc prices nhk lhk
s0 s2 XCHG // ctl dd gc lhk nhk prices
4 UNTUPLE // ctl dd gc lhk nhk sp ppr ppc ppb
s0 s8 XCHG
NEWC // ppb dd gc lhk nhk sp ppr ppc ctl _11
STREF // ppb dd gc lhk nhk sp ppr ppc _12
s1 s7 XCHG // ppb ppc gc lhk nhk sp ppr dd _12
STDICT // ppb ppc gc lhk nhk sp ppr _13
s1 s5 XCHG // ppb ppc ppr lhk nhk sp gc _13
STDICT // ppb ppc ppr lhk nhk sp _14
30 STU // ppb ppc ppr lhk nhk _16
s0 s3 XCHG2 // ppb ppc nhk lhk _16 ppr
STGRAMS // ppb ppc nhk lhk _17
s0 s3 XCHG2 // ppb lhk nhk _17 ppc
STGRAMS // ppb lhk nhk _18
s0 s3 XCHG2 // nhk lhk _18 ppb
STGRAMS // nhk lhk _19
s1 s2 XCHG // lhk nhk _19
32 STU // lhk _21
32 STU // _23
ENDC // _24
c4 POP
}>
send_message PROC:<{
// addr tag query_id body grams mode
0 PUSHINT // addr tag query_id body grams mode _7=0
24 PUSHINT // addr tag query_id body grams mode _7=0 _8=24
NEWC // addr tag query_id body grams mode _7=0 _8=24 _9
6 STU // addr tag query_id body grams mode _7=0 _11
s0 s7 XCHG2 // _7=0 tag query_id body grams mode _11 addr
STSLICER // _7=0 tag query_id body grams mode _12
ROT // _7=0 tag query_id body mode _12 grams
STGRAMS // _7=0 tag query_id body mode _13
s1 s5 XCHG // mode tag query_id body _7=0 _13
107 STU // mode tag query_id body _27
s1 s3 XCHG // mode body query_id tag _27
32 STU // mode body query_id _29
64 STU // mode body msg
OVER // mode body msg body
-1 GTINT // mode body msg _33
IF:<{ // mode body msg
32 STU // mode msg
}>ELSE<{
NIP // mode msg
}>
ENDC // mode _37
SWAP // _37 mode
SENDRAWMSG
}>
send_error PROC:<{
// error_code
query_info GETGLOB
UNTRIPLE // error_code addr query_id op
s2 s3 XCHG
0 PUSHINT
64 PUSHINT // addr error_code query_id op _5=0 _6=64
send_message CALLDICT
}>
send_ok PROC:<{
// price
4 PUSHINT // price _1=4
RAWRESERVE
query_info GETGLOB
UNTRIPLE // addr query_id op
4016791929 PUSHINT // addr query_id op _7=4016791929
-ROT
0 PUSHINT
7 PUSHPOW2 // addr _7=4016791929 query_id op _8=0 _9=128
send_message CALLDICT
}>
housekeeping PROC:<{
// ctl dd gc prices nhk lhk max_steps
NOW // ctl dd gc prices nhk lhk max_steps n
s2 PUSH // ctl dd gc prices nhk lhk max_steps n lhk
60 ADDCONST // ctl dd gc prices nhk lhk max_steps n _10
s4 s(-1) PUXC // ctl dd gc prices nhk lhk max_steps n nhk _10
MAX // ctl dd gc prices nhk lhk max_steps n _11
s1 s(-1) PUXC // ctl dd gc prices nhk lhk max_steps n n _11
LESS // ctl dd gc prices nhk lhk max_steps n _12
IFJMP:<{ // ctl dd gc prices nhk lhk max_steps n
2DROP // ctl dd gc prices nhk lhk
store_data CALLDICT
}> // ctl dd gc prices nhk lhk max_steps n
s2 POP // ctl dd gc prices nhk n max_steps
s4 PUSH
8 PUSHPOW2 // ctl dd gc prices nhk n max_steps gc _17=256
DICTUMIN
NULLSWAPIFNOT2 // ctl dd gc prices nhk n max_steps _63 _62 _64
s2 POP // ctl dd gc prices nhk n max_steps found? mkey
WHILE:<{
s1 s2 XCPU // ctl dd gc prices nhk n max_steps mkey found? max_steps
AND // ctl dd gc prices nhk n max_steps mkey _19
}>DO<{ // ctl dd gc prices nhk n max_steps mkey
s3 POP // ctl dd gc prices mkey n max_steps
s2 PUSH // ctl dd gc prices mkey n max_steps mkey
224 RSHIFT# // ctl dd gc prices mkey n max_steps nhk
s0 s2 PUSH2 // ctl dd gc prices mkey n max_steps nhk nhk n
LESS // ctl dd gc prices mkey n max_steps nhk _24
IF:<{ // ctl dd gc prices mkey n max_steps nhk
DROP // ctl dd gc prices mkey n max_steps
s2 PUSH // ctl dd gc prices mkey n max_steps mkey
224 MODPOW2# // ctl dd gc prices mkey n max_steps key
s0 s6 PUSH2
224 PUSHINT // ctl dd gc prices mkey n max_steps key key dd _35
DICTUGET
NULLSWAPIFNOT // ctl dd gc prices mkey n max_steps key val found?
IF:<{ // ctl dd gc prices mkey n max_steps key val
32 PLDU // ctl dd gc prices mkey n max_steps key exp
s3 PUSH // ctl dd gc prices mkey n max_steps key exp n
LEQ // ctl dd gc prices mkey n max_steps key _40
IF:<{ // ctl dd gc prices mkey n max_steps key
s0 s6 XCHG2
224 PUSHINT // ctl max_steps gc prices mkey n key dd _44
DICTUDEL // ctl max_steps gc prices mkey n _67 _68
DROP // ctl max_steps gc prices mkey n dd
s0 s5 XCHG // ctl dd gc prices mkey n max_steps
}>ELSE<{
DROP // ctl dd gc prices mkey n max_steps
}>
}>ELSE<{
2DROP // ctl dd gc prices mkey n max_steps
}>
s2 s4 XCHG2
8 PUSHPOW2 // ctl dd max_steps prices n mkey gc _47=256
DICTUDEL // ctl dd max_steps prices n _69 _70
DROP // ctl dd max_steps prices n gc
DUP
8 PUSHPOW2 // ctl dd max_steps prices n gc gc _50=256
DICTUMIN
NULLSWAPIFNOT2 // ctl dd max_steps prices n gc _72 _71 _73
s2 POP // ctl dd max_steps prices n gc found? mkey
OVER // ctl dd max_steps prices n gc found? mkey found?
IF:<{ // ctl dd max_steps prices n gc found? mkey
DUP // ctl dd max_steps prices n gc found? mkey mkey
224 RSHIFT# // ctl dd max_steps prices n gc found? mkey _52
}>ELSE<{ // ctl dd max_steps prices n gc found? mkey
32 PUSHPOW2DEC // ctl dd max_steps prices n gc found? mkey _52=4294967295
}> // ctl dd max_steps prices n gc found? mkey nhk
s0 s6 XCHG // ctl dd nhk prices n gc found? mkey max_steps
DEC // ctl dd nhk prices n gc found? mkey max_steps
}>ELSE<{ // ctl dd gc prices mkey n max_steps nhk
s5 s1 s5 XCHG3
s0 s3 XCHG
FALSE
s0 s2 XCHG // ctl dd nhk prices n gc found? mkey max_steps
}>
s3 s6 XCHG
s3 s4 XCHG
-ROT // ctl dd gc prices nhk n max_steps found? mkey
}> // ctl dd gc prices nhk n max_steps mkey
2DROP // ctl dd gc prices nhk n
store_data CALLDICT
}>
calcprice_internal PROCREF:<{
// domain data ppc ppb
s0 s2 XCHG
100 PUSHINT // domain ppb ppc data _7=100
CDATASIZE // domain ppb ppc _24 _25 _26
s2 POP // domain ppb ppc refs bits
s0 s4 XCHG // bits ppb ppc refs domain
SBITS // bits ppb ppc refs _9
1 LSHIFT# // bits ppb ppc refs _11
192 PUSHINT // bits ppb ppc refs _11 _16
ADD // bits ppb ppc refs _17
s1 s4 XCHG // refs ppb ppc bits _17
ADD // refs ppb ppc bits
s0 s3 XCHG // bits ppb ppc refs
2 ADDCONST // bits ppb ppc _20
MUL // bits ppb _21
s0 s2 XCHG // _21 ppb bits
MUL // _21 _22
ADD // _23
}>
check_owner PROCREF:<{
// cat_table owner_info src_wc src_addr strict
s0 s4 XCHG // strict owner_info src_wc src_addr cat_table
ISNULL // strict owner_info src_wc src_addr _5
s4 s(-1) PUXC // strict owner_info src_wc src_addr strict _5
AND // strict owner_info src_wc src_addr _6
IFJMP:<{ // strict owner_info src_wc src_addr
4 BLKDROP //
4000281702 PUSHINT // _7=4000281702
}> // strict owner_info src_wc src_addr
s2 PUSH // strict owner_info src_wc src_addr owner_info
ISNULL // strict owner_info src_wc src_addr _8
IFJMP:<{ // strict owner_info src_wc src_addr
3 BLKDROP // strict
4000263474 PUSHINT // strict _9=4000263474
AND // _10
}> // strict owner_info src_wc src_addr
s3 POP // src_addr owner_info src_wc
3798033458 PUSHINT // src_addr owner_info src_wc ERR_BAD2=3798033458
s0 s2 XCHG // src_addr ERR_BAD2=3798033458 src_wc owner_info
CTOS // src_addr ERR_BAD2=3798033458 src_wc sown
DUP // src_addr ERR_BAD2=3798033458 src_wc sown sown
SBITS // src_addr ERR_BAD2=3798033458 src_wc sown _15
283 PUSHINT // src_addr ERR_BAD2=3798033458 src_wc sown _15 _22
LESS // src_addr ERR_BAD2=3798033458 src_wc sown _23
IFJMP:<{ // src_addr ERR_BAD2=3798033458 src_wc sown
s2 s3 XCHG
3 BLKDROP // ERR_BAD2=3798033458
}> // src_addr ERR_BAD2=3798033458 src_wc sown
19 LDU // src_addr ERR_BAD2=3798033458 src_wc _24 sown
SWAP
327324 PUSHINT // src_addr ERR_BAD2=3798033458 src_wc sown _24 _33
NEQ // src_addr ERR_BAD2=3798033458 src_wc sown _34
IFJMP:<{ // src_addr ERR_BAD2=3798033458 src_wc sown
s2 s3 XCHG
3 BLKDROP // ERR_BAD2=3798033458
}> // src_addr ERR_BAD2=3798033458 src_wc sown
1 2 BLKDROP2 // src_addr src_wc sown
8 LDI // src_addr src_wc _37 sown
256 PLDU // src_addr src_wc owner_wc owner_addr
s0 s2 XCHG // src_addr owner_addr owner_wc src_wc
NEQ // src_addr owner_addr _42
s0 s2 XCHG // _42 owner_addr src_addr
NEQ // _42 _43
OR // _44
IFJMP:<{ //
4000282478 PUSHINT // _45=4000282478
}> //
0 PUSHINT // _46=0
}>
perform_ctl_op PROCREF:<{
// op src_wc src_addr in_msg
load_data INLINECALLDICT // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk
s5 PUSH // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk ctl
CTOS // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk cs
8 LDI // op src_wc src_addr in_msg ctl domdata gc prices nhk lhk _13 cs
s0 s10 XCHG // op cs src_addr in_msg ctl domdata gc prices nhk lhk _13 src_wc
NEQ // op cs src_addr in_msg ctl domdata gc prices nhk lhk _16
s0 s9 XCHG // op _16 src_addr in_msg ctl domdata gc prices nhk lhk cs
256 LDU // op _16 src_addr in_msg ctl domdata gc prices nhk lhk _75 _74
DROP // op _16 src_addr in_msg ctl domdata gc prices nhk lhk _17
s0 s8 XCHG2 // op _16 lhk in_msg ctl domdata gc prices nhk _17 src_addr
NEQ // op _16 lhk in_msg ctl domdata gc prices nhk _20
s1 s8 XCHG // op nhk lhk in_msg ctl domdata gc prices _16 _20
OR // op nhk lhk in_msg ctl domdata gc prices _21
IFJMP:<{ // op nhk lhk in_msg ctl domdata gc prices
8 BLKDROP //
4000282478 PUSHINT // _22=4000282478
send_error CALLDICT
}> // op nhk lhk in_msg ctl domdata gc prices
s7 PUSH
1130909810 PUSHINT // op nhk lhk in_msg ctl domdata gc prices op _24=1130909810
EQUAL // op nhk lhk in_msg ctl domdata gc prices _25
IFJMP:<{ // op nhk lhk in_msg ctl domdata gc prices
DROP
s6 POP // gc nhk lhk in_msg ctl domdata
s0 s2 XCHG // gc nhk lhk domdata ctl in_msg
32 LDU // gc nhk lhk domdata ctl _30 in_msg
LDGRAMS // gc nhk lhk domdata ctl _30 _33 in_msg
LDGRAMS // gc nhk lhk domdata ctl _30 _33 _35 in_msg
LDGRAMS // gc nhk lhk domdata ctl stdper ppr ppc ppb in_msg
ENDS
4 TUPLE // gc nhk lhk domdata ctl _40
s0 s4 s4 XCHG3
s0 s5 XCHG
s0 s3 XCHG // ctl domdata gc _40 nhk lhk
store_data CALLDICT
0 PUSHINT // _42=0
send_ok CALLDICT
}> // op nhk lhk in_msg ctl domdata gc prices
s4 POP
s4 POP // op nhk gc prices ctl domdata
s0 s5 XCHG
1128555884 PUSHINT // domdata nhk gc prices ctl op _44=1128555884
EQUAL // domdata nhk gc prices ctl _45
IFJMP:<{ // domdata nhk gc prices ctl
s4 PUSH // domdata nhk gc prices ctl domdata
ISNULL // domdata nhk gc prices ctl _46
IFNOT:<{ // domdata nhk gc prices ctl
s0 s4 XCHG
s0 s3 XCHG
1 PUSHINT
-1 PUSHINT // ctl domdata gc prices nhk _47=1 _48=-1
housekeeping CALLDICT
}>ELSE<{
5 BLKDROP //
}>
load_data INLINECALLDICT // _84 _85 _86 _87 _88 _89
s4 s5 XCHG
5 BLKDROP // domdata
ISNULL // _51
IFNOTJMP:<{ //
4000605549 PUSHINT // _52=4000605549
send_error CALLDICT
}> //
query_info GETGLOB
UNTRIPLE // addr query_id op
4016791929 PUSHINT // addr query_id op _58=4016791929
-ROT
0 PUSHINT
160 PUSHINT // addr _58=4016791929 query_id op _59=0 _62
send_message CALLDICT
}> // domdata nhk gc prices ctl
5 BLKDROP //
32 PUSHPOW2DEC // _64=4294967295
send_error CALLDICT
}>
recv_internal PROC:<{
// msg_value in_msg_cell in_msg
DUP // msg_value in_msg_cell in_msg in_msg
SBITS // msg_value in_msg_cell in_msg _3
32 LESSINT // msg_value in_msg_cell in_msg _5
IFJMP:<{ // msg_value in_msg_cell in_msg
3 BLKDROP //
}> // msg_value in_msg_cell in_msg
SWAP // msg_value in_msg in_msg_cell
CTOS // msg_value in_msg cs
4 LDU // msg_value in_msg flags cs
SWAP
1 PUSHINT // msg_value in_msg cs flags _12=1
AND // msg_value in_msg cs _13
IFJMP:<{ // msg_value in_msg cs
3 BLKDROP //
}> // msg_value in_msg cs
LDMSGADDR // msg_value in_msg _327 _326
DROP // msg_value in_msg s_addr
DUP // msg_value in_msg s_addr s_addr
REWRITESTDADDR // msg_value in_msg s_addr src_wc src_addr
s0 s3 XCHG // msg_value src_addr s_addr src_wc in_msg
32 LDU // msg_value src_addr s_addr src_wc op in_msg
OVER // msg_value src_addr s_addr src_wc op in_msg op
IFNOTJMP:<{ // msg_value src_addr s_addr src_wc op in_msg
6 BLKDROP //
}> // msg_value src_addr s_addr src_wc op in_msg
0 PUSHINT // msg_value src_addr s_addr src_wc op in_msg query_id=0
OVER // msg_value src_addr s_addr src_wc op in_msg query_id=0 in_msg
SBITS // msg_value src_addr s_addr src_wc op in_msg query_id=0 _26
63 GTINT // msg_value src_addr s_addr src_wc op in_msg query_id=0 _28
IF:<{ // msg_value src_addr s_addr src_wc op in_msg query_id=0
DROP // msg_value src_addr s_addr src_wc op in_msg
64 LDU // msg_value src_addr s_addr src_wc op query_id in_msg
SWAP // msg_value src_addr s_addr src_wc op in_msg query_id
}> // msg_value src_addr s_addr src_wc op in_msg query_id
s4 s0 s2 XC2PU // msg_value src_addr in_msg src_wc op s_addr query_id op
TRIPLE
query_info SETGLOB
DUP
31 PUSHPOW2 // msg_value src_addr in_msg src_wc op op _34
AND // msg_value src_addr in_msg src_wc op _35
IFJMP:<{ // msg_value src_addr in_msg src_wc op
5 BLKDROP //
}> // msg_value src_addr in_msg src_wc op
DUP // msg_value src_addr in_msg src_wc op op
24 RSHIFT# // msg_value src_addr in_msg src_wc op _37
67 EQINT // msg_value src_addr in_msg src_wc op _39
IFJMP:<{ // msg_value src_addr in_msg src_wc op
s4 POP // op src_addr in_msg src_wc
-ROT // op src_wc src_addr in_msg
perform_ctl_op INLINECALLDICT
}> // msg_value src_addr in_msg src_wc op
DUP
1919248228 PUSHINT // msg_value src_addr in_msg src_wc op op _42=1919248228
EQUAL // msg_value src_addr in_msg src_wc op _45
OVER
1886547820 PUSHINT // msg_value src_addr in_msg src_wc op _45 op _46=1886547820
EQUAL // msg_value src_addr in_msg src_wc op _45 _47
1 LSHIFT# // msg_value src_addr in_msg src_wc op _45 _49
ADD // msg_value src_addr in_msg src_wc op _50
OVER
1970300004 PUSHINT // msg_value src_addr in_msg src_wc op _50 op _51=1970300004
EQUAL // msg_value src_addr in_msg src_wc op _50 _52
2 LSHIFT# // msg_value src_addr in_msg src_wc op _50 _54
ADD // msg_value src_addr in_msg src_wc op _55
SWAP
1735354211 PUSHINT // msg_value src_addr in_msg src_wc _55 op _56=1735354211
EQUAL // msg_value src_addr in_msg src_wc _55 _57
3 LSHIFT# // msg_value src_addr in_msg src_wc _55 _59
ADD // msg_value src_addr in_msg src_wc qt
DUP // msg_value src_addr in_msg src_wc qt qt
IFNOTJMP:<{ // msg_value src_addr in_msg src_wc qt
5 BLKDROP //
32 PUSHPOW2DEC // _61=4294967295
send_error CALLDICT
}> // msg_value src_addr in_msg src_wc qt
NEGATE // msg_value src_addr in_msg src_wc qt
load_data INLINECALLDICT // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk
s6 PUSH // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk qt
8 EQINT // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk _72
IFJMP:<{ // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk
DROP
s5 POP
s5 POP
s6 POP
s6 POP // domdata gc in_msg prices nhk ctl
s0 s3 XCHG // domdata gc ctl prices nhk in_msg
32 LDI // domdata gc ctl prices nhk _341 _340
DROP // domdata gc ctl prices nhk max_steps
s3 s5 XCHG
s3 s4 XCHG
1 PUSHINT
SWAP // ctl domdata gc prices nhk _77=1 max_steps
housekeeping CALLDICT
4016791929 PUSHINT // _79=4016791929
send_error CALLDICT
}> // msg_value src_addr in_msg src_wc qt ctl domdata gc prices nhk lhk
s0 s8 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg
LDOPTREF // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg
OVER // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg domain_cell
ISNULL // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg _88
IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg
NIP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg
6 LDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk bytes in_msg
OVER // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk bytes in_msg bytes
0 EQINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk bytes in_msg fail
s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail in_msg bytes
3 LSHIFT# // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail in_msg _97
LDSLICEX // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg
}>ELSE<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk domain_cell in_msg
SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain_cell
CTOS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain
DUP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain domain
SBITREFS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain bits refs
SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs bits
-8 ADDCONST // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs _104
-121 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs _104 _107
AND // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain refs _108
OR // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain fail
s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg
}>
s2 PUSH // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg fail
IFNOT:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg
s2 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain
DUP
8 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain domain _110=8
SDCUTLAST // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain _111
8 PLDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain fail
s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg
}> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk fail domain in_msg
s0 s2 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain fail
IFJMP:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain
12 BLKDROP //
4000275504 PUSHINT // _114=4000275504
send_error CALLDICT
}> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain
NOW // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n
PUSHNULL // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n _120
DUP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info
0 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info _124=0
s0 s0 s4 PUSH3 // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail
DUP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail tail
SBITS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail _126
3 RSHIFTC# // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key=0 zeros=0 exp=0 tail _128
REPEAT:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail
PUSHNULL
s6 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail
8 LDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp _131 tail
SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail _131
0 EQINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail z
s3 s3 XCPU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key z exp tail zeros z
SUB // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key z exp tail zeros
s0 s3 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail z
IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail
s3 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp
s2 PUSH // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp tail
SBITS // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp _137
s7 s(-1) PUXC // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp domain _137
SDSKIPLAST // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp _138
SHA256U // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp _139
32 RSHIFT# // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key
s0 s12 PUSH2
224 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key key domdata _146
DICTUGET
NULLSWAPIFNOT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key val found?
IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key val
1 2 BLKDROP2 // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key val
32 LDU // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val
s1 s7 PUSH2 // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val exp n
GEQ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val _151
IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp val
LDREF // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cat_table val
ENDS
-2 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cat_table _158=-2
SWAP
16 PUSHINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp _158=-2 cat_table _159=16
DICTIGETREF // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cown ok
IF:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp cown
s5 POP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp
}>ELSE<{
DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp
}>
}>ELSE<{
DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros key exp
}>
SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key
}>ELSE<{
DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info tail zeros exp key
}>
s0 s3 XCHG // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail
}> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp tail
}>
DROP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key zeros exp
SWAP // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp zeros
4 GTINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp _162
IFJMP:<{ // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp
15 BLKDROP
2DROP //
4017511472 PUSHINT // _163=4017511472
send_error CALLDICT
}> // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp
s12 PUSH // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp qt
1 NEQINT // msg_value src_addr lhk src_wc qt ctl domdata gc prices nhk in_msg domain n cat_table owner_info key exp _167
s4 PUSH
s0 s4 XCHG
s15 s1 s3 XCHG3
s0 17 s() XCHG
SWAP // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table cat_table owner_info src_wc src_addr _167
check_owner INLINECALLDICT // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err
DUP // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err err
IFJMP:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err
s0 s14 XCHG
14 BLKDROP // err
send_error CALLDICT
}> // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table err
DROP // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table
s9 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table qt
2 NEQINT // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table _173
IF:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table
s0 s3 XCHG // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n in_msg
LDREF // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n _361 _360
DROP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data
DUP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data data
DICTEMPTY // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _176
IFNOT:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data
-2 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _179=-2
OVER
16 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _179=-2 data _180=16
DICTIGETREF // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data oinfo ok
IF:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data oinfo
CTOS // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs
DUP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs cs
SBITS // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs _185
283 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs _185 _192
GEQ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data cs _193
31 THROWIFNOT
19 PLDU // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _197
327324 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _197 _202
EQUAL // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _203
31 THROWIFNOT
}>ELSE<{
DROP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data
}>
DUP
16 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data data _208=16
DICTIMIN
NULLSWAPIFNOT2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _365 _364 _366
2 1 BLKDROP2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok
OVER
16 PUSHINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok data _213=16
DICTIMAX
NULLSWAPIFNOT2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok _368 _367 _369
2 1 BLKDROP2 // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data minok maxok
AND // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data _216
31 THROWIFNOT
}> // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data
}>ELSE<{ // msg_value key lhk exp qt ctl domdata gc prices nhk in_msg domain n cat_table
s3 POP // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n
s2 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data
}>
s5 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data prices
4 UNTUPLE // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb
s3 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb stdper
IFNOTJMP:<{ // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb
15 BLKDROP
3 BLKDROP //
3545187910 PUSHINT // _223=3545187910
send_error CALLDICT
}> // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table domain n data stdper ppr ppc ppb
s4 PUSH
s3 s7 XCHG
-ROT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper domain data ppc ppb
calcprice_internal INLINECALLDICT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper _226
s11 PUSH // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper _226 qt
4 NEQINT // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table ppr n data stdper _226 _228
s1 s5 XCHG // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table _226 n data stdper ppr _228
AND // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table _226 n data stdper _229
s1 s4 XCHG // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _226 _229
ADD // msg_value key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data price
s0 s14 XCHG
30 PUSHPOW2 // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data msg_value _233
SUB // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _234
s14 PUSH // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _234 price
LESS // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _235
IFJMP:<{ // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data
14 BLKDROP //
3883023472 PUSHINT // _236=3883023472
send_error CALLDICT
}> // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data
s9 PUSH // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data qt
2 EQINT // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _243
IFJMP:<{ // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data
s3 POP
s8 POP // price key lhk exp n ctl domdata gc prices nhk data stdper
s7 s7 XCPU // price key lhk exp stdper ctl domdata gc prices nhk data n stdper
ADD // price key lhk exp stdper ctl domdata gc prices nhk data _244
s8 s(-1) PUXC // price key lhk exp stdper ctl domdata gc prices nhk data exp _244
GREATER // price key lhk exp stdper ctl domdata gc prices nhk data _245
IFJMP:<{ // price key lhk exp stdper ctl domdata gc prices nhk data
11 BLKDROP //
4083511919 PUSHINT // _246=4083511919
send_error CALLDICT
}> // price key lhk exp stdper ctl domdata gc prices nhk data
s7 s6 PUSH2 // price key lhk exp stdper ctl domdata gc prices nhk data exp stdper
ADD // price key lhk exp stdper ctl domdata gc prices nhk data _249
NEWC // price key lhk exp stdper ctl domdata gc prices nhk data _249 _250
32 STU // price key lhk exp stdper ctl domdata gc prices nhk data _252
STREF // price key lhk exp stdper ctl domdata gc prices nhk _253
s0 s9 s4 XCPUXC
224 PUSHINT // price key lhk exp stdper ctl nhk gc prices _253 key domdata _256
DICTUSETB // price key lhk exp stdper ctl nhk gc prices domdata
s0 s6 XCHG // price key lhk domdata stdper ctl nhk gc prices exp
224 LSHIFT# // price key lhk domdata stdper ctl nhk gc prices _262
s0 s8 XCHG2 // price prices lhk domdata stdper ctl nhk gc _262 key
ADD // price prices lhk domdata stdper ctl nhk gc gckeyO
s0 s4 XCHG // price prices lhk domdata gckeyO ctl nhk gc stdper
224 LSHIFT# // price prices lhk domdata gckeyO ctl nhk gc _268
s4 s(-1) PUXC // price prices lhk domdata gckeyO ctl nhk gc gckeyO _268
ADD // price prices lhk domdata gckeyO ctl nhk gc gckeyN
s4 s4 XCHG2
8 PUSHPOW2 // price prices lhk domdata gckeyN ctl nhk gckeyO gc _271=256
DICTUDEL // price prices lhk domdata gckeyN ctl nhk _376 _377
DROP // price prices lhk domdata gckeyN ctl nhk gc
NEWC // price prices lhk domdata gckeyN ctl nhk gc _274
s0 s4 s4 XCHG3
8 PUSHPOW2 // price prices lhk domdata nhk ctl _274 gckeyN gc _275=256
DICTUSETB // price prices lhk domdata nhk ctl gc
s0 s3 XCHG
s5 s5 s4 XCHG3
1 PUSHINT // price ctl domdata gc prices nhk lhk _277=1
housekeeping CALLDICT
send_ok CALLDICT
}> // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data
s9 PUSH // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data qt
1 EQINT // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data _281
IFJMP:<{ // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data
s9 POP
s9 POP // price key lhk n data ctl domdata gc prices nhk cat_table stdper
SWAP // price key lhk n data ctl domdata gc prices nhk stdper cat_table
ISNULL // price key lhk n data ctl domdata gc prices nhk stdper _282
IFNOTJMP:<{ // price key lhk n data ctl domdata gc prices nhk stdper
11 BLKDROP //
3781980773 PUSHINT // _283=3781980773
send_error CALLDICT
}> // price key lhk n data ctl domdata gc prices nhk stdper
s1 s7 XCHG // price key lhk nhk data ctl domdata gc prices n stdper
ADD // price key lhk nhk data ctl domdata gc prices expires_at
DUP
NEWC // price key lhk nhk data ctl domdata gc prices expires_at expires_at _288
32 STU // price key lhk nhk data ctl domdata gc prices expires_at _290
s1 s6 XCHG // price key lhk nhk expires_at ctl domdata gc prices data _290
STREF // price key lhk nhk expires_at ctl domdata gc prices _291
s0 s8 s3 XCPUXC
224 PUSHINT // price key lhk nhk expires_at ctl prices gc _291 key domdata _294
DICTUSETB // price key lhk nhk expires_at ctl prices gc domdata
s4 PUSH // price key lhk nhk expires_at ctl prices gc domdata expires_at
224 LSHIFT# // price key lhk nhk expires_at ctl prices gc domdata _300
s0 s8 XCHG2 // price domdata lhk nhk expires_at ctl prices gc _300 key
OR // price domdata lhk nhk expires_at ctl prices gc gckey
NEWC // price domdata lhk nhk expires_at ctl prices gc gckey _303
s0 s2 XCHG
8 PUSHPOW2 // price domdata lhk nhk expires_at ctl prices _303 gckey gc _304=256
DICTUSETB // price domdata lhk nhk expires_at ctl prices gc
s4 s3 XCHG2 // price domdata lhk prices gc ctl nhk expires_at
MIN // price domdata lhk prices gc ctl _306
s1 s5 XCHG
s3 s0 s4 XCHG3
1 PUSHINT // price ctl domdata gc prices _306 lhk _307=1
housekeeping CALLDICT
send_ok CALLDICT
}> // price key lhk exp qt ctl domdata gc prices nhk cat_table stdper n data
s0 s3 XCHG
3 BLKDROP // price key lhk exp qt ctl domdata gc prices nhk data
s0 s6 XCHG // price key lhk exp data ctl domdata gc prices nhk qt
4 EQINT // price key lhk exp data ctl domdata gc prices nhk _311
IFJMP:<{ // price key lhk exp data ctl domdata gc prices nhk
s0 s6 XCHG
NEWC // price key lhk nhk data ctl domdata gc prices exp _313
32 STU // price key lhk nhk data ctl domdata gc prices _315
s1 s5 XCHG // price key lhk nhk prices ctl domdata gc data _315
STREF // price key lhk nhk prices ctl domdata gc _316
s7 s2 XCHG2
224 PUSHINT // price gc lhk nhk prices ctl _316 key domdata _319
DICTUSETB // price gc lhk nhk prices ctl domdata
s5 s4 XCHG2
s1 s3 XCHG
1 PUSHINT // price ctl domdata gc prices nhk lhk _321=1
housekeeping CALLDICT
send_ok CALLDICT
}> // price key lhk exp data ctl domdata gc prices nhk
10 BLKDROP //
}>
recv_external PROC:<{
// in_msg
DROP //
load_data INLINECALLDICT // _12 _13 _14 _15 _16 _17
NIP // ctl dd gc prices lhk
IFNOTJMP:<{ // ctl dd gc prices
ACCEPT
32 PUSHPOW2DEC // ctl dd gc prices _9=4294967295
NOW // ctl dd gc prices _9=4294967295 _10
store_data CALLDICT
}> // ctl dd gc prices
4 BLKDROP //
}>
dnsdictlookup PROCREF:<{
// domain nowtime
OVER // domain nowtime domain
SBITREFS // domain nowtime bits refs
OVER
7 PUSHINT // domain nowtime bits refs bits _6=7
AND // domain nowtime bits refs _7
OR // domain nowtime bits _8
30 THROWIF
DUP // domain nowtime bits bits
IFNOTJMP:<{ // domain nowtime bits
3 BLKDROP //
0 PUSHINT // _10=0
PUSHNULL // _10=0 _11
OVER // _10=0 _11 _12=0
PUSHNULL // _10=0 _11 _12=0 _13
}> // domain nowtime bits
s2 PUSH
8 PUSHINT // domain nowtime bits domain _15=8
SDCUTLAST // domain nowtime bits _16
8 PLDU // domain nowtime bits domain_last_byte
IF:<{ // domain nowtime bits
0 PUSHINT // domain nowtime bits _19=0
NEWC // domain nowtime bits _19=0 _20
s0 s4 XCHG2 // _19=0 nowtime bits _20 domain
STSLICER // _19=0 nowtime bits _21
s1 s3 XCHG // bits nowtime _19=0 _21
8 STU // bits nowtime _23
ENDC // bits nowtime _24
CTOS // bits nowtime domain
s0 s2 XCHG // domain nowtime bits
8 ADDCONST // domain nowtime bits
}> // domain nowtime bits
DUP // domain nowtime bits bits
8 EQINT // domain nowtime bits _29
IFJMP:<{ // domain nowtime bits
3 BLKDROP //
0 PUSHINT // _30=0
PUSHNULL // _30=0 _31
OVER // _30=0 _31 _32=0
PUSHNULL // _30=0 _31 _32=0 _33
}> // domain nowtime bits
c4 PUSH // domain nowtime bits _35
CTOS // domain nowtime bits ds
LDREF // domain nowtime bits _87 _86
NIP // domain nowtime bits ds
LDDICT // domain nowtime bits _89 _88
DROP // domain nowtime bits root
PUSHNULL // domain nowtime bits root val
-1 PUSHINT // domain nowtime bits root val tail_bits=-1
s5 PUSH // domain nowtime bits root val tail_bits=-1 tail
s0 s4 XCHG // domain nowtime tail root val tail_bits=-1 bits
3 RSHIFT# // domain nowtime tail root val tail_bits=-1 _49
REPEAT:<{ // domain nowtime tail root val tail_bits
s0 s3 XCHG // domain nowtime tail_bits root val tail
8 LDU // domain nowtime tail_bits root val _50 tail
SWAP // domain nowtime tail_bits root val tail _50
0 EQINT // domain nowtime tail_bits root val tail _54
IF:<{ // domain nowtime tail_bits root val tail
DUP // domain nowtime tail_bits root val tail tail
SBITS // domain nowtime tail_bits root val tail _56
s6 s(-1) PUXC // domain nowtime tail_bits root val tail domain _56
SDSKIPLAST // domain nowtime tail_bits root val tail _57
SHA256U // domain nowtime tail_bits root val tail _58
32 RSHIFT# // domain nowtime tail_bits root val tail key
s3 PUSH
224 PUSHINT // domain nowtime tail_bits root val tail key root _65
DICTUGET
NULLSWAPIFNOT // domain nowtime tail_bits root val tail v found?
IF:<{ // domain nowtime tail_bits root val tail v
DUP // domain nowtime tail_bits root val tail v v
32 PLDU // domain nowtime tail_bits root val tail v _68
s6 PUSH // domain nowtime tail_bits root val tail v _68 nowtime
GEQ // domain nowtime tail_bits root val tail v _69
IF:<{ // domain nowtime tail_bits root val tail v
s2 POP
s3 POP // domain nowtime tail root val
s2 PUSH // domain nowtime tail root val tail
SBITS // domain nowtime tail root val tail_bits
s0 s3 XCHG // domain nowtime tail_bits root val tail
}>ELSE<{
DROP // domain nowtime tail_bits root val tail
}>
}>ELSE<{
DROP // domain nowtime tail_bits root val tail
}>
}> // domain nowtime tail_bits root val tail
s0 s3 XCHG // domain nowtime tail root val tail_bits
}>
2 2 BLKDROP2
s2 POP // domain tail_bits val
DUP // domain tail_bits val val
ISNULL // domain tail_bits val _71
IFJMP:<{ // domain tail_bits val
3 BLKDROP //
0 PUSHINT // _72=0
PUSHNULL // _72=0 _73
OVER // _72=0 _73 _74=0
PUSHNULL // _72=0 _73 _74=0 _75
}> // domain tail_bits val
32 LDU // domain tail_bits _76 val
LDREF // domain tail_bits _76 _97 _96
DROP // domain tail_bits _76 _79
s2 PUSH // domain tail_bits _76 _79 tail_bits
0 EQINT // domain tail_bits _76 _79 _82
s4 s3 XCHG2 // _79 _82 _76 domain tail_bits
SDSKIPLAST // _79 _82 _76 _83
s3 s3 s0 XCHG3 // _76 _79 _82 _83
}>
dnsresolve PROC:<{
// domain category
NOW // domain category _6
s1 s2 XCHG // category domain _6
dnsdictlookup INLINECALLDICT // category exp cat_table exact? pfx
s0 s3 XCHG // category pfx cat_table exact? exp
IFNOTJMP:<{ // category pfx cat_table exact?
4 BLKDROP //
0 PUSHINT // _8=0
PUSHNULL // _8=0 _9
}> // category pfx cat_table exact?
IFNOT:<{ // category pfx cat_table
-1 PUSHINT
s3 POP // category=-1 pfx cat_table
}> // category pfx cat_table
SWAP // category cat_table pfx
SBITS // category cat_table pfx_bits
s2 PUSH // category cat_table pfx_bits category
IFJMP:<{ // category cat_table pfx_bits
-ROT
16 PUSHINT // pfx_bits category cat_table _14=16
DICTIGETOPTREF // pfx_bits cat_found
}> // category cat_table pfx_bits
s2 POP // pfx_bits cat_table
}>
getexpirationx PROC:<{
// domain nowtime
dnsdictlookup INLINECALLDICT // _7 _8 _9 _10
3 BLKDROP // exp
}>
getexpiration PROC:<{
// domain
NOW // domain _1
getexpirationx INLINECALLDICT // _2
}>
getstdperiod PROC:<{
//
load_prices INLINECALLDICT // _5 _6 _7 _8
3 BLKDROP // stdper
}>
getppr PROC:<{
//
load_prices INLINECALLDICT // _5 _6 _7 _8
s2 s3 XCHG
3 BLKDROP // ppr
}>
getppc PROC:<{
//
load_prices INLINECALLDICT // _5 _6 _7 _8
s1 s3 XCHG
3 BLKDROP // ppc
}>
getppb PROC:<{
//
load_prices INLINECALLDICT // _5 _6 _7 _8
s0 s3 XCHG
3 BLKDROP // ppb
}>
calcprice PROC:<{
// domain val
load_prices INLINECALLDICT // domain val _8 _9 _10 _11
2 2 BLKDROP2 // domain val ppc ppb
calcprice_internal INLINECALLDICT // _7
}>
calcregprice PROC:<{
// domain val
load_prices INLINECALLDICT // domain val _9 _10 _11 _12
s3 POP // domain val ppb ppr ppc
s3 s4 XCHG
s4 s0 s4 XCHG3 // ppr domain val ppc ppb
calcprice_internal INLINECALLDICT // ppr _7
ADD // _8
}>
}END>c

View File

@ -0,0 +1 @@
with_tvm_code("dns-manual", "te6ccgECGAEAAswAART/APSkE/S88sgLAQIBIAIDAgFIBAUC6vLbPAWDCNcYIPkBAdMf0z/4I6ofUyC58mNTKoBA9A5voTHyYFKUuvKiVBNG+RDyo/gAItcLBcAzmDQBdtch0/8wjoVa2zxAA+IDgyWhyEAHgED0Q44aIIBA9JZvpWwSIJQwUwe53iCTMzUBkmwh4rPmbBXwBBESAgLFBgcCASAMDQIBzwgJAAiqgl8DAgFICgsAIdAmRlj4nln+X/+gB6AGT2qkAAUXwOAAFzI9ADJ0EEz9HDyoYAAXvZznaiaGmvmOuF/8AgEgDg8AEbs3PtRNDXCx+AP5ujDCHXSSCUXwNwbeEgd7DyXiJ41yLXCweecMhQBM8WE8sHydACpgjeIMAIlF8DcG3g2zwUXwQjcAOrApjTBwHAABOhAuQgbY6bXwMhyMsGJM8WydCECSIC2zwFpRWyIMEBFUMw5jM1IpRfBXBt4WwSxwCSfzLfAtdJpvkhgRFRAAFsAAkjEB4AKAEPRqABztRNDTH9M/0//0BPQE0QE0cFmOk9s8IMcBmyDXSpPUMNCSfzPi3iLmMDETBPbTBSHBCo4sIZEx4SHAAZcx0wfUAvsA4AHACY4U1CH7BO1DAtDtHu1TVGID8QaC8gDg8i3gcCLBFJQw0g8B3m1tJMEeit4kwRSOkSWECSPbPDMClTLHAPKjkVvi3iTAC44TNAL0BFAkgBD0bjAQI4QJWfABAeAkwAyK4DAUFRYXAIQxAtMAAcABk9QB0JjTBQGqAtcYAeIg10nCD/KmIHjXItcLB/JocFMR10mpNgKY0wcBwAASoQHkMMjLBgHPFsnQUAMAIFn0qG+lIJQC9AQwkjJt4gIAKDQDgBD0WpkQI4QJQETwAQGSMDHiAGYxIsAVnDL0BBAjhAlQQvABAeAiwBaYMgKECfRzMAHgMDIgwB+TMPQE4MAgkm0B4PIsbQE=");

View File

@ -0,0 +1,477 @@
// automatically generated from `smartcont/stdlib.fc` `smartcont/dns-manual-code.fc`
PROGRAM{
DECLPROC pfxdict_set_ref
DECLPROC pfxdict_get_ref
DECLPROC load_data
DECLPROC store_data
DECLPROC recv_internal
1666 DECLMETHOD after_code_upgrade
DECLPROC process_op
DECLPROC process_ops
DECLPROC recv_external
111475 DECLMETHOD get_contract_id
78748 DECLMETHOD get_public_key
123660 DECLMETHOD dnsresolve
pfxdict_set_ref PROC:<{
// dict key_len key value
NEWC // dict key_len key value _6
STOPTREF // dict key_len key _7
ENDC // dict key_len key _8
CTOS // dict key_len key _9
s1 s3 s3 XCHG3 // _9 key dict key_len
PFXDICTSET // dict _5
33 THROWIFNOT
}>
pfxdict_get_ref PROCREF:<{
// dict key_len key
-ROT // key dict key_len
PFXDICTGETQ
NULLSWAPIFNOT2 // pfx val tail succ
DUP // pfx val tail succ succ
IF:<{ // pfx val tail succ
s0 s2 XCHG // pfx succ tail val
LDOPTREF // pfx succ tail _18 _17
DROP // pfx succ tail _9
}>ELSE<{ // pfx val tail succ
s2 POP // pfx succ tail
PUSHNULL // pfx succ tail _9
}> // pfx succ tail res
s0 s2 XCHG // pfx res tail succ
}>
load_data PROCREF:<{
//
c4 PUSH // _1
CTOS // cs
32 LDU // _4 cs
64 LDU // _4 _7 cs
256 LDU // _4 _7 _10 cs
LDDICT // _4 _7 _10 _13 cs
LDDICT // res res res res res cs
ENDS
}>
store_data PROC:<{
// contract_id last_cleaned public_key root old_queries
s0 s4 XCHG
NEWC // old_queries last_cleaned public_key root contract_id _5
32 STU // old_queries last_cleaned public_key root _7
s1 s3 XCHG // old_queries root public_key last_cleaned _7
64 STU // old_queries root public_key _9
256 STU // old_queries root _11
STDICT // old_queries _12
STDICT // _13
ENDC // _14
c4 POP
}>
recv_internal PROC:<{
// msg_value in_msg_cell in_msg
3 BLKDROP //
}>
after_code_upgrade PROC:<{
// root ops old_code
3 BLKDROP //
}>
process_op PROCREF:<{
// root ops
6 LDU // root op ops
OVER // root op ops op
10 LESSINT // root op ops _7
IFJMP:<{ // root op ops
OVER // root op ops op
IFNOTJMP:<{ // root op ops
NIP // root ops
}> // root op ops
OVER // root op ops op
1 EQINT // root op ops _9
IFJMP:<{ // root op ops
NIP // root ops
8 LDU // root mode ops
LDREF // root mode _14 ops
s0 s2 XCHG // root ops _14 mode
SENDRAWMSG
}> // root op ops
SWAP // root ops op
9 EQINT // root ops _18
IFJMP:<{ // root ops
LDREF // root new_code ops
OVER // root new_code ops new_code
SETCODE
c3 PUSH // root new_code ops old_code
s0 s2 XCHG // root old_code ops new_code
CTOS // root old_code ops _25
BLESS // root old_code ops _26
c3 POP
s2 s(-1) s1 PU2XC // root ops root ops old_code
after_code_upgrade CALLDICT
0 THROW
}> // root ops
45 THROW
}> // root op ops
0 PUSHINT // root op ops cat=0
s2 PUSH // root op ops cat=0 op
20 LESSINT // root op ops cat=0 _36
IF:<{ // root op ops cat=0
DROP // root op ops
16 LDI // root op cat ops
SWAP // root op ops cat
}> // root op ops cat
PUSHNULL // root op ops cat name
PUSHNULL // root op ops cat name cat_table
s4 PUSH // root op ops cat name cat_table op
30 LESSINT // root op ops cat name cat_table _45
IF:<{ // root op ops cat name cat_table
NIP // root op ops cat cat_table
s0 s2 XCHG // root op cat_table cat ops
1 LDU // root op cat_table cat _47 ops
SWAP // root op cat_table cat ops _47
1 EQINT // root op cat_table cat ops is_name_ref
IF:<{ // root op cat_table cat ops
LDREF // root op cat_table cat _52 ops
SWAP // root op cat_table cat ops _52
CTOS // root op cat_table cat ops name
}>ELSE<{ // root op cat_table cat ops
6 LDU // root op cat_table cat _56 ops
SWAP // root op cat_table cat ops _56
3 LSHIFT# // root op cat_table cat ops name_len
LDSLICEX // root op cat_table cat name ops
SWAP // root op cat_table cat ops name
}>
DUP // root op cat_table cat ops name name
SBITS // root op cat_table cat ops name _64
15 GTINT // root op cat_table cat ops name _66
38 THROWIFNOT
DUP
8 PUSHINT // root op cat_table cat ops name name _69=8
SDCUTLAST // root op cat_table cat ops name _70
8 PLDU // root op cat_table cat ops name name_last_byte
40 THROWIF
0 PUSHINT // root op cat_table cat ops name zeros=0
s1 s1 PUSH2 // root op cat_table cat ops name zeros=0 cname cname
SBITS // root op cat_table cat ops name zeros=0 cname _78
3 RSHIFTC# // root op cat_table cat ops name zeros=0 cname _80
REPEAT:<{ // root op cat_table cat ops name zeros cname
8 LDU // root op cat_table cat ops name zeros c cname
SWAP // root op cat_table cat ops name zeros cname c
0 EQINT // root op cat_table cat ops name zeros cname _86
s1 s2 XCHG // root op cat_table cat ops name cname zeros _86
SUB // root op cat_table cat ops name cname zeros
SWAP // root op cat_table cat ops name zeros cname
}>
DROP // root op cat_table cat ops name zeros
NEWC // root op cat_table cat ops name zeros _88
7 STU // root op cat_table cat ops name _90
SWAP // root op cat_table cat ops _90 name
STSLICER // root op cat_table cat ops _91
ENDC // root op cat_table cat ops _92
CTOS // root op cat_table cat ops name
s0 s3 XCHG2 // root op ops cat name cat_table
}> // root op ops cat name cat_table
s4 PUSH // root op ops cat name cat_table op
20 LESSINT // root op ops cat name cat_table _95
IF:<{ // root op ops cat name cat_table
s5 PUSH
10 PUSHPOW2DEC
s3 PUSH // root op ops cat name cat_table root _100=1023 name
pfxdict_get_ref INLINECALLDICT // root op ops cat name cat_table _168 _169 _170 _171
s3 POP // root op ops cat name cat_table succ val tail
s0 s2 XCHG // root op ops cat name cat_table tail val succ
IF:<{ // root op ops cat name cat_table tail val
s2 POP // root op ops cat name val tail
SEMPTY // root op ops cat name val _103
35 THROWIFNOT // root op ops cat name cat_table
}>ELSE<{
2DROP // root op ops cat name cat_table
}>
}> // root op ops cat name cat_table
s4 PUSH // root op ops cat name cat_table op
11 EQINT // root op ops cat name cat_table _106
IFJMP:<{ // root op ops cat name cat_table
s4 POP // root cat_table ops cat name
s0 s2 XCHG // root cat_table name cat ops
LDOPTREF // root cat_table name cat new_value ops
s2 s4 XCHG2
16 PUSHINT // root ops name new_value cat cat_table _111=16
DICTISETGETOPTREF // root ops name _174 _175
DROP // root ops name cat_table
s2 s3 XCHG
10 PUSHPOW2DEC
-ROT // ops root _114=1023 name cat_table
pfxdict_set_ref CALLDICT // ops root
SWAP // root ops
}> // root op ops cat name cat_table
s4 PUSH // root op ops cat name cat_table op
12 EQINT // root op ops cat name cat_table _117
IFJMP:<{ // root op ops cat name cat_table
s4 POP // root cat_table ops cat name
s0 s3 XCHG
16 PUSHINT // root name ops cat cat_table _119=16
DICTIDEL // root name ops cat_table _118
IF:<{ // root name ops cat_table
s2 s3 XCHG
10 PUSHPOW2DEC
s0 s4 s4 XCHG3 // ops root _122=1023 name cat_table
pfxdict_set_ref CALLDICT // ops root
SWAP // root ops
}>ELSE<{
DROP
NIP // root ops
}>
}> // root op ops cat name cat_table
DROP
NIP // root op ops name
s2 PUSH // root op ops name op
21 EQINT // root op ops name _125
IFJMP:<{ // root op ops name
s2 POP // root name ops
LDOPTREF // root name new_cat_table ops
s2 s3 XCHG
10 PUSHPOW2DEC
s4 s2 XCHG2 // ops root _130=1023 name new_cat_table
pfxdict_set_ref CALLDICT // ops root
SWAP // root ops
}> // root op ops name
s2 PUSH // root op ops name op
22 EQINT // root op ops name _133
IFJMP:<{ // root op ops name
s2 POP // root name ops
s0 s2 XCHG
10 PUSHPOW2DEC // ops name root _135=1023
PFXDICTDEL // ops _180 _181
DROP // ops root
SWAP // root ops
}> // root op ops name
DROP
s2 POP // ops op
DUP // ops op op
31 EQINT // ops op _138
IFJMP:<{ // ops op
DROP // ops
LDOPTREF // new_tree_root ops
}> // ops op
32 EQINT // ops _143
IFJMP:<{ // ops
PUSHNULL // ops _144
SWAP // _144 ops
}> // ops
44 THROW
PUSHNULL // ops _147
SWAP // _147 ops
}>
process_ops PROCREF:<{
// root ops
FALSE // root ops stop
-ROT // stop root ops
UNTIL:<{
process_op INLINECALLDICT // stop root ops
DUP // stop root ops ops
SDEMPTY // stop root ops _9
IF:<{ // stop root ops
DUP // stop root ops ops
SREFS // stop root ops _10
IF:<{ // stop root ops
LDREF // stop root _18 _17
DROP // stop root _11
CTOS // stop root ops
}>ELSE<{ // stop root ops
TRUE
s3 POP // stop root ops
}>
}> // stop root ops
s2 PUSH // stop root ops stop
}> // stop root ops
DROP
NIP // root
}>
recv_external PROC:<{
// in_msg
load_data INLINECALLDICT // in_msg contract_id last_cleaned public_key root old_queries
s0 s5 XCHG
9 PUSHPOW2 // old_queries contract_id last_cleaned public_key root in_msg _9=512
LDSLICEX // old_queries contract_id last_cleaned public_key root signature in_msg
DUP // old_queries contract_id last_cleaned public_key root signature in_msg in_msg
HASHSU // old_queries contract_id last_cleaned public_key root signature in_msg shash
SWAP // old_queries contract_id last_cleaned public_key root signature shash in_msg
32 LDU // old_queries contract_id last_cleaned public_key root signature shash _15 in_msg
64 LDU // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg
NOW // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg _22
32 LSHIFT# // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound
s2 s0 PUSH2 // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound query_id bound
LESS // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound _26
35 THROWIF
s2 s10 PUSH2
64 PUSHINT // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound query_id old_queries _30=64
DICTUGET
NULLSWAPIFNOT // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound _84 _85
NIP // old_queries contract_id last_cleaned public_key root signature shash query_contract query_id in_msg bound found?
32 THROWIF
s9 s3 PUXC // old_queries contract_id last_cleaned public_key root signature shash bound query_id in_msg contract_id query_contract
EQUAL // old_queries contract_id last_cleaned public_key root signature shash bound query_id in_msg _35
34 THROWIFNOT
s3 s4 s6 XC2PU // old_queries contract_id last_cleaned public_key root in_msg query_id bound shash signature public_key
CHKSIGNU // old_queries contract_id last_cleaned public_key root in_msg query_id bound _38
35 THROWIFNOT
ACCEPT
s2 PUSH // old_queries contract_id last_cleaned public_key root in_msg query_id bound in_msg
6 PLDU // old_queries contract_id last_cleaned public_key root in_msg query_id bound op
51 EQINT // old_queries contract_id last_cleaned public_key root in_msg query_id bound _45
IF:<{ // old_queries contract_id last_cleaned public_key root in_msg query_id bound
s4 POP // old_queries contract_id last_cleaned bound root in_msg query_id
SWAP
6 PUSHINT // old_queries contract_id last_cleaned bound root query_id in_msg _47=6
SDSKIPFIRST // old_queries contract_id last_cleaned bound root query_id in_msg
256 LDU // old_queries contract_id last_cleaned bound root query_id _87 _86
DROP // old_queries contract_id last_cleaned bound root query_id public_key
}>ELSE<{ // old_queries contract_id last_cleaned public_key root in_msg query_id bound
2SWAP // old_queries contract_id last_cleaned public_key query_id bound root in_msg
process_ops INLINECALLDICT // old_queries contract_id last_cleaned public_key query_id bound root
s0 s0 s3 XCHG3 // old_queries contract_id last_cleaned bound root query_id public_key
}>
s0 s3 XCHG
38 PUSHPOW2 // old_queries contract_id last_cleaned public_key root query_id bound _55
SUB // old_queries contract_id last_cleaned public_key root query_id bound
NEWC // old_queries contract_id last_cleaned public_key root query_id bound _58
s0 s0 s7 XCHG3
64 PUSHINT // bound contract_id last_cleaned public_key root _58 query_id old_queries _59=64
DICTUSETB // bound contract_id last_cleaned public_key root old_queries
UNTIL:<{
DUP
64 PUSHINT // bound contract_id last_cleaned public_key root old_queries old_queries _66=64
DICTUREMMIN
NULLSWAPIFNOT2 // bound contract_id last_cleaned public_key root old_queries _88 _90 _89 _91
1 2 BLKDROP2 // bound contract_id last_cleaned public_key root old_queries old_queries' i f
DUP // bound contract_id last_cleaned public_key root old_queries old_queries' i f f
IF:<{ // bound contract_id last_cleaned public_key root old_queries old_queries' i f
DROP // bound contract_id last_cleaned public_key root old_queries old_queries' i
s0 s7 PUSH2 // bound contract_id last_cleaned public_key root old_queries old_queries' i i bound
LESS // bound contract_id last_cleaned public_key root old_queries old_queries' i f
}> // bound contract_id last_cleaned public_key root old_queries old_queries' i f
DUP // bound contract_id last_cleaned public_key root old_queries old_queries' i f f
IF:<{ // bound contract_id last_cleaned public_key root old_queries old_queries' i f
s3 POP
s5 POP // bound contract_id last_cleaned public_key root f old_queries
SWAP // bound contract_id last_cleaned public_key root old_queries f
}>ELSE<{
2 1 BLKDROP2 // bound contract_id last_cleaned public_key root old_queries f
}>
NOT // bound contract_id last_cleaned public_key root old_queries _71
}> // bound contract_id last_cleaned public_key root old_queries
1 5 BLKDROP2 // contract_id last_cleaned public_key root old_queries
store_data CALLDICT
}>
get_contract_id PROC:<{
//
c4 PUSH // _0
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
96 LDU // _11 _10
NIP // cs
256 PLDU // _9
}>
dnsresolve PROC:<{
// subdomain category
OVER // subdomain category subdomain
SBITS // subdomain category bits
DUP // subdomain category bits bits
IFNOTJMP:<{ // subdomain category bits
3 BLKDROP //
0 PUSHINT // _4=0
PUSHNULL // _4=0 _5
}> // subdomain category bits
DUP
7 PUSHINT // subdomain category bits bits _7=7
AND // subdomain category bits _8
30 THROWIF
s2 PUSH
8 PUSHINT // subdomain category bits subdomain _11=8
SDCUTLAST // subdomain category bits _12
8 PLDU // subdomain category bits name_last_byte
IF:<{ // subdomain category bits
0 PUSHINT // subdomain category bits _15=0
NEWC // subdomain category bits _15=0 _16
s0 s4 XCHG2 // _15=0 category bits _16 subdomain
STSLICER // _15=0 category bits _17
s1 s3 XCHG // bits category _15=0 _17
8 STU // bits category _19
ENDC // bits category _20
CTOS // bits category subdomain
s0 s2 XCHG // subdomain category bits
8 ADDCONST // subdomain category bits
}> // subdomain category bits
DUP // subdomain category bits bits
8 EQINT // subdomain category bits _25
IFJMP:<{ // subdomain category bits
3 BLKDROP //
0 PUSHINT // _26=0
PUSHNULL // _26=0 _27
}> // subdomain category bits
load_data INLINECALLDICT // subdomain category bits _80 _81 _82 _83 _84
s1 s4 XCHG
4 BLKDROP // subdomain category bits root
s3 PUSH // subdomain category bits root cname
0 PUSHINT // subdomain category bits root cname zeros=0
s0 s3 XCHG // subdomain category zeros=0 root cname bits
3 RSHIFT# // subdomain category zeros=0 root cname _38
REPEAT:<{ // subdomain category zeros root cname
8 LDU // subdomain category zeros root c cname
SWAP // subdomain category zeros root cname c
0 EQINT // subdomain category zeros root cname _44
s1 s3 XCHG // subdomain category cname root zeros _44
SUB // subdomain category cname root zeros
s0 s2 XCHG // subdomain category zeros root cname
}>
DUP // subdomain category zeros root cname pfx
PUSHNULL // subdomain category zeros root tail pfx val
UNTIL:<{
3 BLKDROP // subdomain category zeros root
OVER
NEWC // subdomain category zeros root zeros _51
7 STU // subdomain category zeros root _53
s4 PUSH // subdomain category zeros root _53 subdomain
STSLICER // subdomain category zeros root _54
ENDC // subdomain category zeros root _55
CTOS // subdomain category zeros root pfxname
10 PUSHPOW2DEC // subdomain category zeros root pfxname _58=1023
s2 PUSH
s0 s2 XCHG // subdomain category zeros root root _58=1023 pfxname
pfxdict_get_ref INLINECALLDICT // subdomain category zeros root pfx val tail succ
s0 s5 XCHG // subdomain category succ root pfx val tail zeros
DEC // subdomain category succ root pfx val tail _61
s1 s5 XCHG // subdomain category tail root pfx val succ _61
XOR // subdomain category tail root pfx val zeros
DUP // subdomain category tail root pfx val zeros zeros
1 LESSINT // subdomain category tail root pfx val zeros _64
s1 s5 XCHG
s3 s3 s0 XCHG3 // subdomain category zeros root tail pfx val _64
}> // subdomain category zeros root tail pfx val
s3 POP
s5 POP // pfx category zeros val tail
s2 PUSH // pfx category zeros val tail zeros
IFNOTJMP:<{ // pfx category zeros val tail
5 BLKDROP //
0 PUSHINT // _65=0
PUSHNULL // _65=0 _66
}> // pfx category zeros val tail
1 2 BLKDROP2 // pfx category val tail
SEMPTY // pfx category val _68
IFNOT:<{ // pfx category val
-1 PUSHINT
s2 POP // pfx category=-1 val
}> // pfx category val
s0 s2 XCHG // val category pfx
SBITS // val category _71
-7 ADDCONST // cat_table category pfx_bits
OVER // cat_table category pfx_bits category
0 EQINT // cat_table category pfx_bits _76
IFJMP:<{ // cat_table category pfx_bits
NIP // cat_table pfx_bits
SWAP // pfx_bits cat_table
}> // cat_table category pfx_bits
s0 s2 XCHG
16 PUSHINT // pfx_bits category cat_table _78=16
DICTIGETOPTREF // pfx_bits cat_found
}>
}END>c

View File

@ -1 +1 @@
with_tvm_code("elector-code", "te6ccgECVQEACskAART/APSkE/Sg8sgLAQIBIAIDAgFIBAUAUaX//xh2omh6AnoCETdKrPgN+SBOKjgQ+At5ICz4DPkgcXgL+SB4DRhAAgLFBgcCASAKCwIBywgJACyqgjGCEE5Db2SCEM5Db2RwQzCAQPAGAgEgEBECASAzNAIDeqAMDQIBbg4PACSqB+1E0PQFIG6SMHCU0NcLH+IAQqss7UTQ9AUgbpJbcODwAxAmXwaDB/QOb6GT+gAwkjBw4gBzsKV7UTQ9AUgbpIwbeDwAxAmXwZthP+OHiKDB/R+b6FvoSCcAvoAMFIQbwJQA28Cklow4gGzEuYwMYAAzs+A7UTQ9AQx9AQwgwf0Dm+hk/oAMJIwcOKACASASEwIBICMkAgEgFBUCASAdHgIBIBYXAgEgGxwBASAYACE7UTQ9AT0BPQE+gDTH9P/0YAL8AdDTAwFxsJJfA+D6QDAhxwCUMQHwEOAB0x8hwACUWwHwEODTPyKCEE5zdEu6lTIQI/AL4DQhghBHZXQkupMT8BHgIYIQTkNvZLqOGVRSRPASloIQzkNvZJKEH+JwEDRDMIBA8AbgIYIQ7nZPS7oighDudk9vulIQsYrgMDMgGRoADDIQIwHwDwAkgx6wm4QfcBA0QzCAQPAG4V8DACkyBb0ABT0ABL0AAH6Assfy//J7VSAAITQ0x/TH/oA+gD0BNIA0gDRgAgEgHyACASAhIgArMgXyx8Vyx9QA/oCAfoC9ADKAMoAyYAAdIAP+DPQ0h/SH9If1wofgAEUcIAYyMsFUAfPFlj6AhXLahPLH8s/IcL/kssfkTHiyQH7AIAAbIIQ7m9FTHBDMIBA8AaACASAlJgIBIC0uAgEgJygCASApKgAjIIQ83RITIIQO5rKAEMwcvAGgAEcghBOVlNUcIIAxP/IyxAVy/+DHfoCFMtqE8sfEss/zMlx+wCAAMxTEoMH9A5voZT6ADCgkTDiyAH6AgKDB/RDgAQEgKwH+I/pE7UTQ9AQhbgSkFLGXEDVfBXDwB+AE0//TH9Mf0//UAdCDCNcZAdGCEGVMUHTIyx9SQMsfUjDLH1Jgy/9SIMv/ydBRFfkRlxBoXwhx8AfhIYMPuZcQaF8IdvAH4AfwAzEF/iANghA7msoAoSCqCyO5mBC8XwwxcvAH4FEioCwA/lF9vZcQrF8Mc/AH4ASXEJtfC3DwB+BTY4MH9A5voSCfMPoAWaAB0z8x0/8wUoC9kTHilxCbXwt08AfgUwG5lxCbXwt18AfgIPKs+AD4I8hY+gLLHxTLHxbL/xjL/0A3gwf0Q3AQVxA0ECMQJnDwBMj0AAHPFsntVCCTcPAI4FsCASAvMAIBIDEyAHkcCB/jjAkgwf0fG+hb6EgjhwC0//TPzH6ANIA0ZQxUTOgl1QYiPAKBwPiUEOgk1BCMOIBsxPmMDMBuvK7gAKEcFMAf447JoMH9HxvoW+hII4nAtP/0z8x+gDSANGUMVEzoI4RVHcIqYRRZqBSF6BLsPAKCQPiUFOgk1BSMOIBsxTmMDUDulMhu7DyuxKgAaGAAVwBgCD0Zm+hkjBw4dM/MdP/MfQE+gD6APQEMdEgwgCUEDTwDZUwECPwDOISgAKMMgL6RHD4M9DXC//tRND0BASkWr2xIW6xkl8E4PADBV8FUhW9BLMUsZJfA+D4AAGRW44d9AT0BPoAQzTwDnDIygAT9AD0AFmg+gIBzxbJ7VTigAgEgNTYCAUhPUAIBIDc4AgEgPT4CASA5OgIBIDs8AKU8AEH+kQBpLEhwACxlwWgVRMB8ALgUwKAIPQOb6GOJ9M/0//0BPoA+gALoMgVyz8Ty//0AAH6AgH6AlAGzxYBgCBURkT0Q5QwBaAB4hA1QUPwAoADZDEh+kQBpJ8wghD////+cBA0E4BA8Abg7UTQ9AT0BFAzgwf0Zm+hjhBfBIIQ/////nAQNBOAQPAG4TYF+gDRyBL0ABX0AAHPFsntVIIQ+W9zJHCAGMjLBVAEzxZQBPoCEstqEssfyz/JgED7AIABpHD4MyBuk18EcODQ1wv/I/pEAaQCvbGTXwNw4PgAAdQh+wQgxwCSXwSZAe1TAfEGgvIA4n+AAAxwgAgEgP0ACASBKSwA1HACjhMCbyIhbxACbxEkqKsPErYIEqBY5DAxgAQEgQQP+gBD4M9DTD9MPMdMP0XG2CXBtf45GKYMH9HxvoW+hII4wAvoA0x/TH9P/0//RA6PIFct/FMofUkDL/8nQURq2CMjLHxPL/8v/QBSBAaD0QQOklBA0WjDiAbNDMOYwNFi2CFMBuZdfB21wbVMR4G2K5jM0pVySbxHkcCCK5jIyNEJDRABqA4EBoPSSb6FvoSCOIAHTf1EZtggB0x8x1wv/A9Mf0/8x1wv/QTAUbwRQBW8Ck0YWW+IEsxQASgJvIgFvEASkU0i+jhBUZQbwFFMCvJMyMiKSEzDik1A0MOJTNr4BZDQiwABSQ7kSsZdfBG1wbVMR4CD+ICKlkm8R5G8QbxBwUwBtbYrmNDQ0NlJVuvKxQzQBRQT+Bm8iAW8kUx2DB/QOb6HyvfoAMdM/MdcL/1OcuY5aUTqoqw9SQLYIUUShJKo7LqkEUZWgUYmgghCOgSeKI5KAc5KAU+LIywfLH1JAy/9SoMs/I5MTy/+TUAMw4gGAEFRLmfRDcCTIy/8ayz9QBfoCGMoAQBqDB/RDiuIjioriBEZHSEkAEAsQeBBGA18DAAhMg/AKAAZMg1sAFqQqbhBbEFcVEDQSAQEgTAGtPABgCL4M/kAUwG6k18HcOAiji9TJIAg9A5voY4f0x8xINMf0/8wUAS68rn4I1ADoMjLH1jPFkAEgCD0Q5QVE18D4pNEFFvif4rmIG6SMHCQ4lAD8AJ/gTgH8AfADNPgjJbmTXwhw4HD4M26UXwjwE+CAEfgz0PoA+gD6ANMf0VNhuZRfDPAT4ASUXwvwE+AGk18KcOAQOChRMlB38BUgwAAgsysGEFsQShA5Td3wBCOOFDEyMjIyMsgS9AD0AAHPFsntVPAT4fAFMvgjAaCmxCm2CYAQ+DPQTQDQgBDXIdcLD1JwtghTE6CAEsjLB1Iwyx/LHxjLDxfLDxrLPxP0AMlw+DPQ1wv/UxjwCQn0BHAL+QBQZKApoMjLHxnLHxLL/xX0AFAD+gJw+gIWygBANIAg9EPIE/QA9AD0AAHPFsntVH8ApCGAIPR8b6FvoSCOPwLTP9P/Uxe6ji00A/QE+gD6ACirAlGZoVApoMgVyz8Wy/8S9AAB+gIB+gJYzxYBgCBUQUT0Q3CWEDUQNF8D4pNDAzDisxICASBRUgIBIFNUABkIW6SW3CVAfkAAbrigAJUAfADBV8Fk18DcOEC9ARRMYAg9A5voZNfBHDhgEDXIdcL/4Ai+DMh8BiAJPgzWPAYsY4TcMjKABL0APQAAc8Wye1U8Bcwf+BfA3CAAkzwAX+OPiSAIPR8b6FvoSCOJALTHzD4I7tTFL2wjhExVBVE8A4UoFR2E1RzWPACcJRGFVBE4pYQNxZFBTDisxAmEEUU5gZfBm6zgAOEMYAk+DNukltw4XH4M9DXC//4KPpEAaQCvbGSW3DggCL4MyBuk18DcODwBTAyAtCAKNch1wsf+CNRE6FcuZNfBnDgXKHBPJExkTDigBH4M9D6ADADoP4gUgKhcG1wEEUQNHDwBMj0APQAAc8Wye1Uf4A==");
with_tvm_code("elector-code", "te6ccgECUwEACr8AART/APSkE/S88sgLAQIBIAIDAgFIBAUAUaX//xh2omh6AnoCETdKrPgN+SBOKjgQ+At5ICz4DPkgcXgL+SB4DRhAAgLFBgcCASAKCwIBywgJACqqgjGCEE5Db2SCEM5Db2RZcIBA8AYCASASEwIBIDM0AgN6oAwNAgFuEBECAWoODwBCqyztRND0BSBukltw4PADECZfBoMH9A5voZP6ADCSMHDiACO4ftRND0BSBukjBwlNDXCx/igAh7qu1E0PQFIG6YMHBUcABtUxHg8ANthP+OJySDB/R+b6UgjhgC+gDTHzHTH9P/0//RbwRSEG8CUANvAgKRMuIBs+YwM4AG2wpXtRND0BSBukjBt4PADECZfBm2E/44bIoMH9H5vpSCdAvoAMFIQbwJQA28CApEy4gGz5jAxgADOz4DtRND0BDH0BDCDB/QOb6GT+gAwkjBw4oAIBIBQVAgEgJCUCASAWFwIBIB4fAgEgGBkCASAcHQL3AHQ0wMBcbCSXwPg+kAwIccAlDEB8BDgAdMfIcAAlFsB8BDg0z8ighBOc3RLupUyECPwC+A0IYIQR2V0JLqTE/AR4CGCEE5Db2S6jhdUUkTwEpaCEM5Db2SShB/iQDNwgEDwBuAhghDudk9LuiKCEO52T2+6UhCxiuAwM4BobACE7UTQ9AT0BPQE+gDTH9P/0YAAKMkMA8A8AIiCDHrCZhB9AM3CAQPAG4V8DACkBcj0ABT0ABL0AAH6Assfy//J7VSAAITQ0x/TH/oA+gD0BNIA0gDRgAgEgICECASAiIwArAbIyx8Vyx9QA/oCAfoC9ADKAMoAyYAAdIAP+DPQ0h/SH9If1wofgAEUcIAYyMsFUAfPFlj6AhXLahPLH8s/IcL/kssfkTHiyQH7AIAAZIIQ7m9FTFlwgEDwBoAIBICYnAgEgLS4CASAoKQIBICorACEghDzdEhMWYIQO5rKAHLwBoABHIIQTlZTVHCCAMT/yMsQFcv/gx36AhTLahPLHxLLP8zJcfsAgADMUxKDB/QOb6GU+gAwoJEw4sgB+gICgwf0Q4AH3CP6RO1E0PQEIW4EpBSxlxA1XwVw8AfgBNP/0x/TH9P/1AHQgwjXGQHRghBlTFB0yMsfUkDLH1Iwyx9SYMv/UiDL/8nQURX5EZcQaF8IcfAH4SGDD7mXEGhfCHbwB+AH8AMxDYIQO5rKAKEgqgsjuZcQvV8NcvAH4FEioICwA+FF1vZcQrF8Mc/AH4AyXEJtfC3DwB+BTa4MH9A5voSCfMPoAWaAB0z8x0/8wUoC9kTHilxCbXwt08AfgUwG5lxCbXwt18AfgIPKs+AD4I8hY+gLLHxTLHxbL/xjL/0A4gwf0QxBFQTAWcHDwBMj0AFjPFsntVCCTcPAI4FsCASAvMAIBIDEyAHEcCB/jiwkgwf0fG+lII4dAtP/0z8x+gDSANGUMVEzoJdUGIjwCgcD4lBDoAORMuIBs+YwMwG68ruAAmRwUwB/jjcmgwf0fG+lII4oAtP/0z8x+gDSANGUMVEzoI4RVHcIqYRRZqBSF6BLsPAKCQPiUFOgBJEy4gGz5jA1A7pTIbuw8rsSoAGhgAFcAYAg9GZvoZIwcOHTPzHT/zH0BPoA+gD0BDHRIMIAlBA08A2VMBAj8AziEoACjDIC+kRw+DPQ1wv/7UTQ9AQEpFq9sSFusZJfBODwAwVfBVIVvQSzFLGSXwPg+AABkVuOHfQE9AT6AEM08A5wyMoAE/QA9ABZoPoCAc8Wye1U4oAIBIDU2AgFITU4CASA3OAIBID0+AgEgOToCASA7PAClPABB/pEAaSxIcAAsZgFoBA1VRLwAuBTAoAg9A5voY4m0z/T//QE+gD6AAugBMjLPxPL//QAAfoCAfoCUAbPFlQgU4Ag9EOUMAWgAeIQNUFD8AKAA0wxIfpEAaSeMIIQ/////kATcIBA8Abg7UTQ9AT0BFAzgwf0Zm+hn18EghD////+QBNwgEDwBuE2BfoA0QHI9AAV9AABzxbJ7VSCEPlvcyRwgBjIywVQBM8WUAT6AhLLahLLH8s/yYBA+wCAAbxw+DMgbpNfBHDg0NcL/yP6RAGkAr2xk18DcOD4AAHUIfsEIMcAkl8EnAHQ7R7tUwHxBoLyAOJ/gAAMcIAIBID9AAgEgSUoANRwAo4TAm8iIW8QAm8RJKirDxK2CBKgWOQwMYAP3IAQ+DPQ0w/TDzHTD9FxtglwbX+OQSmDB/R8b6UgjjIC+gDTH9Mf0//T/9EDowTIy38Uyh9SQMv/ydBRGrYIyMsfE8v/y/9AFIEBoPRBA6RDE5Ey4gGz5jA0WLYIUwG5l18HbXBtUxHgbYrmMzSlXJJvEeRwIIrmNjZbIoEFCQwBkA4EBoPSSb6UgjiEB039RGbYIAdMfMdcL/wPTH9P/MdcL/0EwFG8EUAVvAgSSbCHisxQASAJvIgFvEASkU0i+jhBUZQbwFFMCvJRsIiICkTDikTTiUza+EwFewABSQ7kSsZdfBG1wbVMR4FMBpZJvEeRvEG8QcFMAbW2K5jQ0NDZSVbrysVBEQxNEA/4GbyIBbyRTHYMH9A5vofK9+gAx0z8x1wv/U5y5jl1ROqirD1JAtghRRKEkqjsuqQRRlaBRiaCCEI6BJ4ojkoBzkoBT4sjLB8sfUkDL/1Kgyz8jlBPL/wKRM+JUIqiAEPRDcCTIy/8ayz9QBfoCGMoAQBqDB/RDCBBFExSK4iGKRUZHAAYDXwMACkwA8AoKARCK4gSkJG4VF0gAAlsB9QB8AM0+CMluZNfCHDgcPgzbpRfCPAT4IAR+DPQ+gD6APoA0x/RU2G5lF8M8BPgBJRfC/AT4AaTXwpw4CMQSVEyUHfwFSDAACCzKwYQWxBKEDlN3fAEI44QMWxSyPQA9AABzxbJ7VTwE+HwBTL4IwGgpsQptgmAEPgz0IEsBqTwAYAi+DP5AFMBupNfB3DgIo4vUySAIPQOb6GOINMfMSDTH9P/MFAEuvK5+CNQA6DIyx9YzxZABIAg9EMCkxNfA+KSbCHif4rmIG6SMHCQ4gHwAn+BMANCAENch1wsPUnC2CFMToIASyMsHUjDLH8sfGMsPF8sPGss/E/QAyXD4M9DXC/9TGPAJCfQEcAv5AFBkoCmgyMsfGcsfEsv/FfQAUAP6AnD6AhbKAEA0gCD0QwLI9AD0APQAAc8Wye1UfwCWI4Ag9HxvpSCOPALTP9P/UxW6ji40A/QE+gD6ACirAlGZoVApoATIyz8Wy/8S9AAB+gIB+gJYzxZUIAWAIPRDA3ABkl8D4pEy4gGzAgEgT1ACASBRUgAZCFukltwlQH5AAG64oACVAHwAwVfBZNfA3DhAvQEUTGAIPQOb6GTXwRw4YBA1yHXC/+AIvgzIfAYgCT4M1jwGLGOE3DIygAS9AD0AAHPFsntVPAXMH/gXwNwgAHs8AF/jjIkgCD0fG+lII4jAtMfMPgju1MUvbCOFTFUFUTwDhSgVHYTVHNY8AIDUFRwAd6RMuIBs+YGXwZus4ADdDGAJPgzbpJbcOFx+DPQ1wv/+Cj6RAGkAr2xkltw4IAi+DMgbpNfA3Dg8AUwMgLQgCjXIdcLH/gjUROhXLmTXwZw4FyhwTyRMZEw4oAR+DPQ+gAwA6BSAqFwbRA0ECNwcPAEyPQA9AABzxbJ7VR/g");

View File

@ -1 +1 @@
with_tvm_code("highload-wallet", "te6ccgEBBgEAhgABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==");
with_tvm_code("highload-wallet", "te6ccgEBCAEAlwABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQC48oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhYhgBD0eG+lIJgC0wfUMAH7AJEy4gGz5lsBpMjLH8sfy//J7VQABNAwAgFIBgcAF7s5ztRNDTPzHXC/+AARuMl+1E0NcLH4");

View File

@ -3,6 +3,7 @@ PROGRAM{
DECLPROC recv_internal
DECLPROC recv_external
85143 DECLMETHOD seqno
78748 DECLMETHOD get_public_key
recv_internal PROC:<{
// in_msg
DROP //
@ -44,8 +45,7 @@ PROGRAM{
OVER
16 PUSHINT // public_key stored_seqno stored_subwallet dict i dict _57=16
DICTIGETNEXT
NULLSWAPIFNOT
NULLSWAPIFNOT // public_key stored_seqno stored_subwallet dict cs i f
NULLSWAPIFNOT2 // public_key stored_seqno stored_subwallet dict cs i f
DUP // public_key stored_seqno stored_subwallet dict cs i f f
IF:<{ // public_key stored_seqno stored_subwallet dict cs i f
s0 s2 XCHG // public_key stored_seqno stored_subwallet dict f i cs
@ -76,4 +76,12 @@ PROGRAM{
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
64 LDU // _9 _8
NIP // cs
256 PLDU // _7
}>
}END>c

View File

@ -1 +1 @@
with_tvm_code("highoad-wallet-v2", "te6ccgEBBwEA1wABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQHu8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44YIYAQ9HhvoW+hIJgC0wfUMAH7AJEy4gGz5luDJaHIQDSAQPRDiuYxyBLLHxPLP8v/9ADJ7VQGAATQMABBoZfl2omhpj5jpn+n/mPoCaKkQQCB6BzfQmMktv8ld0fFADoggED0lm+hb6EyURCUMFMDud4gkjM2k0MTW+IBsw==");
with_tvm_code("highload-wallet-v2", "te6ccgEBCQEA5QABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQHq8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44WIYAQ9HhvpSCYAtMH1DAB+wCRMuIBs+ZbgyWhyEA0gED0Q4rmMQHIyx8Tyz/L//QAye1UCAAE0DACASAGBwAXvZznaiaGmvmOuF/8AEG+X5dqJoaY+Y6Z/p/5j6AmipEEAgegc30JjJLb/JXdHxQANCCAQPSWb6VsEiCUMFMDud4gkzM2AZJsIeKz");

View File

@ -3,6 +3,7 @@ PROGRAM{
DECLPROC recv_internal
DECLPROC recv_external
117746 DECLMETHOD processed?
78748 DECLMETHOD get_public_key
recv_internal PROC:<{
// in_msg
DROP //
@ -49,8 +50,7 @@ PROGRAM{
OVER
16 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i dict _62=16
DICTIGETNEXT
NULLSWAPIFNOT
NULLSWAPIFNOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f
NULLSWAPIFNOT2 // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f
DUP // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f f
IF:<{ // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f
s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i cs
@ -76,10 +76,9 @@ PROGRAM{
DUP
64 PUSHINT // last_cleaned public_key stored_subwallet bound old_queries old_queries _85=64
DICTUREMMIN
NULLSWAPIFNOT
NULLSWAPIFNOT // last_cleaned public_key stored_subwallet bound old_queries _126 _128 _127 _129
s2 POP // last_cleaned public_key stored_subwallet bound old_queries old_queries' f i
s1 s0 XCPU // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f
NULLSWAPIFNOT2 // last_cleaned public_key stored_subwallet bound old_queries _126 _128 _127 _129
1 2 BLKDROP2 // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
DUP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f
IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
DROP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i
s0 s3 PUSH2 // last_cleaned public_key stored_subwallet bound old_queries old_queries' i i bound
@ -89,16 +88,15 @@ PROGRAM{
IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
s3 POP
s6 POP // last_cleaned public_key stored_subwallet bound f old_queries
SWAP // last_cleaned public_key stored_subwallet bound old_queries f
}>ELSE<{
s3 s1 s3 XCHG3
2DROP // last_cleaned public_key stored_subwallet bound f old_queries
2 1 BLKDROP2 // last_cleaned public_key stored_subwallet bound old_queries f
}>
SWAP // last_cleaned public_key stored_subwallet bound old_queries f
NOT // last_cleaned public_key stored_subwallet bound old_queries _90
}> // last_cleaned public_key stored_subwallet bound old_queries
NIP // last_cleaned public_key stored_subwallet old_queries
NEWC // last_cleaned public_key stored_subwallet old_queries _91
s1 s2 XCHG // last_cleaned public_key old_queries stored_subwallet _91
SWAP
NEWC // last_cleaned public_key old_queries stored_subwallet _91
32 STU // last_cleaned public_key old_queries _93
s1 s3 XCHG // old_queries public_key last_cleaned _93
64 STU // old_queries public_key _95
@ -131,4 +129,12 @@ PROGRAM{
NEGATE // _24
}>
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
96 LDU // _11 _10
NIP // cs
256 PLDU // _9
}>
}END>c

View File

@ -1 +1 @@
with_tvm_code("multisig", "te6ccgECMAEAA2oAART/APSkE/Sg8sgLAQIBIAIDAgFICAkEwPIgxwCOgzDbPOCDCNcYIPkBAdMH2zwiwAAToVNhePQOb6Hyn9cL/0iQ+RDyoAP0BCD5AQHTP/gjqh9TILnyYVMngED0Dm+hECNUSADbPAquXLDyYrEBpPgAVDiTVHo5KxcvFgQEnts8VHCrU5rbPO1U+A9wJm5TqL6xmBA6EHlQdl8GiuIEgyWhjichgED0lm+hb6EyURCUMFMCud4glDQ2N3+XEEkQR0QUW+ICsxBXECXmMAMaHwUGAiowKkZTBts8UHegECQQN0EGU1bbPH8kGgEKipJfBeIHAQwQJNs87VQfAgLNCgsCASAbHAIBIAwNAgEgEhMCASAODwIBIBARAAMMIAEBIC8BASAfAQEgJAIBIBQVAgEgGBkBASAWAQEgFwA4jhXSAAHyo9MHWNcBIPkBBPkBFLrypFjgW3BSAgIc2zwC8mX4AFpxAts87VQvHwEBIBoATwhbpEx4CBukTDgAdAg10rDAJrUAvAHyFjPFszJ4HHXI8gBzxb0AMmAAaFIwvo4aXwOTIddKmAHTB9QC+wAB6DFwyMoAAoBA9EOOEnHIywATywdYzwFYzxYCgED0Q+ICASAdHgIBICUmARO77ZbVAjcFnbPIHwIBSCAhABjIywfLB8s/9AD0AMkCASAiIwF5sR10IMI1xgg+QEB0weCAdTE7UPYUyB49A5vofKf1wv/XjH5EPKgrgH0BCFulhAjXwNxAeD5AVjbPAGkAYCQAPa7agOgA6AD6AgF6AhH8gID8gN15T/gD5HoAAOeLZMAAFa4ZV0EA1WZ2oexAAGBwjikD0IMI1xjTB/QEMFMWePQOb6HypdcL/1RFRPkQ8qauUiCxUgO9FKEjbuYyMjICASAnKAIBSCkqAVW3JVtnhiZQCAqIhn6BzfQxwmYmQDpAADMaYOYuAFrgJhwLb+4cBgY3dG4QLwGNtVmbZ4Br4G/tscbqIlAIHo+N9C30JBHEgFpAADHDRA8a5CTa4GT2E5kAOeLAMAgKiCq+iHJCZhxSQmYcUktGHEA2fMCL4JAvAgEgKywCA5k4LS4BDawabZ4vgcAvABWt+UEAzJV2oewYQAENqTbPBRfBIC8AFa3cLOCAarM7UPYgABztRNDTB9MH0z/0BPQE0Q==");
with_tvm_code("multisig", "te6ccgECKAEAA+YAART/APSkE/S88sgLAQIBIAIDAgFIBAUE3vIgxwCOgzDbPOCDCNcYIPkBAdMH2zwiwAAToVNxePQOb6EB2zwC8p9UGrv5EPKgBvQEIPkBAdMfURi68qrTP3BTAfAJAcIIAYMKvLHyaFMVgED0Dm+hIJgNpCDCCvJnDd/4I6ofU0C58mFUI6NTThweJB0CAswGBwIBIAoLAAPZhAIBSAgJAC1QKkItdJEqCTItdKlwLUAdAT8AnobBKABPQhbpEx4CBukTDgAdAg10rDAJrUAvAKyFjPFszJ4HHXI8gBzxb0AMmAIBIAwNAgEgEhMBFbvtltUDRwVSDbPIJwIBSA4PAgEgEBEBc7EddCDCNcYIPkBAdMHggHUxO1D2FMgePQOb6Hyn9cL/14x+RDyoK4B9AQhbpNbcTLg+QFY2zwBpAGAhAD2u2oDoAOgA+gIBegIR/ICA/IDdeU/4BWR6AADni2TAABWuGVdBANVmdqHsQAIBIBQVAgFIFhcBUbclW2eGJkZqRhAIHoHN9DHCTYRaQAAzGmHmLgBa4CYcC2/uHAt3dG4QHgGHtVmbZ4ar4G/tscaKInAIHo+N9KQRxGBaQAAxw0QQAhrkJLrgZPYTmQA54sqEAJAIHohgUiYcUiYcUiZcQDZiXMCL4JAeAgEgGBkCA5k4GhsBEawabZ4vgbYJQB4AFa35QQDMlXah7BhAAQ2pNs8FV8FgHgAVrdws4IBqsztQ9iACINs8AvJl+ABQQ3FDE9s87VQeJwSo2zwvrlMgsPJiErECpIIBhqD4AQWXAhEQAj4+MI6jAREQAQ/bPEDXePRDUxe5JoIgDhAAAAAAoCS8sPJpEL0QvAXiVBZbVHPnVhBT3Ns8VHEKVHq8HyUiIAAg7UTQ0x/TB9MH0z/0BPQE0QBIAY4aMNIAAfKj0wfTB1AD1wEg+QEF+QEVuvKkUAPgbCFwVCATBLjbPO1U+A9wJW5Tib6xmBBuEC1Qx18HjxswVCQDUE3bPFBVoEZQEEkQOksJU7nbPFBUFn/i+AAHgyWhjh0mgED0lm+lbBIglDBTArneIJY3OH85BwWSbCHis+YwBichIiMAYHCOKQPQgwjXGNMH9AQwUxZ49A5vofKl1wv/VEVE+RDypq5SILFSA70UoSNu5mwiMgKaUjC+jy5fA/gAkyLXSpgC0wfUAvsAAugycMjKAEAUgED0Q1MhePQOb6Ew2zyl2zxaePRDjhdxyMsAFMsHEssHWM8BWM8WQBOAQPRDAeIkJQEKipJfBuImAArT/9MHMAAMAcjL/8sHARQQRRA0QwDbPO1UJwAcyMsfywfLB8s/9AD0AMk=");

View File

@ -2,11 +2,14 @@
PROGRAM{
DECLPROC unpack_state
DECLPROC pack_state
DECLPROC pack_owner_info
DECLPROC unpack_owner_info
DECLPROC check_signatures
DECLPROC recv_internal
DECLPROC unpack_query_data
DECLPROC try_init
DECLPROC update_pending_queries
DECLPROC calc_boc_size
DECLPROC recv_external
104746 DECLMETHOD get_query_state
117746 DECLMETHOD processed?
@ -23,22 +26,37 @@ PROGRAM{
//
c4 PUSH // _1
CTOS // ds
8 LDU // _4 ds
32 LDU // _4 ds
8 LDU // _4 _7 ds
64 LDU // _4 _7 _10 ds
LDDICT // _4 _7 _10 _13 ds
LDDICT // res res res res res ds
8 LDU // _4 _7 _10 ds
64 LDU // _4 _7 _10 _13 ds
LDDICT // _4 _7 _10 _13 _16 ds
LDDICT // res res res res res res ds
ENDS
}>
pack_state PROCREF:<{
// pending_queries public_keys last_cleaned k n
NEWC // pending_queries public_keys last_cleaned k n _5
8 STU // pending_queries public_keys last_cleaned k _7
8 STU // pending_queries public_keys last_cleaned _9
64 STU // pending_queries public_keys _11
STDICT // pending_queries _12
STDICT // _13
ENDC // _14
// pending_queries owner_infos last_cleaned k n wallet_id
NEWC // pending_queries owner_infos last_cleaned k n wallet_id _6
32 STU // pending_queries owner_infos last_cleaned k n _8
8 STU // pending_queries owner_infos last_cleaned k _10
8 STU // pending_queries owner_infos last_cleaned _12
64 STU // pending_queries owner_infos _14
STDICT // pending_queries _15
STDICT // _16
ENDC // _17
}>
pack_owner_info PROCREF:<{
// public_key flood
SWAP
NEWC // flood public_key _2
256 STU // flood _4
8 STU // _6
}>
unpack_owner_info PROCREF:<{
// cs
256 LDU // _1 cs
8 LDU // _1 _10 _9
DROP // _1 _4
}>
check_signatures PROCREF:<{
// public_keys signatures hash cnt_bits
@ -70,8 +88,7 @@ PROGRAM{
s3 PUSH // public_keys signatures hash cnt_bits cnt signatures
ISNULL // public_keys signatures hash cnt_bits cnt _37
}> // public_keys signatures hash cnt_bits cnt
s2 POP
s2 POP
2 2 BLKDROP2
s2 POP // cnt cnt_bits
}>
recv_internal PROC:<{
@ -79,78 +96,117 @@ PROGRAM{
DROP //
}>
unpack_query_data PROCREF:<{
// in_msg n query found?
IFJMP:<{ // in_msg n query
1 LDI // in_msg n _5 query
SWAP // in_msg n query _5
// in_msg n query found? root_i
SWAP // in_msg n query root_i found?
IFJMP:<{ // in_msg n query root_i
DROP // in_msg n query
1 LDI // in_msg n _6 query
SWAP // in_msg n query _6
35 THROWIFNOT
8 LDU // in_msg n _12 query
ROT // in_msg _12 query n
LDUX // in_msg cnt cnt_bits msg
DUP // in_msg cnt cnt_bits msg msg
HASHSU // in_msg cnt cnt_bits msg _18
s0 s4 XCHG // _18 cnt cnt_bits msg in_msg
HASHSU // _18 cnt cnt_bits msg _19
s1 s4 XCHG // msg cnt cnt_bits _18 _19
EQUAL // msg cnt cnt_bits _20
8 LDU // in_msg n _14 query
8 LDU // in_msg n _14 _17 query
s0 s3 XCHG2 // in_msg _17 _14 query n
LDUX // in_msg cnt creator_i cnt_bits msg
DUP // in_msg cnt creator_i cnt_bits msg msg
HASHSU // in_msg cnt creator_i cnt_bits msg _23
s0 s5 XCHG // _23 cnt creator_i cnt_bits msg in_msg
HASHSU // _23 cnt creator_i cnt_bits msg _24
s1 s5 XCHG // msg cnt creator_i cnt_bits _23 _24
EQUAL // msg cnt creator_i cnt_bits _25
36 THROWIFNOT
ROT // cnt cnt_bits msg
}> // in_msg n query
2DROP // in_msg
0 PUSHINT // in_msg _22=0
s0 s1 PUXC // _22=0 _23=0 in_msg
s0 s3 XCHG2 // creator_i cnt cnt_bits msg
}> // in_msg n query root_i
2 1 BLKDROP2 // in_msg root_i
0 PUSHINT // in_msg root_i _27=0
s0 s1 s2 XCPUXC // root_i _27=0 _28=0 in_msg
}>
try_init PROCREF:<{
//
unpack_state INLINECALLDICT // n k last_cleaned public_keys pending_queries
s0 s2 XCHG // n k pending_queries public_keys last_cleaned
unpack_state INLINECALLDICT // wallet_id n k last_cleaned owner_infos pending_queries
s0 s2 XCHG // wallet_id n k pending_queries owner_infos last_cleaned
37 THROWIF
ACCEPT
2SWAP
s4 s3 XCHG2
1 PUSHINT
s0 s2 XCHG // pending_queries public_keys _9=1 k n
pack_state INLINECALLDICT // _10
s3 s1 s3 XCHG3 // pending_queries owner_infos _10=1 k n wallet_id
pack_state INLINECALLDICT // _11
c4 POP
}>
update_pending_queries PROCREF:<{
// pending_queries msg query_id cnt cnt_bits n k
s3 s(-1) PUXC // pending_queries msg query_id cnt cnt_bits n cnt k
GEQ // pending_queries msg query_id cnt cnt_bits n _7
IF:<{ // pending_queries msg query_id cnt cnt_bits n
3 BLKDROP // pending_queries msg query_id
// pending_queries owner_infos msg query_id creator_i cnt cnt_bits n k
s3 s(-1) PUXC // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n cnt k
GEQ // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _9
IF:<{ // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n
3 BLKDROP // pending_queries owner_infos msg query_id creator_i
ACCEPT
WHILE:<{
OVER // pending_queries msg query_id msg
SREFS // pending_queries msg query_id _8
}>DO<{ // pending_queries msg query_id
SWAP // pending_queries query_id msg
8 LDU // pending_queries query_id mode msg
LDREF // pending_queries query_id mode _13 msg
s0 s2 XCHG // pending_queries query_id msg _13 mode
s2 PUSH // pending_queries owner_infos msg query_id creator_i msg
SREFS // pending_queries owner_infos msg query_id creator_i _11
}>DO<{ // pending_queries owner_infos msg query_id creator_i
s0 s2 XCHG // pending_queries owner_infos creator_i query_id msg
8 LDU // pending_queries owner_infos creator_i query_id mode msg
LDREF // pending_queries owner_infos creator_i query_id mode _16 msg
s0 s2 XCHG // pending_queries owner_infos creator_i query_id msg _16 mode
SENDRAWMSG
SWAP // pending_queries msg query_id
}> // pending_queries msg query_id
NIP // pending_queries query_id
0 PUSHINT // pending_queries query_id _17=0
NEWC // pending_queries query_id _17=0 _18
1 STI // pending_queries query_id _20
s0 s2 XCHG
64 PUSHINT // _20 query_id pending_queries _21=64
DICTUSETB // pending_queries
}>ELSE<{ // pending_queries msg query_id cnt cnt_bits n
1 PUSHINT // pending_queries msg query_id cnt cnt_bits n _24=1
NEWC // pending_queries msg query_id cnt cnt_bits n _24=1 _25
1 STU // pending_queries msg query_id cnt cnt_bits n _27
s1 s3 XCHG // pending_queries msg query_id n cnt_bits cnt _27
8 STU // pending_queries msg query_id n cnt_bits _29
ROT // pending_queries msg query_id cnt_bits _29 n
STUX // pending_queries msg query_id _30
ROT // pending_queries query_id _30 msg
STSLICER // pending_queries query_id _31
s0 s2 XCHG
64 PUSHINT // _31 query_id pending_queries _32=64
DICTUSETB // pending_queries
s0 s2 XCHG // pending_queries owner_infos msg query_id creator_i
}> // pending_queries owner_infos msg query_id creator_i
s2 POP // pending_queries owner_infos creator_i query_id
0 PUSHINT // pending_queries owner_infos creator_i query_id _20=0
NEWC // pending_queries owner_infos creator_i query_id _20=0 _21
1 STI // pending_queries owner_infos creator_i query_id _23
s0 s1 s4 XCHG3
64 PUSHINT // creator_i owner_infos _23 query_id pending_queries _24=64
DICTUSETB // creator_i owner_infos pending_queries
s2 s1 PUSH2
8 PUSHINT // creator_i owner_infos pending_queries creator_i owner_infos _28=8
DICTUGET
NULLSWAPIFNOT // creator_i owner_infos pending_queries _56 _57
DROP // creator_i owner_infos pending_queries owner_info
unpack_owner_info INLINECALLDICT // creator_i owner_infos pending_queries public_key flood
DEC // creator_i owner_infos pending_queries public_key _35
pack_owner_info INLINECALLDICT // creator_i owner_infos pending_queries _36
2SWAP
8 PUSHINT // pending_queries _36 creator_i owner_infos _37=8
DICTUSETB // pending_queries owner_infos
}>ELSE<{ // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n
1 PUSHINT // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _40=1
NEWC // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _40=1 _41
1 STU // pending_queries owner_infos msg query_id creator_i cnt cnt_bits n _43
s1 s4 XCHG // pending_queries owner_infos msg query_id n cnt cnt_bits creator_i _43
8 STU // pending_queries owner_infos msg query_id n cnt cnt_bits _45
s1 s2 XCHG // pending_queries owner_infos msg query_id n cnt_bits cnt _45
8 STU // pending_queries owner_infos msg query_id n cnt_bits _47
ROT // pending_queries owner_infos msg query_id cnt_bits _47 n
STUX // pending_queries owner_infos msg query_id _48
ROT // pending_queries owner_infos query_id _48 msg
STSLICER // pending_queries owner_infos query_id _49
s0 s1 s3 XCHG3
64 PUSHINT // owner_infos _49 query_id pending_queries _50=64
DICTUSETB // owner_infos pending_queries
SWAP // pending_queries owner_infos
}>
}>
calc_boc_size PROC:<{
// cells bits root
s0 s2 XCHG // root bits cells
INC // root bits cells
s2 PUSH // root bits cells root
SBITS // root bits cells _5
s1 s2 XCHG // root cells bits _5
ADD // root cells bits
WHILE:<{
s2 PUSH // root cells bits root
SREFS // root cells bits _7
}>DO<{ // root cells bits
s0 s2 XCHG // bits cells root
LDREF // bits cells _8 root
SWAP // bits cells root _8
CTOS // bits cells root _10
s1 s3 XCHG // root cells bits _10
calc_boc_size CALLDICT // root cells bits
}> // root cells bits
1 2 BLKDROP2 // cells bits
}>
recv_external PROC:<{
// in_msg
DUP // in_msg in_msg
@ -165,157 +221,209 @@ PROGRAM{
HASHSU // root_signature in_msg root_hash
SWAP // root_signature root_hash in_msg
8 LDU // root_signature root_hash root_i in_msg
unpack_state INLINECALLDICT // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries
s2 PUSH // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries last_cleaned
0 EQINT // root_signature root_hash root_i in_msg n k last_cleaned public_keys pending_queries _20
s1 s3 XCHG // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned _20
SUB // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned
s6 s1 PUSH2
8 PUSHINT // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned root_i public_keys _24=8
unpack_state INLINECALLDICT // root_signature root_hash root_i in_msg wallet_id n k last_cleaned owner_infos pending_queries
s2 PUSH // root_signature root_hash root_i in_msg wallet_id n k last_cleaned owner_infos pending_queries last_cleaned
0 EQINT // root_signature root_hash root_i in_msg wallet_id n k last_cleaned owner_infos pending_queries _21
s1 s3 XCHG // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned _21
SUB // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned
s7 s1 PUSH2
8 PUSHINT // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned root_i owner_infos _25=8
DICTUGET
NULLSWAPIFNOT // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned public_key found?
NULLSWAPIFNOT // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned owner_info found?
SWAP // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned found? owner_info
unpack_owner_info INLINECALLDICT // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned found? public_key flood
s0 s2 XCHG // root_signature root_hash root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned flood public_key found?
31 THROWIFNOT
256 PLDU // root_signature root_hash root_i in_msg n k pending_queries public_keys last_cleaned _30
s8 s9 s0 XCHG3 // last_cleaned public_keys root_i in_msg n k pending_queries root_hash root_signature _30
CHKSIGNU // last_cleaned public_keys root_i in_msg n k pending_queries _31
s10 s11 s11 XC2PU // public_key flood root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned root_hash root_signature public_key
CHKSIGNU // public_key flood root_i in_msg wallet_id n k pending_queries owner_infos last_cleaned _33
32 THROWIFNOT
s0 s3 XCHG // last_cleaned public_keys root_i pending_queries n k in_msg
LDDICT // last_cleaned public_keys root_i pending_queries n k signatures in_msg
DUP // last_cleaned public_keys root_i pending_queries n k signatures in_msg in_msg
HASHSU // last_cleaned public_keys root_i pending_queries n k signatures in_msg hash
SWAP // last_cleaned public_keys root_i pending_queries n k signatures hash in_msg
64 LDU // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg
NOW // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg _43
32 LSHIFT# // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound
s2 s0 PUSH2 // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query_id bound
LESS // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound _47
33 THROWIF
s2 s7 PUSH2
64 PUSHINT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query_id pending_queries _51=64
s0 s6 XCHG // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos in_msg
LDDICT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures in_msg
DUP // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures in_msg in_msg
HASHSU // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures in_msg hash
SWAP // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash in_msg
32 LDU // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_wallet_id in_msg
s1 s8 XCPU // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash in_msg query_wallet_id wallet_id
EQUAL // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash in_msg _45
42 THROWIFNOT
64 LDU // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg
0 PUSHINT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _53=0
s0 s1 PUSH2 // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _53=0 _54=0 in_msg
calc_boc_size CALLDICT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg cnt bits
SWAP // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg bits cnt
8 GTINT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg bits _58
SWAP
11 PUSHPOW2 // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _58 bits _59=2048
GREATER // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _58 _60
OR // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg _61
40 THROWIF
s1 s5 PUSH2
64 PUSHINT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query_id pending_queries _65=64
DICTUGET
NULLSWAPIFNOT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id in_msg bound query found?
s2 s3 XCHG
s8 s(-1) s(-1) PUXC2 // last_cleaned public_keys root_i pending_queries n k signatures hash query_id bound in_msg n query found?
unpack_query_data INLINECALLDICT // last_cleaned public_keys root_i pending_queries n k signatures hash query_id bound cnt cnt_bits msg
s0 s10 XCHG // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits root_i
POW2 // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask
2DUP // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask cnt_bits mask
AND // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits mask _61
NULLSWAPIFNOT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found?
DUP // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? found?
IFNOT:<{ // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found?
s0 s13 XCHG // public_key found? root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood
INC // public_key found? root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood
DUP // public_key found? root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood flood
10 GTINT // public_key found? root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query flood _71
39 THROWIF
s0 s13 XCHG // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found?
}> // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found?
NOW // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? _74
32 LSHIFT# // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? bound
s4 s0 PUSH2 // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? bound query_id bound
LESS // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id in_msg query found? bound _78
33 THROWIF
s3 s10 s2 XCPUXC
s4 s14 PUSH2 // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound in_msg n query found? root_i
unpack_query_data INLINECALLDICT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg
s15 PUSH // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg root_i
POW2 // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg mask
s2 s0 PUSH2 // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg mask cnt_bits mask
AND // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt cnt_bits msg mask _89
34 THROWIF
OR // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt cnt_bits
SWAP // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt_bits cnt
INC // last_cleaned public_keys msg pending_queries n k signatures hash query_id bound cnt_bits cnt
ACCEPT
s8 s9 s3 XCPU2
s10 s3 s9 PUSH3
s11 PUSH // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries msg query_id cnt cnt_bits n k
update_pending_queries INLINECALLDICT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries
s0 s10 s11 PUSH3
s9 s10 PUSH2 // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries pending_queries public_keys last_cleaned k n
pack_state INLINECALLDICT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries _68
s1 s2 XCHG // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt msg cnt_bits mask
OR // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt msg cnt_bits
s0 s2 XCHG // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt
INC // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt
100000 PUSHINT // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id found? bound creator_i cnt_bits msg cnt _94=100000
SETGASLIMIT
s0 s5 XCHG // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i cnt_bits msg found?
IFNOT:<{ // public_key flood root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i cnt_bits msg
s1 16 s() XCHG
s0 s15 XCHG // cnt_bits msg root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i public_key flood
pack_owner_info INLINECALLDICT // cnt_bits msg root_i last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound creator_i _97
s0 s13 s7 XCHG3
8 PUSHINT // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt _97 root_i owner_infos _98=8
DICTUSETB // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos
s1 s7 PUSH2 // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos cnt k
LESS // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos _101
s6 PUSH
15461882265600 PUSHINT // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos _101 bound _106
ADD // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos _101 _107
s4 PUSH // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos _101 _107 query_id
GREATER // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos _101 _108
AND // cnt_bits msg creator_i last_cleaned wallet_id n k pending_queries bound signatures hash query_id cnt owner_infos _109
41 THROWIF
s11 s13 XCHG
s11 s12 XCHG
s0 s5 XCHG // creator_i cnt_bits msg last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound
}>ELSE<{
s2 16 s() XCHG
s14 POP
s14 POP
DROP // creator_i cnt_bits msg last_cleaned wallet_id n k pending_queries owner_infos signatures hash query_id cnt bound
}>
s6 s5 s11 XC2PU
s3 s14 s7 PUSH3
16 s() PUSH
s13 s12 PUSH2 // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos msg query_id creator_i cnt cnt_bits n k
update_pending_queries INLINECALLDICT // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos
s1 s0 s10 PUSH3
s10 s11 s12 PUSH3 // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos pending_queries owner_infos last_cleaned k n wallet_id
pack_state INLINECALLDICT // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos _112
c4 POP
COMMIT
0 PUSHINT // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0
s6 PUSH // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 signatures
ISNULL // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73
s10 s8 PUSH2 // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73 cnt k
GEQ // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _73 _74
OR // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0 _75
IFNOT:<{ // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries need_save=0
DROP // last_cleaned public_keys msg cnt n k signatures hash query_id bound cnt_bits pending_queries
s10 PUSH
s6 s5 s3 XCHG3
s0 s6 XCHG // last_cleaned public_keys msg cnt n k bound pending_queries query_id public_keys signatures hash cnt_bits
check_signatures INLINECALLDICT // last_cleaned public_keys msg cnt n k bound pending_queries query_id new_cnt cnt_bits
s7 s7 XCHG2 // last_cleaned public_keys msg cnt_bits n k bound pending_queries query_id cnt new_cnt
ADD // last_cleaned public_keys msg cnt_bits n k bound pending_queries query_id cnt
s2 s4 XCHG
s3 s7 XCHG
s1 s0 s6 XCHG3
s5 s6 PUSH2 // last_cleaned public_keys bound k n pending_queries msg query_id cnt cnt_bits n k
update_pending_queries INLINECALLDICT // last_cleaned public_keys bound k n pending_queries
-1 PUSHINT // last_cleaned public_keys bound k n pending_queries need_save=-1
}>ELSE<{
0 PUSHINT // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0
s5 PUSH // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 signatures
ISNULL // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _117
s8 s9 PUSH2 // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _117 cnt k
GEQ // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _117 _118
OR // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0 _119
IFNOT:<{ // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos need_save=0
DROP // creator_i cnt_bits msg last_cleaned wallet_id n k cnt bound signatures hash query_id pending_queries owner_infos
s4 s0 s2 XCPUXC
s4 s13 XCHG2 // creator_i query_id msg last_cleaned wallet_id n k cnt bound pending_queries owner_infos owner_infos signatures hash cnt_bits
check_signatures INLINECALLDICT // creator_i query_id msg last_cleaned wallet_id n k cnt bound pending_queries owner_infos new_cnt cnt_bits
s5 s5 XCHG2 // creator_i query_id msg last_cleaned wallet_id n k cnt_bits bound pending_queries owner_infos cnt new_cnt
ADD // creator_i query_id msg last_cleaned wallet_id n k cnt_bits bound pending_queries owner_infos cnt
s6 s5 s0 XCHG3
s4 s9 XCHG
s3 s10 XCHG
s7 s9 XCHG
s7 s6 XCHG2
6 BLKDROP // last_cleaned public_keys bound k n pending_queries need_save
s11 s0 s9 XCHG3
s11 s9 PUSH2 // n bound k last_cleaned wallet_id pending_queries owner_infos msg query_id creator_i cnt cnt_bits n k
update_pending_queries INLINECALLDICT // n bound k last_cleaned wallet_id pending_queries owner_infos
s5 s4 XCHG2
s1 s6 XCHG
-1 PUSHINT // bound pending_queries owner_infos last_cleaned wallet_id n k need_save=-1
}>ELSE<{
s6 s14 XCHG
s2 s13 XCHG
s12 s7 XCHG2
7 BLKDROP // bound pending_queries owner_infos last_cleaned wallet_id n k need_save
}>
s0 s4 XCHG
38 PUSHPOW2 // last_cleaned public_keys need_save k n pending_queries bound _83
SUB // last_cleaned public_keys need_save k n pending_queries bound
ACCEPT
s0 s7 XCHG
38 PUSHPOW2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound _128
SUB // need_save pending_queries owner_infos last_cleaned wallet_id n k bound
UNTIL:<{
OVER
64 PUSHINT // last_cleaned public_keys need_save k n pending_queries bound pending_queries _90=64
s6 PUSH
64 PUSHINT // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries _135=64
DICTUREMMIN
NULLSWAPIFNOT
NULLSWAPIFNOT // last_cleaned public_keys need_save k n pending_queries bound _121 _123 _122 _124
s2 POP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' f i
s1 s0 XCPU // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f f
IF:<{ // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
DROP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i
s0 s2 PUSH2 // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i i bound
LESS // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
}> // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
DUP // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f f
IF:<{ // last_cleaned public_keys need_save k n pending_queries bound pending_queries' i f
s4 POP
s6 POP
s7 POP // pending_queries public_keys last_cleaned k n f bound
-1 PUSHINT // pending_queries public_keys last_cleaned k n f bound need_save=-1
NULLSWAPIFNOT2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound _178 _180 _179 _181
1 2 BLKDROP2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i f
DUP // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i f f
IF:<{ // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i f
DROP // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i
s0 s2 PUSH2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i i bound
LESS // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i f
}> // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i f
DUP // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i f f
IF:<{ // need_save pending_queries owner_infos last_cleaned wallet_id n k bound pending_queries' i f
s7 POP
s8 POP
-1 PUSHINT
s9 POP
s0 s7 XCHG
s0 s5 XCHG // need_save=-1 pending_queries owner_infos last_cleaned wallet_id n k bound f
}>ELSE<{
s4 s9 XCHG
s4 s7 XCHG
s4 s1 s4 XCHG3
2DROP // pending_queries public_keys last_cleaned k n f bound need_save
2 1 BLKDROP2 // need_save pending_queries owner_infos last_cleaned wallet_id n k bound f
}>
s0 s2 XCHG // pending_queries public_keys last_cleaned k n need_save bound f
NOT // pending_queries public_keys last_cleaned k n need_save bound _96
s5 s7 XCHG
s2 s5 XCHG // last_cleaned public_keys need_save k n pending_queries bound _96
}> // last_cleaned public_keys need_save k n pending_queries bound
DROP // last_cleaned public_keys need_save k n pending_queries
s0 s3 XCHG // last_cleaned public_keys pending_queries k n need_save
IF:<{ // last_cleaned public_keys pending_queries k n
s2 s4 XCHG // pending_queries public_keys last_cleaned k n
pack_state INLINECALLDICT // _97
NOT // need_save pending_queries owner_infos last_cleaned wallet_id n k bound _141
}> // need_save pending_queries owner_infos last_cleaned wallet_id n k bound
DROP // need_save pending_queries owner_infos last_cleaned wallet_id n k
s0 s6 XCHG // k pending_queries owner_infos last_cleaned wallet_id n need_save
IF:<{ // k pending_queries owner_infos last_cleaned wallet_id n
s4 s5 XCHG
s3 s4 XCHG
s3 s0 s0 XCHG3 // pending_queries owner_infos last_cleaned k n wallet_id
pack_state INLINECALLDICT // _142
c4 POP
}>ELSE<{
5 BLKDROP //
6 BLKDROP //
}>
}>
get_query_state PROC:<{
// query_id
unpack_state INLINECALLDICT // query_id _25 _26 _27 _28 _29
unpack_state INLINECALLDICT // query_id _28 _29 _30 _31 _32 _33
NIP
s2 POP // query_id n pending_queries last_cleaned
64 PUSHINT // query_id n pending_queries last_cleaned _9=64
s4 s2 s2 PUXC2 // query_id n last_cleaned query_id pending_queries _9=64
s2 POP
s3 POP // query_id last_cleaned n pending_queries
s3 s(-1) PUXC
64 PUSHINT // query_id last_cleaned n query_id pending_queries _10=64
DICTUGET
NULLSWAPIFNOT // query_id n last_cleaned cs found
IFJMP:<{ // query_id n last_cleaned cs
NIP
s2 POP // cs n
SWAP // n cs
1 LDI // n _11 cs
SWAP // n cs _11
NULLSWAPIFNOT // query_id last_cleaned n cs found
IFJMP:<{ // query_id last_cleaned n cs
2 2 BLKDROP2 // n cs
1 LDI // n _12 cs
SWAP // n cs _12
IFJMP:<{ // n cs
8 LDU // n _35 _34
16 LDU // n _39 _38
NIP // n cs
0 PUSHINT // n cs _17=0
s0 s2 XCHG // _17=0 cs n
LDUX // _17=0 _37 _36
DROP // _17=0 _18
0 PUSHINT // n cs _20=0
s0 s2 XCHG // _20=0 cs n
LDUX // _20=0 _41 _40
DROP // _20=0 _21
}> // n cs
2DROP //
-1 PUSHINT // _20=-1
0 PUSHINT // _20=-1 _21=0
}> // query_id n last_cleaned cs
DROP
NIP // query_id last_cleaned
LEQ // _22
NEGATE // _23
0 PUSHINT // _23 _24=0
-1 PUSHINT // _23=-1
0 PUSHINT // _23=-1 _24=0
}> // query_id last_cleaned n cs
2DROP // query_id last_cleaned
LEQ // _25
NEGATE // _26
0 PUSHINT // _26 _27=0
}>
processed? PROC:<{
// query_id
@ -323,12 +431,12 @@ PROGRAM{
DROP // x
}>
create_init_state PROC:<{
// n k public_keys
NEWDICT // n k public_keys _3
s2 s3 XCHG2
// wallet_id n k owners_info
NEWDICT // wallet_id n k owners_info _4
s3 s4 XCHG2
0 PUSHINT
-ROT // _3 public_keys _4=0 k n
pack_state INLINECALLDICT // _5
3 -ROLL // _4 owners_info _5=0 k n wallet_id
pack_state INLINECALLDICT // _6
}>
merge_list PROC:<{
// a b
@ -351,7 +459,7 @@ PROGRAM{
LDREF // b _10 as
s0 s2 XCHG // as _10 b
merge_list CALLDICT // as tail
NEWC // as tail _13
NEWC
ROT // tail _13 as
STSLICER // tail _14
STREF // _15
@ -367,9 +475,9 @@ PROGRAM{
}>
get_public_keys PROC:<{
//
unpack_state INLINECALLDICT // _6 _7 _8 _9 _10
s1 s4 XCHG
4 BLKDROP // public_keys
unpack_state INLINECALLDICT // _7 _8 _9 _10 _11 _12
s1 s5 XCHG
5 BLKDROP // public_keys
}>
check_query_signatures PROC:<{
// query
@ -396,10 +504,9 @@ PROGRAM{
OVER // public_keys mask signatures cs signatures
ISNULL // public_keys mask signatures cs _32
IFJMP:<{ // public_keys mask signatures cs
s2 s3 XCHG
3 BLKDROP // mask
1 PUSHINT // mask _33=1
SWAP // _33=1 mask
2DROP
1 PUSHINT
s2 POP // _33=1 mask
}> // public_keys mask signatures cs
HASHSU // public_keys mask signatures _35
ROT // public_keys signatures _35 mask
@ -410,53 +517,50 @@ PROGRAM{
}>
messages_by_mask PROC:<{
// mask
unpack_state INLINECALLDICT // mask _29 _30 _31 _32 _33
s0 s3 XCHG
3 BLKDROP // mask n pending_queries
-1 PUSHINT // mask n pending_queries i=-1
NEWDICT // mask n pending_queries i=-1 a
unpack_state INLINECALLDICT // mask _32 _33 _34 _35 _36 _37
s5 POP
3 BLKDROP // mask pending_queries n
-1 PUSHINT // mask pending_queries n i=-1
NEWDICT // mask pending_queries n i=-1 a
UNTIL:<{
s1 s2 XCPU
64 PUSHINT // mask n pending_queries a i pending_queries _13=64
s1 s3 XCPU
64 PUSHINT // mask pending_queries n a i pending_queries _14=64
DICTUGETNEXT
NULLSWAPIFNOT
NULLSWAPIFNOT // mask n pending_queries a cs i f
DUP // mask n pending_queries a cs i f f
IF:<{ // mask n pending_queries a cs i f
s0 s2 XCHG // mask n pending_queries a f i cs
1 LDI // mask n pending_queries a f i _15 cs
SWAP // mask n pending_queries a f i cs _15
IF:<{ // mask n pending_queries a f i cs
NULLSWAPIFNOT2 // mask pending_queries n a cs i f
DUP // mask pending_queries n a cs i f f
IF:<{ // mask pending_queries n a cs i f
s0 s2 XCHG // mask pending_queries n a f i cs
1 LDI // mask pending_queries n a f i _16 cs
SWAP // mask pending_queries n a f i cs _16
IF:<{ // mask pending_queries n a f i cs
DUP
8 PUSHINT // mask n pending_queries a f i cs cs _19=8
SDSKIPFIRST // mask n pending_queries a f i cs _20
s6 PUSH // mask n pending_queries a f i cs _20 n
PLDUX // mask n pending_queries a f i cs cnt_bits
s7 PUSH // mask n pending_queries a f i cs cnt_bits mask
AND // mask n pending_queries a f i cs _22
IF:<{ // mask n pending_queries a f i cs
NEWC // mask n pending_queries a f i cs _24
SWAP // mask n pending_queries a f i _24 cs
STSLICER // mask n pending_queries a f i _25
SWAP
64 PUSHINT
s1 s4 s4 PUXC2 // mask n pending_queries i f _25 i a _26=64
DICTUSETB // mask n pending_queries i f a
16 PUSHINT // mask pending_queries n a f i cs cs _22
SDSKIPFIRST // mask pending_queries n a f i cs _23
s5 PUSH // mask pending_queries n a f i cs _23 n
PLDUX // mask pending_queries n a f i cs cnt_bits
s7 PUSH // mask pending_queries n a f i cs cnt_bits mask
AND // mask pending_queries n a f i cs _25
IF:<{ // mask pending_queries n a f i cs
NEWC // mask pending_queries n a f i cs _27
SWAP // mask pending_queries n a f i _27 cs
STSLICER // mask pending_queries n a f i _28
s0 s0 s3 XCPUXC
64 PUSHINT // mask pending_queries n i f _28 i a _29=64
DICTUSETB // mask pending_queries n i f a
s0 s2 XCHG // mask pending_queries n a f i
}>ELSE<{
s1 s3 XCHG
DROP // mask n pending_queries i f a
DROP // mask pending_queries n a f i
}>
}>ELSE<{
s1 s3 XCHG
DROP // mask n pending_queries i f a
DROP // mask pending_queries n a f i
}>
}>ELSE<{
2SWAP
DROP // mask n pending_queries i f a
s2 POP // mask pending_queries n a f i
}>
SWAP // mask n pending_queries i a f
NOT // mask n pending_queries i a _28
}> // mask n pending_queries i a
SWAP // mask pending_queries n a i f
NOT // mask pending_queries n a i _31
s1 s2 XCHG // mask pending_queries n i a _31
}> // mask pending_queries n i a
s0 s4 XCHG
4 BLKDROP // a
}>
@ -473,8 +577,9 @@ PROGRAM{
}>
get_n_k PROC:<{
//
unpack_state INLINECALLDICT // _6 _7 _8 _9 _10
3 BLKDROP // n k
unpack_state INLINECALLDICT // _7 _8 _9 _10 _11 _12
3 BLKDROP
1 2 BLKDROP2 // n k
}>
merge_inner_queries PROC:<{
// a b

View File

@ -1 +1 @@
with_tvm_code("restricted-wallet", "te6ccgECDQEAAQgAART/APSkE/Sg8sgLAQIBIAIDAgFIBAUB+vKDCNcYINMf0x/4IxK78mPtRNDTH9P/0VMxuvKhA54xMjL4AKTIyx/L/8ntVOED+QFUEEL5EPKi+ACA8/gzIG6SMH+X0NcLH/gjvOJx+DPQ1wv/BJMg10qOldMH1H8kjoUwUxbbPN6TAvsAkjIw4ugxMwLRpMjLH8v/ye1UDAICzgYHAgEgCgsCASAICQEBSAwAAwwgACUgPP4MyBukjB/l9DXCx/4I7zigABG+ZL9qJoa4WPwAOby2BAefwZkDdJGD/L6GuFj/wR3nFIuEp8EzeIcUADIB0NMDAXiwklt/4PpAMfpAMPpEAcD/Arqw");
with_tvm_code("restricted-wallet", "te6ccgEBDAEA+wABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQL28oMI1xgg0x/TH/gjErvyY+1E0NMf0//RUzG68qEDnjFsIvgApMjLH8v/ye1U4QP5AVQQQvkQ8qL4AIDz+DMgbpIwf5fQ1wsf+CO84nH4M9DXC/8EkyDXSo6V0wfUfySOhTBTFts83pMC+wCSbCHi6DEzAtGkyMsfy//JCgsABNAwAgEgBgcCASAICQA5vLYEB5/BmQN0kYP8voa4WP/BHecUi4SnwTt4hxQAF7s5ztRNDTHzHXC/+AARuMl+1E0NcLH4ADIB0NMDAXiwklt/4PpAMfpAMPpEAcD/ArqwAATtVA==");

View File

@ -5,6 +5,7 @@ PROGRAM{
DECLPROC check_destination
DECLPROC recv_external
85143 DECLMETHOD seqno
78748 DECLMETHOD get_public_key
104128 DECLMETHOD balance
recv_internal PROC:<{
// in_msg
@ -71,8 +72,7 @@ PROGRAM{
s0 s3 XCHG // signature in_msg public_key cs stored_seqno msg_seqno
IFNOTJMP:<{ // signature in_msg public_key cs stored_seqno
NIP
s2 POP
s2 POP // public_key stored_seqno
2 2 BLKDROP2 // public_key stored_seqno
ACCEPT
INC // public_key _35
NEWC // public_key _35 _36
@ -110,8 +110,7 @@ PROGRAM{
s0 s2 XCHG // elector stored_seqno public_key restrict cs msg mode
SENDRAWMSG
}>ELSE<{
s2 POP
DROP // elector stored_seqno public_key restrict cs
2 1 BLKDROP2 // elector stored_seqno public_key restrict cs
}>
}> // elector stored_seqno public_key restrict cs
NIP
@ -131,6 +130,14 @@ PROGRAM{
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
32 LDU // _9 _8
NIP // cs
256 PLDU // _7
}>
balance PROC:<{
//
restricted? INLINECALLDICT // _0

View File

@ -1 +1 @@
with_tvm_code("restricted-wallet2", "te6ccgECDAEAAR0AART/APSkE/Sg8sgLAQIBIAIDAgFIBAUBAvIKAgLPBgcCASAICQADDCAAMyA8/gzIG6SMH+e+CMB0NcLH6GCAVGAqQTigABG+ZL9qJoa4WPwAf7y2B2omhAgJBrkPoCaMB5/BmQN0kYP898EYDoa4WP0MEAqMBUgnF8EzeIAUAIej230LfQmMv9ABhQuFsEyJhxQB/oMI1xgg0x/TH/gjErvyY+1E0NMf0//0BNFTQrryoQSOEjIzM/gAAaTIyx8Sy//0AMntVOEE+QFUEFT5EPKi+ACA8/gzIG6SMH+e+CMB0NcLH6GCAVGAqQTiIoAQ9HtvoW+hMZb6ADBy+wKRMOKTINdKltMH1AL7AOjRAqTIyx8LAA7L//QAye1U");
with_tvm_code("restricted-wallet2", "te6ccgECCwEAAQgAART/APSkE/S88sgLAQIBIAIDAgFIBAUB+PKDCNcYINMf0x/4IxK78mPtRNDTH9P/9ATRU0K68qEEjhIyMzP4AAGkyMsfEsv/9ADJ7VThBPkBVBBU+RDyovgAgPP4MyBukjB/nvgjAdDXCx+hggFRgKkE4iKAEPR7b6UxlvoAMHL7ApEw4pMg10qW0wfUAvsA6NECpMgKAATQMAIBIAYHAgEgCAkAe7y2B2omhAgJBrkPoCaMB5/BmQN0kYP898EYDoa4WP0MEAqMBUgnF8E7eIAUAIej230pjL/QAYULhbBMiYcUABe7Oc7UTQ0x8x1wv/gAEbjJftRNDXCx+AASyx/L//QAye1U");

View File

@ -4,6 +4,7 @@ PROGRAM{
DECLPROC days_passed
DECLPROC recv_external
85143 DECLMETHOD seqno
78748 DECLMETHOD get_public_key
104128 DECLMETHOD balance
recv_internal PROC:<{
// in_msg
@ -74,8 +75,7 @@ PROGRAM{
s2 PUSH
16 PUSHINT // stored_seqno public_key rdict cs ts rdict _57=16
DICTIGETPREVEQ
NULLSWAPIFNOT
NULLSWAPIFNOT // stored_seqno public_key rdict cs _98 _97 _99
NULLSWAPIFNOT2 // stored_seqno public_key rdict cs _98 _97 _99
NIP // stored_seqno public_key rdict cs value found
IF:<{ // stored_seqno public_key rdict cs value
LDGRAMS // stored_seqno public_key rdict cs _101 _100
@ -110,6 +110,14 @@ PROGRAM{
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
32 LDU // _9 _8
NIP // cs
256 PLDU // _7
}>
balance PROC:<{
//
c4 PUSH // _1
@ -124,8 +132,7 @@ PROGRAM{
s0 s2 XCHG
16 PUSHINT // balance ts rdict _19=16
DICTIGETPREVEQ
NULLSWAPIFNOT
NULLSWAPIFNOT // balance _29 _28 _30
NULLSWAPIFNOT2 // balance _29 _28 _30
NIP // balance value found
IF:<{ // balance value
LDGRAMS // balance _32 _31

View File

@ -1 +1 @@
with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9KDyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U");
with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9LzyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U");

View File

@ -1 +1 @@
with_tvm_code("simple-wallet-ext", "te6ccgEBFgEAzwABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQA08vACVDIS8AT4ACDXSpbTB9QC+wDe0aQB8AMCAs0GBwIBIA4PAgEgCAkAKdAUGEa4wQaY+CXXlQ/ICgCfyIeVFAIBIAoLAgEgDA0AAwwgAA8yBLLH8v/yYAARO1E0NMf0/8wgAAk8AHtVIAIBIBARAgEgFBUADbvtlwAfABgCASASEwARtZL9qJoa4WPwAA22l54AXgCQACG40BggFMl+1D2IIByODtQ9iAAVuI4MjLHxLLB8zJg=");
with_tvm_code("simple-wallet-ext", "te6ccgEBGAEA3AABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQA08vACVDIS8AT4ACDXSpbTB9QC+wDe0aQB8AMCAs0GBwIBIA4PAgEgCAkAKdAUGEa4wQaY+CXXlQ/ICgCfyIeVFAIBIAoLAgEgDA0AAwwgAA8AcjLH8v/yYAARO1E0NMf0/8wgAAk8AHtVIAIBIBARAgEgFhcCAW4SEwIBIBQVAAutzngBGMAADa9suAD4AMAAEbWS/aiaGuFj8AANtpeeAF4AkAAhuNAYIBTJftQ9iCAcjg7UPYgAFbiODIyx8SywfMyY");

View File

@ -7,14 +7,15 @@ PROGRAM{
DECLPROC do_verify_message
DECLPROC recv_external
85143 DECLMETHOD seqno
78748 DECLMETHOD get_public_key
81625 DECLMETHOD create_init_state
116960 DECLMETHOD prepare_send_message_with_seqno
101633 DECLMETHOD prepare_send_message
95420 DECLMETHOD verify_message
create_state PROC:<{
// seqno public_key
NEWC // seqno public_key _2
s1 s2 XCHG // public_key seqno _2
SWAP
NEWC // public_key seqno _2
32 STU // public_key _4
256 STU // _6
ENDC // _7
@ -76,6 +77,11 @@ PROGRAM{
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
load_state CALLDICT // _3 _4
NIP // public_key
}>
create_init_state PROC:<{
// public_key
0 PUSHINT // public_key _1=0

View File

@ -1 +1 @@
with_tvm_code("wallet", "te6ccgEBBgEAaAABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQCA8oMI1xgg0x/TH/gjErvyY+1E0NMf0//RUTG68qED+QFUEEL5EPKi+AACkyDXSpbTB9QC+wDo0aTIyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==");
with_tvm_code("wallet", "te6ccgEBCAEAewABFP8A9KQT9LzyyAsBAgEgAgMCAUgEBQCA8oMI1xgg0x/TH/gjErvyY+1E0NMf0//RUTG68qED+QFUEEL5EPKi+AACkyDXSpbTB9QC+wDo0aTIyx/L/8ntVAAE0DACAUgGBwAXuznO1E0NMfMdcL/4ABG4yX7UTQ1wsfg=");

View File

@ -3,6 +3,7 @@ PROGRAM{
DECLPROC recv_internal
DECLPROC recv_external
85143 DECLMETHOD seqno
78748 DECLMETHOD get_public_key
recv_internal PROC:<{
// in_msg
DROP //
@ -56,4 +57,12 @@ PROGRAM{
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
32 LDU // _9 _8
NIP // cs
256 PLDU // _7
}>
}END>c

View File

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

View File

@ -3,6 +3,7 @@ PROGRAM{
DECLPROC recv_internal
DECLPROC recv_external
85143 DECLMETHOD seqno
78748 DECLMETHOD get_public_key
recv_internal PROC:<{
// in_msg
DROP //
@ -62,4 +63,12 @@ PROGRAM{
CTOS // _1
32 PLDU // _3
}>
get_public_key PROC:<{
//
c4 PUSH // _1
CTOS // cs
64 LDU // _9 _8
NIP // cs
256 PLDU // _7
}>
}END>c

View File

@ -9,10 +9,9 @@
(cell, int, int, cell) load_data() inline {
var cs = get_data().begin_parse();
var (cfg_dict, stored_seqno, public_key) = (cs~load_ref(), cs~load_uint(32), cs~load_uint(256));
var vote_dict = cs.slice_empty?() ? new_dict() : cs~load_dict();
var res = (cs~load_ref(), cs~load_uint(32), cs~load_uint(256), cs~load_dict());
cs.end_parse();
return (cfg_dict, stored_seqno, public_key, vote_dict);
return res;
}
() store_data(cfg_dict, stored_seqno, public_key, vote_dict) impure inline {
@ -26,7 +25,7 @@
(int, int) check_validator_set(cell vset) {
var cs = vset.begin_parse();
throw_if(9, (cs~load_uint(8) - 0x11) & -2); ;; validators#11 or validators_ext#12
throw_unless(9, cs~load_uint(8) == 0x12); ;; validators_ext#12 only
int utime_since = cs~load_uint(32);
int utime_until = cs~load_uint(32);
int total = cs~load_uint(16);
@ -103,7 +102,7 @@
.end_cell(), 0);
}
() after_code_upgrade(slice param, cell old_code) impure method_id(1666) {
() after_code_upgrade(slice param, cont old_code) impure method_id(1666) {
}
_ perform_action(cfg_dict, public_key, action, cs) {
@ -119,7 +118,7 @@ _ perform_action(cfg_dict, public_key, action, cs) {
var new_code = cs~load_ref();
set_code(new_code);
var old_code = get_c3();
set_c3(new_code);
set_c3(new_code.begin_parse().bless());
after_code_upgrade(cs, old_code);
throw(0);
return (cfg_dict, public_key);
@ -138,16 +137,21 @@ _ perform_action(cfg_dict, public_key, action, cs) {
}
}
slice get_validator_descr(int idx) inline_ref {
(slice, int) get_validator_descr(int idx) inline_ref {
var vset = config_param(34);
if (vset.null?()) {
return null();
return (null(), 0);
}
var cs = begin_parse(vset);
cs~skip_bits(8 + 32 + 32 + 16 + 16);
;; validators_ext#12 utime_since:uint32 utime_until:uint32
;; total:(## 16) main:(## 16) { main <= total } { main >= 1 }
;; total_weight:uint64
throw_unless(40, cs~load_uint(8) == 0x12);
cs~skip_bits(32 + 32 + 16 + 16);
int total_weight = cs~load_uint(64);
var dict = begin_cell().store_slice(cs).end_cell();
var (value, _) = dict.udict_get?(16, idx);
return value;
return (value, total_weight);
}
(int, int) unpack_validator_descr(slice cs) inline {
@ -159,33 +163,51 @@ slice get_validator_descr(int idx) inline_ref {
return (cs~load_uint(256), cs~load_uint(64));
}
slice create_new_entry(cs) inline {
return begin_cell().store_int(false, 1).store_uint(0, 64).store_uint(0, 256).store_slice(cs).end_cell().begin_parse();
(cell, int, int, slice) new_proposal(cs) inline {
return (null(), 0, 0, cs);
}
(cell, int, int, slice) unpack_suggestion(slice cs) inline {
(cell, int, int, slice) unpack_proposal(slice cs) inline {
return (cs~load_dict(), cs~load_uint(64), cs~load_uint(256), cs);
}
builder pack_suggestion(cell voters, int sum_weight, int vset_id, slice body) inline {
builder pack_proposal(cell voters, int sum_weight, int vset_id, slice body) inline {
return begin_cell().store_dict(voters).store_uint(sum_weight, 64).store_uint(vset_id, 256).store_slice(body);
}
cell register_vote(vote_dict, action, cs, idx, weight) {
(cell, slice) register_vote(vote_dict, action, cs, idx, weight, total_weight, cur_vset_id) {
int hash = 0;
int found? = 0;
var entry = null();
if (action & 1) {
hash = slice_hash(cs);
(entry, var found?) = vote_dict.udict_get?(256, hash);
ifnot (found?) {
entry = create_new_entry(cs);
}
(entry, found?) = vote_dict.udict_get?(256, hash);
} else {
hash = cs.preload_uint(256);
(entry, var found?) = vote_dict.udict_get?(256, hash);
(entry, found?) = vote_dict.udict_get?(256, hash);
throw_unless(42, found?);
}
return vote_dict;
var (voters, sum_weight, vset_id, body) = found? ? unpack_proposal(entry) : (null(), 0, cur_vset_id, cs);
if (vset_id != cur_vset_id) {
voters = null();
sum_weight = 0;
vset_id = cur_vset_id;
}
var (_, found?) = voters.udict_get?(16, idx);
ifnot (found?) {
voters~udict_set_builder(16, idx, begin_cell().store_uint(32, now()));
sum_weight += weight;
if (sum_weight * 3 > total_weight * 2) {
;; proposal accepted
vote_dict~udict_delete?(256, hash);
return (vote_dict, body);
} else {
vote_dict~udict_set_builder(256, hash, pack_proposal(voters, sum_weight, cur_vset_id, body));
return (vote_dict, null());
}
} else {
return (vote_dict, null());
}
}
() recv_external(slice in_msg) impure {
@ -199,15 +221,19 @@ cell register_vote(vote_dict, action, cs, idx, weight) {
throw_unless(33, msg_seqno == stored_seqno);
ifnot ((action - 0x566f7465) & -2) {
var idx = cs~load_uint(16);
var vdescr = get_validator_descr(idx);
var (vdescr, total_weight) = get_validator_descr(idx);
var (val_pubkey, weight) = unpack_validator_descr(vdescr);
throw_unless(34, check_signature(slice_hash(in_msg), signature, val_pubkey));
accept_message();
stored_seqno += 1;
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
commit();
vote_dict = register_vote(vote_dict, action, cs, idx, weight);
(vote_dict, var accepted) = register_vote(vote_dict, action, cs, idx, weight, total_weight, config_param(34).cell_hash());
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
ifnot (accepted.null?()) {
(cfg_dict, public_key) = perform_action(cfg_dict, public_key, accepted~load_uint(32), accepted);
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
}
return ();
}
throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key));
@ -231,7 +257,7 @@ cell register_vote(vote_dict, action, cs, idx, weight) {
if (ds.slice_bits() >= 40) {
var tag = ds~load_uint(8);
var since = ds.preload_uint(32);
if ((tag == 0x11) & (since >= now())) {
if ((since <= now()) & (tag == 0x12)) {
;; next validator set becomes active!
var cur_vset = cfg_dict~idict_set_get_ref(kl, 34, next_vset); ;; next_vset -> cur_vset
cfg_dict~idict_set_get_ref(kl, 32, cur_vset); ;; cur_vset -> prev_vset
@ -241,3 +267,7 @@ cell register_vote(vote_dict, action, cs, idx, weight) {
}
set_data(begin_cell().store_ref(cfg_dict).store_slice(cs).end_cell());
}
int seqno() impure method_id {
return get_data().begin_parse().preload_uint(32);
}

View File

@ -0,0 +1,514 @@
{-
Adapted from original version written by:
/------------------------------------------------------------------------\
| Created for: Telegram (Open Network) Blockchain Contest |
| Task 2: DNS Resolver (Automatically registering) |
>------------------------------------------------------------------------<
| Author: Oleksandr Murzin (tg: @skydev / em: alexhacker64@gmail.com) |
| October 2019 |
\------------------------------------------------------------------------/
-}
;;===========================================================================;;
;; Utility functions ;;
;;===========================================================================;;
{-
Data structure:
Root cell: [OptRef<1b+1r?>:Hashmap<PfxDict:Slice->UInt<32b>,CatTable>:domains]
[OptRef<1b+1r?>:Hashmap<UInt<160b>(Time|Hash128)->Slice(DomName)>:gc]
[UInt<32b>:stdperiod] [Gram:PPReg] [Gram:PPCell] [Gram:PPBit]
[UInt<32b>:lasthousekeeping]
<CatTable> := HashmapE 16 ^DNSRecord
STORED DOMAIN NAME SLICE FORMAT: (#ZeroChars<7b>) (Domain name value)
#Zeros allows to simultaneously store, for example, com\0 and com\0google\0
That will be stored as \1com\0 and \2com\0google\0 (pfx tree has restricitons)
This will allow to resolve more specific requests to subdomains, and resort
to parent domain next resolver lookup if subdomain is not found
com\0goo\0 lookup will, for example look up \2com\0goo\0 and then
\1com\0goo\0 which will return \1com\0 (as per pfx tree) with -1 cat
-}
(cell, cell, cell, [int, int, int, int], int, int) load_data() inline_ref {
slice cs = get_data().begin_parse();
return (
cs~load_ref(), ;; control data
cs~load_dict(), ;; pfx tree: domains data and exp
cs~load_dict(), ;; gc auxillary with expiration and 128-bit hash slice
[ cs~load_uint(30), ;; length of this period of time in seconds
cs~load_grams(), ;; standard payment for registering a new subdomain
cs~load_grams(), ;; price paid for each cell (PPC)
cs~load_grams() ], ;; and bit (PPB)
cs~load_uint(32), ;; next housekeeping to be done at
cs~load_uint(32) ;; last housekeeping done at
);
}
(int, int, int, int) load_prices() inline_ref {
slice cs = get_data().begin_parse();
(cs~load_ref(), cs~load_dict(), cs~load_dict());
return (cs~load_uint(30), cs~load_grams(), cs~load_grams(), cs~load_grams());
}
() store_data(cell ctl, cell dd, cell gc, prices, int nhk, int lhk) impure {
var [sp, ppr, ppc, ppb] = prices;
set_data(begin_cell()
.store_ref(ctl) ;; control data
.store_dict(dd) ;; domains data and exp
.store_dict(gc) ;; keyed expiration time and 128-bit hash slice
.store_uint(sp, 30) ;; standard period
.store_grams(ppr) ;; price per registration
.store_grams(ppc) ;; price per cell
.store_grams(ppb) ;; price per bit
.store_uint(nhk, 32) ;; next housekeeping
.store_uint(lhk, 32) ;; last housekeeping
.end_cell());
}
global var query_info;
() send_message(slice addr, int tag, int query_id,
int body, int grams, int mode) impure {
;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
;; src:MsgAddress -> 011000 0x18
var msg = begin_cell()
.store_uint (0x18, 6)
.store_slice(addr)
.store_grams(grams)
.store_uint (0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint (tag, 32)
.store_uint (query_id, 64);
if (body >= 0) {
msg~store_uint(body, 32);
}
send_raw_message(msg.end_cell(), mode);
}
() send_error(int error_code) impure {
var (addr, query_id, op) = query_info;
return send_message(addr, error_code, query_id, op, 0, 64);
}
() send_ok(int price) impure {
raw_reserve(price, 4);
var (addr, query_id, op) = query_info;
return send_message(addr, 0xef6b6179, query_id, op, 0, 128);
}
() housekeeping(cell ctl, cell dd, cell gc, prices, int nhk, int lhk, int max_steps) impure {
int n = now();
if (n < max(nhk, lhk + 60)) { ;; housekeeping cooldown: 1 minute
;; if housekeeping was done recently, or if next housekeeping is in the future, just save
return store_data(ctl, dd, gc, prices, nhk, lhk);
}
;; need to do some housekeeping - maybe remove entry with
;; least expiration but only if it is already expired
;; no iterating and deleting all to not put too much gas gc
;; burden on any random specific user request
;; over time it will do the garbage collection required
(int mkey, _, int found?) = gc.udict_get_min?(256);
while (found? & max_steps) { ;; no short circuit optimization, two nested ifs
nhk = (mkey >> (256 - 32));
if (nhk < n) {
int key = mkey % (1 << (256 - 32));
(slice val, found?) = dd.udict_get?(256 - 32, key);
if (found?) {
int exp = val.preload_uint(32);
if (exp <= n) {
dd~udict_delete?(256 - 32, key);
}
}
gc~udict_delete?(256, mkey);
(mkey, _, found?) = gc.udict_get_min?(256);
nhk = (found? ? mkey >> (256 - 32) : 0xffffffff);
max_steps -= 1;
} else {
found? = false;
}
}
store_data(ctl, dd, gc, prices, nhk, n);
}
int calcprice_internal(slice domain, cell data, ppc, ppb) inline_ref { ;; only for internal calcs
var (_, bits, refs) = compute_data_size(data, 100); ;; 100 cells max
bits += slice_bits(domain) * 2 + (128 + 32 + 32);
return ppc * (refs + 2) + ppb * bits;
}
int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int strict) inline_ref {
if (strict & cat_table.null?()) { ;; domain not found: return notf | 2^31
return 0xee6f7466;
}
if (owner_info.null?()) { ;; no owner on this domain: no-2 (in strict mode), ok else
return strict & 0xee6f2d32;
}
var ERR_BAD2 = 0xe2616432;
slice sown = owner_info.begin_parse();
if (sown.slice_bits() < 16 + 3 + 8 + 256) { ;; bad owner record: bad2
return ERR_BAD2;
}
if (sown~load_uint(16 + 3) != 0x9fd3 * 8 + 4) {
return ERR_BAD2;
}
(int owner_wc, int owner_addr) = (sown~load_int(8), sown.preload_uint(256));
if ((owner_wc != src_wc) | (owner_addr != src_addr)) { ;; not owner: nown
return 0xee6f776e;
}
return 0; ;; ok
}
;;===========================================================================;;
;; Internal message handler (Code 0) ;;
;;===========================================================================;;
{-
Internal message cell structure:
8 4 2 1
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddressInt dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32
Internal message data structure:
[UInt<32b>:op] [UInt<64b>:query_id] [Ref<1r>:domain]
(if not prolong: [Ref<1r>:value->CatTable])
-}
;; Control operations: permitted only to the owner of this smartcontract
() perform_ctl_op(int op, int src_wc, int src_addr, slice in_msg) impure inline_ref {
var (ctl, domdata, gc, prices, nhk, lhk) = load_data();
var cs = ctl.begin_parse();
if ((cs~load_int(8) != src_wc) | (cs~load_uint(256) != src_addr)) {
return send_error(0xee6f776e);
}
if (op == 0x43685072) { ;; ChPr = Change Prices
var (stdper, ppr, ppc, ppb) = (in_msg~load_uint(32), in_msg~load_grams(), in_msg~load_grams(), in_msg~load_grams());
in_msg.end_parse();
;; NB: stdper == 0 -> disable new actions
store_data(ctl, domdata, gc, [stdper, ppr, ppc, ppb], nhk, lhk);
return send_ok(0);
}
if (op == 0x4344656c) { ;; CDel = destroy smart contract
ifnot (domdata.null?()) {
;; domain dictionary not empty, force gc
housekeeping(ctl, domdata, gc, prices, nhk, 1, -1);
}
(ctl, domdata, gc, prices, nhk, lhk) = load_data();
ifnot (domdata.null?()) {
;; domain dictionary still not empty, error
return send_error(0xee74656d);
}
var (addr, query_id, op) = query_info;
return send_message(addr, 0xef6b6179, query_id, op, 0, 128 + 32);
}
return send_error(0xffffffff);
}
;; Must send at least GR$1 more for possible gas fees!
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure {
;; this time very interested in internal messages
if (in_msg.slice_bits() < 32) {
return (); ;; simple transfer or short
}
slice cs = in_msg_cell.begin_parse();
int flags = cs~load_uint(4);
if (flags & 1) {
return (); ;; bounced messages
}
slice s_addr = cs~load_msg_addr();
(int src_wc, int src_addr) = s_addr.parse_std_addr();
int op = in_msg~load_uint(32);
ifnot (op) {
return (); ;; simple transfer with comment
}
int query_id = 0;
if (in_msg.slice_bits() >= 64) {
query_id = in_msg~load_uint(64);
}
query_info = (s_addr, query_id, op);
if (op & (1 << 31)) {
return (); ;; an answer to our query
}
if ((op >> 24) == 0x43) {
;; Control operations
return perform_ctl_op(op, src_wc, src_addr, in_msg);
}
int qt = (op == 0x72656764) * 1 + (op == 0x70726f6c) * 2 + (op == 0x75706464) * 4 + (op == 0x676f6763) * 8;
ifnot (qt) { ;; unknown query, return error
return send_error(0xffffffff);
}
qt = - qt;
(cell ctl, cell domdata, cell gc, [int, int, int, int] prices, int nhk, int lhk) = load_data();
if (qt == 8) { ;; 0x676f6763 -> GO, GC! go!!!
;; Manual garbage collection iteration
int max_steps = in_msg~load_int(32); ;; -1 = infty
housekeeping(ctl, domdata, gc, prices, nhk, 1, max_steps); ;; forced
return send_error(0xef6b6179);
}
slice domain = null();
cell domain_cell = in_msg~load_maybe_ref();
int fail = 0;
if (domain_cell.null?()) {
int bytes = in_msg~load_uint(6);
fail = (bytes == 0);
domain = in_msg~load_bits(bytes * 8);
} else {
domain = domain_cell.begin_parse();
var (bits, refs) = slice_bits_refs(domain);
fail = (refs | ((bits - 8) & (7 - 128)));
}
ifnot (fail) {
;; domain must end with \0! no\0 error
fail = domain.slice_last(8).preload_uint(8);
}
if (fail) {
return send_error(0xee6f5c30);
}
int n = now();
cell cat_table = cell owner_info = null();
int key = int exp = int zeros = 0;
slice tail = domain;
repeat (tail.slice_bits() ^>> 3) {
cat_table = null();
int z = (tail~load_uint(8) == 0);
zeros -= z;
if (z) {
key = (string_hash(domain.skip_last_bits(tail.slice_bits())) >> 32);
var (val, found?) = domdata.udict_get?(256 - 32, key);
if (found?) {
exp = val~load_uint(32);
if (exp >= n) { ;; entry not expired
cell cat_table = val~load_ref();
val.end_parse();
var (cown, ok) = cat_table.idict_get_ref?(16, -2);
if (ok) {
owner_info = cown;
}
}
}
}
}
if (zeros > 4) { ;; too much zero chars (overflow): ov\0
return send_error(0xef765c30);
}
;; ##########################################################################
int err = check_owner(cat_table, owner_info, src_wc, src_addr, qt != 1);
if (err) {
return send_error(err);
}
;; ##########################################################################
;; load desired data (reuse old for a "prolong" operation)
cell data = null();
if (qt != 2) { ;; not a "prolong", load data dictionary
data = in_msg~load_ref();
;; basic integrity check of (client-provided) dictionary
ifnot (data.dict_empty?()) { ;; 1000 gas!
var (oinfo, ok) = data.idict_get_ref?(16, -2);
if (ok) {
var cs = oinfo.begin_parse();
throw_unless(31, cs.slice_bits() >= 16 + 3 + 8 + 256);
throw_unless(31, cs.preload_uint(19) == 0x9fd3 * 8 + 4);
}
(_, _, int minok) = data.idict_get_min?(16);
(_, _, int maxok) = data.idict_get_max?(16);
throw_unless(31, minok & maxok);
}
} else {
data = cat_table;
}
;; load prices
var [stdper, ppr, ppc, ppb] = prices;
ifnot (stdper) { ;; smart contract disabled by owner, no new actions
return send_error(0xd34f4646);
}
;; compute action price
int price = calcprice_internal(domain, data, ppc, ppb) + (ppr & (qt != 4));
if (msg_value - (1 << 30) < price) { ;; gr<p: grams - GR$1 < price
return send_error(0xe7723c70);
}
;; load desired expiration unixtime
int req_expires_at = in_msg~load_uint(32);
;; ##########################################################################
if (qt == 2) { ;; 0x70726f6c -> prol | prolong domain
if (exp > n + stdper) { ;; does not expire soon, cannot prolong
return send_error(0xf365726f);
}
domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(exp + stdper, 32).store_ref(data));
int gckeyO = (exp << (256 - 32)) + key;
int gckeyN = gckeyO + (stdper << (256 - 32));
gc~udict_delete?(256, gckeyO); ;; delete old gc entry, add new
gc~udict_set_builder(256, gckeyN, begin_cell());
housekeeping(ctl, domdata, gc, prices, nhk, lhk, 1);
return send_ok(price);
}
;; ##########################################################################
if (qt == 1) { ;; 0x72656764 -> regd | register domain
ifnot (cat_table.null?()) { ;; domain already exists: return alre | 2^31
return send_error(0xe16c7265);
}
int expires_at = n + stdper;
domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(expires_at, 32).store_ref(data));
int gckey = (expires_at << (256 - 32)) | key;
gc~udict_set_builder(256, gckey, begin_cell());
housekeeping(ctl, domdata, gc, prices, min(nhk, expires_at), lhk, 1);
return send_ok(price);
}
;; ##########################################################################
if (qt == 4) { ;; 0x75706464 -> updd | update domain (data)
domdata~udict_set_builder(256 - 32, key, begin_cell().store_uint(exp, 32).store_ref(data));
housekeeping(ctl, domdata, gc, prices, nhk, lhk, 1);
return send_ok(price);
}
;; ##########################################################################
return (); ;; should NEVER reach this part of code!
}
;;===========================================================================;;
;; External message handler (Code -1) ;;
;;===========================================================================;;
() recv_external(slice in_msg) impure {
;; only for initialization
(cell ctl, cell dd, cell gc, var prices, int nhk, int lhk) = load_data();
ifnot (lhk) {
accept_message();
return store_data(ctl, dd, gc, prices, 0xffffffff, now());
}
}
;;===========================================================================;;
;; Getter methods ;;
;;===========================================================================;;
(int, cell, int, slice) dnsdictlookup(slice domain, int nowtime) inline_ref {
(int bits, int refs) = domain.slice_bits_refs();
throw_if(30, refs | (bits & 7)); ;; malformed input (~ 8n-bit)
ifnot (bits) {
return (0, null(), 0, null()); ;; zero-length input
}
int domain_last_byte = domain.slice_last(8).preload_uint(8);
if (domain_last_byte) {
domain = begin_cell().store_slice(domain) ;; append zero byte
.store_uint(0, 8).end_cell().begin_parse();
bits += 8;
}
if (bits == 8) {
return (0, null(), 0, null()); ;; zero-length input, but with zero byte
}
var ds = get_data().begin_parse();
(_, cell root) = (ds~load_ref(), ds~load_dict());
slice val = null();
int tail_bits = -1;
slice tail = domain;
repeat (bits >> 3) {
if (tail~load_uint(8) == 0) {
var key = (string_hash(domain.skip_last_bits(tail.slice_bits())) >> 32);
var (v, found?) = root.udict_get?(256 - 32, key);
if (found?) {
if (v.preload_uint(32) >= nowtime) { ;; entry not expired
val = v;
tail_bits = tail.slice_bits();
}
}
}
}
if (val.null?()) {
return (0, null(), 0, null()); ;; failed to find entry in subdomain dictionary
}
return (val~load_uint(32), val~load_ref(), tail_bits == 0, domain.skip_last_bits(tail_bits));
}
;;8m dns-record-value
(int, cell) dnsresolve(slice domain, int category) method_id {
(int exp, cell cat_table, int exact?, slice pfx) = dnsdictlookup(domain, now());
ifnot (exp) {
return (0, null());
}
ifnot (exact?) { ;; incomplete subdomain found, must return next resolver (-1)
category = -1;
}
int pfx_bits = pfx.slice_bits();
;; pfx.slice_bits() will contain 8m, where m is number of bytes in subdomain
;; COUNTING the zero byte (if structurally correct: no multiple-ZB keys)
;; which corresponds to 8m, m=one plus the number of bytes in the subdomain found)
ifnot (category) {
return (pfx_bits, cat_table); ;; return cell with entire dictionary for 0
} else {
cell cat_found = cat_table.idict_get_ref(16, category);
return (pfx_bits, cat_found);
}
}
;; getexpiration needs to know the current time to skip any possible expired
;; subdomains in the chain. it will return 0 if not found or expired.
int getexpirationx(slice domain, int nowtime) inline method_id {
(int exp, _, _, _) = dnsdictlookup(domain, nowtime);
return exp;
}
int getexpiration(slice domain) method_id {
return getexpirationx(domain, now());
}
int getstdperiod() method_id {
(int stdper, _, _, _) = load_prices();
return stdper;
}
int getppr() method_id {
(_, int ppr, _, _) = load_prices();
return ppr;
}
int getppc() method_id {
(_, _, int ppc, _) = load_prices();
return ppc;
}
int getppb() method_id {
( _, _, _, int ppb) = load_prices();
return ppb;
}
int calcprice(slice domain, cell val) method_id { ;; only for external gets (not efficient)
(_, _, int ppc, int ppb) = load_prices();
return calcprice_internal(domain, val, ppc, ppb);
}
int calcregprice(slice domain, cell val) method_id { ;; only for external gets (not efficient)
(_, int ppr, int ppc, int ppb) = load_prices();
return ppr + calcprice_internal(domain, val, ppc, ppb);
}

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