mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Update tonlib
This commit is contained in:
parent
e813ff8be6
commit
1ad432fd9c
@ -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>
|
||||
|
@ -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/...",
|
||||
]
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"optionSet" : {
|
||||
"BazelPath" : {
|
||||
"p" : "/usr/local/bin/bazel"
|
||||
},
|
||||
"WorkspaceRootPath" : {
|
||||
"p" : "/Users/peter/build/telegram-temp/telegram-ios"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"configDefaults" : {
|
||||
"optionSet" : {
|
||||
"ProjectPrioritizesSwift" : {
|
||||
"p" : "YES"
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages" : [
|
||||
"Wallet"
|
||||
],
|
||||
"projectName" : "Wallet",
|
||||
"workspaceRoot" : "../.."
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>"
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
2
submodules/ton/tonlib-src/LGPLv2
vendored
2
submodules/ton/tonlib-src/LGPLv2
vendored
@ -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
|
||||
*/
|
||||
|
9
submodules/ton/tonlib-src/README
vendored
9
submodules/ton/tonlib-src/README
vendored
@ -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:
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
203
submodules/ton/tonlib-src/crypto/block/adjust-block.cpp
Normal file
203
submodules/ton/tonlib-src/crypto/block/adjust-block.cpp
Normal 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
@ -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 {
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
21
submodules/ton/tonlib-src/crypto/fift/lib/Color.fif
Normal file
21
submodules/ton/tonlib-src/crypto/fift/lib/Color.fif
Normal 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
|
@ -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
|
||||
|
131
submodules/ton/tonlib-src/crypto/fift/lib/GetOpt.fif
Normal file
131
submodules/ton/tonlib-src/crypto/fift/lib/GetOpt.fif
Normal 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
|
@ -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?
|
||||
|
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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[]);
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)),
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>";
|
||||
|
9
submodules/ton/tonlib-src/crypto/func/test/a10.fc
Normal file
9
submodules/ton/tonlib-src/crypto/func/test/a10.fc
Normal 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);
|
||||
}
|
28
submodules/ton/tonlib-src/crypto/func/test/a11.fc
Normal file
28
submodules/ton/tonlib-src/crypto/func/test/a11.fc
Normal 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);
|
||||
}
|
||||
|
20
submodules/ton/tonlib-src/crypto/func/test/a6_4.fc
Normal file
20
submodules/ton/tonlib-src/crypto/func/test/a6_4.fc
Normal 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);
|
||||
}
|
20
submodules/ton/tonlib-src/crypto/func/test/a6_5.fc
Normal file
20
submodules/ton/tonlib-src/crypto/func/test/a6_5.fc
Normal 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;
|
||||
}
|
37
submodules/ton/tonlib-src/crypto/func/test/c1.fc
Normal file
37
submodules/ton/tonlib-src/crypto/func/test/c1.fc
Normal 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();
|
||||
}
|
||||
|
10
submodules/ton/tonlib-src/crypto/func/test/c2.fc
Normal file
10
submodules/ton/tonlib-src/crypto/func/test/c2.fc
Normal 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);
|
||||
}
|
7
submodules/ton/tonlib-src/crypto/func/test/c2_1.fc
Normal file
7
submodules/ton/tonlib-src/crypto/func/test/c2_1.fc
Normal 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);
|
||||
}
|
22
submodules/ton/tonlib-src/crypto/func/test/w8.fc
Normal file
22
submodules/ton/tonlib-src/crypto/func/test/w8.fc
Normal 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;
|
||||
}
|
8
submodules/ton/tonlib-src/crypto/func/test/w9.fc
Normal file
8
submodules/ton/tonlib-src/crypto/func/test/w9.fc
Normal file
@ -0,0 +1,8 @@
|
||||
_ g(s) {
|
||||
var (z, t) = (17, s);
|
||||
while (z > 0) {
|
||||
t = s;
|
||||
z -= 1;
|
||||
}
|
||||
return ~ t;
|
||||
}
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
115
submodules/ton/tonlib-src/crypto/smartcont/auto-dns.fif
Normal file
115
submodules/ton/tonlib-src/crypto/smartcont/auto-dns.fif
Normal 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
|
@ -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==");
|
||||
|
@ -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
|
||||
|
@ -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=");
|
@ -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
|
@ -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=");
|
@ -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
|
@ -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");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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=");
|
||||
|
@ -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
|
||||
|
@ -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==");
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -1 +1 @@
|
||||
with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9KDyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U");
|
||||
with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9LzyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U");
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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=");
|
||||
|
@ -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
|
||||
|
@ -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==");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
514
submodules/ton/tonlib-src/crypto/smartcont/dns-auto-code.fc
Normal file
514
submodules/ton/tonlib-src/crypto/smartcont/dns-auto-code.fc
Normal 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
Loading…
x
Reference in New Issue
Block a user