mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated smartcontract code
- updated smartcontract code - fixed bug in liteserver listening socket - updated documentation
This commit is contained in:
parent
38c3e39066
commit
b978e27b2f
63 changed files with 3185 additions and 81 deletions
|
@ -62,6 +62,9 @@ void AdnlExtClientImpl::hangup() {
|
||||||
conn_ = {};
|
conn_ = {};
|
||||||
is_closing_ = true;
|
is_closing_ = true;
|
||||||
ref_cnt_--;
|
ref_cnt_--;
|
||||||
|
for (auto &it : out_queries_) {
|
||||||
|
td::actor::ActorOwn<>(it.second); // send hangup
|
||||||
|
}
|
||||||
try_stop();
|
try_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,8 +146,8 @@ void AdnlExtServerImpl::add_tcp_port(td::uint16 port) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto act = td::actor::create_actor<td::TcpListener>(td::actor::ActorOptions().with_name("listener").with_poll(), port,
|
auto act = td::actor::create_actor<TcpInfiniteListener>(td::actor::ActorOptions().with_name("listener").with_poll(),
|
||||||
std::make_unique<Callback>(actor_id(this)));
|
port, std::make_unique<Callback>(actor_id(this)));
|
||||||
listeners_.emplace(port, std::move(act));
|
listeners_.emplace(port, std::move(act));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,69 @@ namespace ton {
|
||||||
|
|
||||||
namespace adnl {
|
namespace adnl {
|
||||||
|
|
||||||
|
class TcpInfiniteListener : public td::actor::Actor {
|
||||||
|
public:
|
||||||
|
TcpInfiniteListener(td::int32 port, std::unique_ptr<td::TcpListener::Callback> callback)
|
||||||
|
: port_(port), callback_(std::move(callback)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
td::int32 port_;
|
||||||
|
std::unique_ptr<td::TcpListener::Callback> callback_;
|
||||||
|
td::actor::ActorOwn<td::TcpListener> tcp_listener_;
|
||||||
|
td::int32 refcnt_{0};
|
||||||
|
bool close_flag_{false};
|
||||||
|
|
||||||
|
void start_up() override {
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hangup() override {
|
||||||
|
close_flag_ = true;
|
||||||
|
tcp_listener_.reset();
|
||||||
|
if (refcnt_ == 0) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() override {
|
||||||
|
if (!tcp_listener_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
class Callback : public td::TcpListener::Callback {
|
||||||
|
public:
|
||||||
|
Callback(td::actor::ActorShared<TcpInfiniteListener> parent) : parent_(std::move(parent)) {
|
||||||
|
}
|
||||||
|
void accept(td::SocketFd fd) override {
|
||||||
|
td::actor::send_closure(parent_, &TcpInfiniteListener::accept, std::move(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
td::actor::ActorShared<TcpInfiniteListener> parent_;
|
||||||
|
};
|
||||||
|
refcnt_++;
|
||||||
|
tcp_listener_ = td::actor::create_actor<td::TcpListener>(
|
||||||
|
td::actor::ActorOptions().with_name(PSLICE() << "TcpListener" << td::tag("port", port_)).with_poll(), port_,
|
||||||
|
std::make_unique<Callback>(actor_shared(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void accept(td::SocketFd fd) {
|
||||||
|
callback_->accept(std::move(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
void hangup_shared() override {
|
||||||
|
refcnt_--;
|
||||||
|
tcp_listener_.reset();
|
||||||
|
if (close_flag_) {
|
||||||
|
if (refcnt_ == 0) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alarm_timestamp() = td::Timestamp::in(5 /*5 seconds*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class AdnlExtServerImpl;
|
class AdnlExtServerImpl;
|
||||||
|
|
||||||
class AdnlInboundConnection : public AdnlExtConnection {
|
class AdnlInboundConnection : public AdnlExtConnection {
|
||||||
|
@ -69,6 +132,9 @@ class AdnlExtServerImpl : public AdnlExtServer {
|
||||||
ports_.clear();
|
ports_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reopen_port() {
|
||||||
|
}
|
||||||
|
|
||||||
AdnlExtServerImpl(td::actor::ActorId<AdnlPeerTable> adnl, std::vector<AdnlNodeIdShort> ids,
|
AdnlExtServerImpl(td::actor::ActorId<AdnlPeerTable> adnl, std::vector<AdnlNodeIdShort> ids,
|
||||||
std::vector<td::uint16> ports)
|
std::vector<td::uint16> ports)
|
||||||
: peer_table_(adnl) {
|
: peer_table_(adnl) {
|
||||||
|
@ -84,7 +150,7 @@ class AdnlExtServerImpl : public AdnlExtServer {
|
||||||
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
||||||
std::set<AdnlNodeIdShort> local_ids_;
|
std::set<AdnlNodeIdShort> local_ids_;
|
||||||
std::set<td::uint16> ports_;
|
std::set<td::uint16> ports_;
|
||||||
std::map<td::uint16, td::actor::ActorOwn<td::TcpListener>> listeners_;
|
std::map<td::uint16, td::actor::ActorOwn<TcpInfiniteListener>> listeners_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace adnl
|
} // namespace adnl
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
#include "common/bitstring.h"
|
#include "common/bitstring.h"
|
||||||
|
#include "common/errorcode.h"
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -52,6 +53,9 @@ class AdnlQuery : public td::actor::Actor {
|
||||||
}
|
}
|
||||||
void tear_down() override {
|
void tear_down() override {
|
||||||
destroy_(id_);
|
destroy_(id_);
|
||||||
|
if (promise_) {
|
||||||
|
promise_.set_error(td::Status::Error(ErrorCode::cancelled, "Cancelled"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -279,6 +279,7 @@ if (TON_USE_ASAN AND NOT WIN32)
|
||||||
set(TURN_OFF_LSAN export LSAN_OPTIONS=detect_leaks=0)
|
set(TURN_OFF_LSAN export LSAN_OPTIONS=detect_leaks=0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY smartcont/auto)
|
||||||
if (NOT CMAKE_CROSSCOMPILING)
|
if (NOT CMAKE_CROSSCOMPILING)
|
||||||
set(GENERATE_TLB_CMD tlbc)
|
set(GENERATE_TLB_CMD tlbc)
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
|
@ -295,29 +296,41 @@ if (NOT CMAKE_CROSSCOMPILING)
|
||||||
add_custom_target(gen_fif ALL)
|
add_custom_target(gen_fif ALL)
|
||||||
function(GenFif)
|
function(GenFif)
|
||||||
set(options )
|
set(options )
|
||||||
set(oneValueArgs DEST)
|
set(oneValueArgs DEST NAME)
|
||||||
set(multiValueArgs SOURCE)
|
set(multiValueArgs SOURCE)
|
||||||
set(FUNC_LIB_SOURCE smartcont/stdlib.fc)
|
set(FUNC_LIB_SOURCE smartcont/stdlib.fc)
|
||||||
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
|
||||||
string(REGEX REPLACE "[^a-zA-Z_]" "_" ID ${ARG_DEST})
|
string(REGEX REPLACE "[^a-zA-Z_]" "_" ID ${ARG_DEST})
|
||||||
|
set(ARG_DEST_FIF "${ARG_DEST}.fif")
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
COMMENT "Generate ${ARG_DEST}"
|
COMMENT "Generate ${ARG_DEST_FIF}"
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
COMMAND func -PS -o ${ARG_DEST} ${FUNC_LIB_SOURCE} ${ARG_SOURCE}
|
COMMAND func -PS -o ${ARG_DEST_FIF} ${FUNC_LIB_SOURCE} ${ARG_SOURCE}
|
||||||
MAIN_DEPENDENCY ${ARG_SOURCE}
|
MAIN_DEPENDENCY ${ARG_SOURCE}
|
||||||
DEPENDS func ${FUNC_LIB_SOURCE}
|
DEPENDS func ${FUNC_LIB_SOURCE}
|
||||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST}
|
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_FIF}
|
||||||
)
|
)
|
||||||
add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST})
|
set(ARG_DEST_CPP "${ARG_DEST}.cpp")
|
||||||
|
add_custom_command(
|
||||||
|
COMMENT "Generate ${ARG_DEST_CPP}"
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMAND fift -Ifift/lib:smartcont -s asm-to-cpp.fif ${ARG_DEST_FIF} ${ARG_DEST_CPP} ${ARG_NAME}
|
||||||
|
MAIN_DEPENDENCY ${ARG_SOURCE}
|
||||||
|
DEPENDS fift ${ARG_DEST_FIF} smartcont/asm-to-cpp.fif
|
||||||
|
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_DEST_CPP}
|
||||||
|
)
|
||||||
|
add_custom_target(gen_fif_${ID} DEPENDS ${ARG_DEST_FIF} ${ARG_DEST_CPP})
|
||||||
add_dependencies(gen_fif gen_fif_${ID})
|
add_dependencies(gen_fif gen_fif_${ID})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
GenFif(DEST smartcont/config-code.fif SOURCE smartcont/config-code.fc)
|
GenFif(DEST smartcont/auto/config-code SOURCE smartcont/config-code.fc NAME config)
|
||||||
GenFif(DEST smartcont/wallet-code.fif SOURCE smartcont/wallet-code.fc)
|
GenFif(DEST smartcont/auto/wallet-code SOURCE smartcont/wallet-code.fc NAME wallet)
|
||||||
GenFif(DEST smartcont/simple-wallet-code.fif SOURCE smartcont/simple-wallet-code.fc)
|
GenFif(DEST smartcont/auto/simple-wallet-code SOURCE smartcont/simple-wallet-code.fc NAME simple-wallet)
|
||||||
GenFif(DEST smartcont/highload-wallet-code.fif SOURCE smartcont/highload-wallet-code.fc)
|
GenFif(DEST smartcont/auto/highload-wallet-code SOURCE smartcont/highload-wallet-code.fc NAME highload-wallet)
|
||||||
GenFif(DEST smartcont/highload-wallet-v2-code.fif SOURCE smartcont/highload-wallet-v2-code.fc)
|
GenFif(DEST smartcont/auto/highload-wallet-v2-code SOURCE smartcont/highload-wallet-v2-code.fc NAME highoad-wallet-v2)
|
||||||
GenFif(DEST smartcont/elector-code.fif SOURCE smartcont/elector-code.fc)
|
GenFif(DEST smartcont/auto/elector-code SOURCE smartcont/elector-code.fc NAME elector-code)
|
||||||
|
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)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(create-state block/create-state.cpp)
|
add_executable(create-state block/create-state.cpp)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include "tl/tlblib.hpp"
|
#include "tl/tlblib.hpp"
|
||||||
#include "td/utils/bits.h"
|
#include "td/utils/bits.h"
|
||||||
|
#include "td/utils/CancellationToken.h"
|
||||||
#include "td/utils/StringBuilder.h"
|
#include "td/utils/StringBuilder.h"
|
||||||
#include "ton/ton-types.h"
|
#include "ton/ton-types.h"
|
||||||
|
|
||||||
|
@ -162,12 +163,12 @@ struct MsgProcessedUpto {
|
||||||
MsgProcessedUpto(ton::ShardId _shard, ton::BlockSeqno _mcseqno, ton::LogicalTime _lt, td::ConstBitPtr _hash)
|
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) {
|
: 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);
|
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,
|
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
|
// NB: this is for checking whether we have already imported an internal message
|
||||||
bool already_processed(const EnqueuedMsgDescr& msg) const;
|
bool already_processed(const EnqueuedMsgDescr& msg) const;
|
||||||
};
|
};
|
||||||
|
@ -573,7 +574,7 @@ struct BlockProofChain {
|
||||||
bool last_link_incomplete() const {
|
bool last_link_incomplete() const {
|
||||||
return !links.empty() && last_link().incomplete();
|
return !links.empty() && last_link().incomplete();
|
||||||
}
|
}
|
||||||
td::Status validate();
|
td::Status validate(td::CancellationToken cancellation_token = {});
|
||||||
};
|
};
|
||||||
|
|
||||||
int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull old_shard, ton::ShardIdFull subshard);
|
int filter_out_msg_queue(vm::AugmentedDictionary& out_queue, ton::ShardIdFull old_shard, ton::ShardIdFull subshard);
|
||||||
|
|
|
@ -424,7 +424,7 @@ td::Status BlockProofLink::validate(td::uint32* save_utime) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Status BlockProofChain::validate() {
|
td::Status BlockProofChain::validate(td::CancellationToken cancellation_token) {
|
||||||
valid = false;
|
valid = false;
|
||||||
has_key_block = false;
|
has_key_block = false;
|
||||||
has_utime = false;
|
has_utime = false;
|
||||||
|
@ -450,6 +450,9 @@ td::Status BlockProofChain::validate() {
|
||||||
<< link.from.to_str() << " but the previous link ends at different block "
|
<< link.from.to_str() << " but the previous link ends at different block "
|
||||||
<< cur.to_str());
|
<< cur.to_str());
|
||||||
}
|
}
|
||||||
|
if (cancellation_token) {
|
||||||
|
return td::Status::Error("Cancelled");
|
||||||
|
}
|
||||||
auto err = link.validate(&last_utime);
|
auto err = link.validate(&last_utime);
|
||||||
if (err.is_error()) {
|
if (err.is_error()) {
|
||||||
return td::Status::Error(PSTRING() << "link #" << i << " in BlockProofChain is invalid: " << err.to_string());
|
return td::Status::Error(PSTRING() << "link #" << i << " in BlockProofChain is invalid: " << err.to_string());
|
||||||
|
|
|
@ -975,6 +975,8 @@ x{F82} @Defop(4u) GETPARAM
|
||||||
x{F823} @Defop NOW
|
x{F823} @Defop NOW
|
||||||
x{F824} @Defop BLOCKLT
|
x{F824} @Defop BLOCKLT
|
||||||
x{F825} @Defop LTIME
|
x{F825} @Defop LTIME
|
||||||
|
x{F826} @Defop BALANCE
|
||||||
|
x{F827} @Defop RANDSEED
|
||||||
x{F828} @Defop MYADDR
|
x{F828} @Defop MYADDR
|
||||||
x{F829} @Defop CONFIGROOT
|
x{F829} @Defop CONFIGROOT
|
||||||
x{F830} @Defop CONFIGDICT
|
x{F830} @Defop CONFIGDICT
|
||||||
|
|
|
@ -136,3 +136,15 @@ recursive append-long-bytes {
|
||||||
// S -- c
|
// S -- c
|
||||||
{ <b over $len { 0 32 u, swap 36 append-long-string } { nip } cond b>
|
{ <b over $len { 0 32 u, swap 36 append-long-string } { nip } cond b>
|
||||||
} : simple-transfer-body
|
} : simple-transfer-body
|
||||||
|
|
||||||
|
// ( S -- x ) parse public key
|
||||||
|
{ dup $len 48 <> abort"public key must be 48 characters long"
|
||||||
|
base64>B dup Blen 36 <> abort"public key must be 48 characters long"
|
||||||
|
34 B| 16 B>u@ over crc16 <> abort"crc16 mismatch in public key"
|
||||||
|
16 B>u@+ 0x3ee6 <> abort"invalid tag in public key"
|
||||||
|
256 B>u@
|
||||||
|
} : parse-pubkey
|
||||||
|
{ bl word parse-pubkey 1 'nop } ::_ PK'
|
||||||
|
// ( x -- S ) serialize public key
|
||||||
|
{ 256 u>B B{3ee6} swap B+ dup crc16 16 u>B B+ B>base64 } : pubkey>$
|
||||||
|
{ pubkey>$ type } : .pubkey
|
||||||
|
|
|
@ -614,6 +614,43 @@ void interpret_str_reverse(vm::Stack& stack) {
|
||||||
stack.push_string(std::move(s));
|
stack.push_string(std::move(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void interpret_utf8_str_len(vm::Stack& stack) {
|
||||||
|
std::string s = stack.pop_string();
|
||||||
|
long long cnt = 0;
|
||||||
|
for (char c : s) {
|
||||||
|
if ((c & 0xc0) != 0x80) {
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack.push_smallint(cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void interpret_utf8_str_split(vm::Stack& stack) {
|
||||||
|
stack.check_underflow(2);
|
||||||
|
unsigned c = stack.pop_smallint_range(0xffff);
|
||||||
|
std::string s = stack.pop_string();
|
||||||
|
if (c > s.size()) {
|
||||||
|
throw IntError{"not enough utf8 characters for cutting"};
|
||||||
|
}
|
||||||
|
auto it = s.begin();
|
||||||
|
for (; it < s.end(); ++it) {
|
||||||
|
if ((*it & 0xc0) != 0x80) {
|
||||||
|
if (!c) {
|
||||||
|
stack.push_string(std::string{s.begin(), it});
|
||||||
|
stack.push_string(std::string{it, s.end()});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
--c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!c) {
|
||||||
|
stack.push_string(std::move(s));
|
||||||
|
stack.push_string(std::string{});
|
||||||
|
} else {
|
||||||
|
throw IntError{"not enough utf8 characters for cutting"};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void interpret_str_remove_trailing_int(vm::Stack& stack, int arg) {
|
void interpret_str_remove_trailing_int(vm::Stack& stack, int arg) {
|
||||||
char x = (char)(arg ? arg : stack.pop_long_range(127));
|
char x = (char)(arg ? arg : stack.pop_long_range(127));
|
||||||
std::string s = stack.pop_string();
|
std::string s = stack.pop_string();
|
||||||
|
@ -1797,6 +1834,16 @@ void interpret_char(IntCtx& ctx) {
|
||||||
push_argcount(ctx, 1);
|
push_argcount(ctx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void interpret_char_internal(vm::Stack& stack) {
|
||||||
|
auto s = stack.pop_string();
|
||||||
|
int len = (s.size() < 10 ? (int)s.size() : 10);
|
||||||
|
int code = str_utf8_code(s.c_str(), len);
|
||||||
|
if (code < 0 || s.size() != (unsigned)len) {
|
||||||
|
throw IntError{"exactly one character expected"};
|
||||||
|
}
|
||||||
|
stack.push_smallint(code);
|
||||||
|
}
|
||||||
|
|
||||||
int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool allow_frac = true,
|
int parse_number(std::string s, td::RefInt256& num, td::RefInt256& denom, bool allow_frac = true,
|
||||||
bool throw_error = false) {
|
bool throw_error = false) {
|
||||||
if (allow_frac) {
|
if (allow_frac) {
|
||||||
|
@ -2496,6 +2543,7 @@ void init_words_common(Dictionary& d) {
|
||||||
// char/string manipulation
|
// char/string manipulation
|
||||||
d.def_active_word("\"", interpret_quote_str);
|
d.def_active_word("\"", interpret_quote_str);
|
||||||
d.def_active_word("char ", interpret_char);
|
d.def_active_word("char ", interpret_char);
|
||||||
|
d.def_stack_word("(char) ", interpret_char_internal);
|
||||||
d.def_ctx_word("emit ", interpret_emit);
|
d.def_ctx_word("emit ", interpret_emit);
|
||||||
d.def_ctx_word("space ", std::bind(interpret_emit_const, _1, ' '));
|
d.def_ctx_word("space ", std::bind(interpret_emit_const, _1, ' '));
|
||||||
d.def_ctx_word("cr ", std::bind(interpret_emit_const, _1, '\n'));
|
d.def_ctx_word("cr ", std::bind(interpret_emit_const, _1, '\n'));
|
||||||
|
@ -2515,6 +2563,8 @@ void init_words_common(Dictionary& d) {
|
||||||
d.def_stack_word("-trailing0 ", std::bind(interpret_str_remove_trailing_int, _1, '0'));
|
d.def_stack_word("-trailing0 ", std::bind(interpret_str_remove_trailing_int, _1, '0'));
|
||||||
d.def_stack_word("$len ", interpret_str_len);
|
d.def_stack_word("$len ", interpret_str_len);
|
||||||
d.def_stack_word("Blen ", interpret_bytes_len);
|
d.def_stack_word("Blen ", interpret_bytes_len);
|
||||||
|
d.def_stack_word("$Len ", interpret_utf8_str_len);
|
||||||
|
d.def_stack_word("$Split ", interpret_utf8_str_split);
|
||||||
d.def_ctx_word("Bx. ", std::bind(interpret_bytes_hex_print_raw, _1, true));
|
d.def_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, true));
|
||||||
d.def_stack_word("B>x ", std::bind(interpret_bytes_to_hex, _1, false));
|
d.def_stack_word("B>x ", std::bind(interpret_bytes_to_hex, _1, false));
|
||||||
|
|
|
@ -205,6 +205,9 @@ void VarDescr::clear_value() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VarDescrList::show(std::ostream& os) const {
|
void VarDescrList::show(std::ostream& os) const {
|
||||||
|
if (unreachable) {
|
||||||
|
os << "<unreachable> ";
|
||||||
|
}
|
||||||
os << "[";
|
os << "[";
|
||||||
for (const auto& v : list) {
|
for (const auto& v : list) {
|
||||||
os << ' ' << v;
|
os << ' ' << v;
|
||||||
|
|
|
@ -272,6 +272,12 @@ VarDescrList& VarDescrList::operator+=(const VarDescrList& y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VarDescrList VarDescrList::operator|(const VarDescrList& y) const {
|
VarDescrList VarDescrList::operator|(const VarDescrList& y) const {
|
||||||
|
if (y.unreachable) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
if (unreachable) {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
VarDescrList res;
|
VarDescrList res;
|
||||||
auto it1 = list.cbegin();
|
auto it1 = list.cbegin();
|
||||||
auto it2 = y.list.cbegin();
|
auto it2 = y.list.cbegin();
|
||||||
|
@ -289,7 +295,11 @@ VarDescrList VarDescrList::operator|(const VarDescrList& y) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
VarDescrList& VarDescrList::operator|=(const VarDescrList& y) {
|
VarDescrList& VarDescrList::operator|=(const VarDescrList& y) {
|
||||||
return *this = *this | y;
|
if (y.unreachable) {
|
||||||
|
return *this;
|
||||||
|
} else {
|
||||||
|
return *this = *this | y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VarDescrList& VarDescrList::operator&=(const VarDescrList& values) {
|
VarDescrList& VarDescrList::operator&=(const VarDescrList& values) {
|
||||||
|
@ -299,16 +309,22 @@ VarDescrList& VarDescrList::operator&=(const VarDescrList& values) {
|
||||||
*item &= vd;
|
*item &= vd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
unreachable |= values.unreachable;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
VarDescrList& VarDescrList::import_values(const VarDescrList& values) {
|
VarDescrList& VarDescrList::import_values(const VarDescrList& values) {
|
||||||
for (const VarDescr& vd : values.list) {
|
if (values.unreachable) {
|
||||||
VarDescr* item = operator[](vd.idx);
|
set_unreachable();
|
||||||
if (item) {
|
} else
|
||||||
item->set_value(vd);
|
for (auto& vd : list) {
|
||||||
|
auto new_vd = values[vd.idx];
|
||||||
|
if (new_vd) {
|
||||||
|
vd.set_value(*new_vd);
|
||||||
|
} else {
|
||||||
|
vd.clear_value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,8 +674,11 @@ void Op::prepare_args(VarDescrList values) {
|
||||||
const VarDescr* val = values[right[i]];
|
const VarDescr* val = values[right[i]];
|
||||||
if (val) {
|
if (val) {
|
||||||
args[i].set_value(*val);
|
args[i].set_value(*val);
|
||||||
args[i].clear_unused();
|
// args[i].clear_unused();
|
||||||
|
} else {
|
||||||
|
args[i].clear_value();
|
||||||
}
|
}
|
||||||
|
args[i].clear_unused();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,7 +689,7 @@ VarDescrList Op::fwd_analyze(VarDescrList values) {
|
||||||
case _Import:
|
case _Import:
|
||||||
break;
|
break;
|
||||||
case _Return:
|
case _Return:
|
||||||
values.list.clear();
|
values.set_unreachable();
|
||||||
break;
|
break;
|
||||||
case _IntConst: {
|
case _IntConst: {
|
||||||
values.add_newval(left[0]).set_const(int_const);
|
values.add_newval(left[0]).set_const(int_const);
|
||||||
|
|
|
@ -668,6 +668,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
||||||
return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v != 0);
|
return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v != 0);
|
||||||
}
|
}
|
||||||
int v = compute_compare(x, y, mode);
|
int v = compute_compare(x, y, mode);
|
||||||
|
// std::cerr << "compute_compare(" << x << ", " << y << ", " << mode << ") = " << v << std::endl;
|
||||||
assert(v);
|
assert(v);
|
||||||
if (!(v & (v - 1))) {
|
if (!(v & (v - 1))) {
|
||||||
r.set_const(v - (v >> 2) - 2);
|
r.set_const(v - (v >> 2) - 2);
|
||||||
|
@ -685,6 +686,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
||||||
if (v & 4) {
|
if (v & 4) {
|
||||||
r.val &= VarDescr::ConstOne;
|
r.val &= VarDescr::ConstOne;
|
||||||
}
|
}
|
||||||
|
// std::cerr << "result: " << r << std::endl;
|
||||||
static const char* cmp_int_names[] = {"", "GTINT", "EQINT", "GTINT", "LESSINT", "NEQINT", "LESSINT"};
|
static const char* cmp_int_names[] = {"", "GTINT", "EQINT", "GTINT", "LESSINT", "NEQINT", "LESSINT"};
|
||||||
static const char* cmp_names[] = {"", "GREATER", "EQUAL", "GEQ", "LESS", "NEQ", "LEQ", "CMP"};
|
static const char* cmp_names[] = {"", "GREATER", "EQUAL", "GEQ", "LESS", "NEQ", "LEQ", "CMP"};
|
||||||
static int cmp_int_delta[] = {0, 0, 0, -1, 0, 0, 1};
|
static int cmp_int_delta[] = {0, 0, 0, -1, 0, 0, 1};
|
||||||
|
@ -911,6 +913,7 @@ void define_builtins() {
|
||||||
define_builtin_func("false", Int, /* AsmOp::Const("FALSE") */ std::bind(compile_bool_const, _1, _2, false));
|
define_builtin_func("false", Int, /* AsmOp::Const("FALSE") */ std::bind(compile_bool_const, _1, _2, false));
|
||||||
// define_builtin_func("null", Null, AsmOp::Const("PUSHNULL"));
|
// define_builtin_func("null", Null, AsmOp::Const("PUSHNULL"));
|
||||||
define_builtin_func("nil", Tuple, AsmOp::Const("PUSHNULL"));
|
define_builtin_func("nil", Tuple, AsmOp::Const("PUSHNULL"));
|
||||||
|
define_builtin_func("Nil", Tuple, AsmOp::Const("NIL"));
|
||||||
define_builtin_func("null?", TypeExpr::new_forall({X}, TypeExpr::new_map(X, Int)), compile_is_null);
|
define_builtin_func("null?", TypeExpr::new_forall({X}, TypeExpr::new_map(X, Int)), compile_is_null);
|
||||||
define_builtin_func("cons", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor(X, Tuple), Tuple)),
|
define_builtin_func("cons", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor(X, Tuple), Tuple)),
|
||||||
AsmOp::Custom("CONS", 2, 1));
|
AsmOp::Custom("CONS", 2, 1));
|
||||||
|
@ -932,6 +935,10 @@ void define_builtins() {
|
||||||
AsmOp::Custom("4 TUPLE", 4, 1));
|
AsmOp::Custom("4 TUPLE", 4, 1));
|
||||||
define_builtin_func("untuple4", TypeExpr::new_forall({X, Y, Z, T}, TypeExpr::new_map(Tuple, XYZT)),
|
define_builtin_func("untuple4", TypeExpr::new_forall({X, Y, Z, T}, TypeExpr::new_map(Tuple, XYZT)),
|
||||||
AsmOp::Custom("4 UNTUPLE", 1, 4));
|
AsmOp::Custom("4 UNTUPLE", 1, 4));
|
||||||
|
define_builtin_func("first", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, X)), AsmOp::Custom("FIRST", 1, 1));
|
||||||
|
define_builtin_func("second", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, X)), AsmOp::Custom("SECOND", 1, 1));
|
||||||
|
define_builtin_func("third", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, X)), AsmOp::Custom("THIRD", 1, 1));
|
||||||
|
define_builtin_func("fourth", TypeExpr::new_forall({X}, TypeExpr::new_map(Tuple, X)), AsmOp::Custom("3 INDEX", 1, 1));
|
||||||
define_builtin_func("throw", impure_un_op, compile_throw, true);
|
define_builtin_func("throw", impure_un_op, compile_throw, true);
|
||||||
define_builtin_func("throw_if", impure_bin_op, std::bind(compile_cond_throw, _1, _2, true), true);
|
define_builtin_func("throw_if", impure_bin_op, std::bind(compile_cond_throw, _1, _2, true), true);
|
||||||
define_builtin_func("throw_unless", impure_bin_op, std::bind(compile_cond_throw, _1, _2, false), true);
|
define_builtin_func("throw_unless", impure_bin_op, std::bind(compile_cond_throw, _1, _2, false), true);
|
||||||
|
@ -947,7 +954,7 @@ void define_builtins() {
|
||||||
define_builtin_func("preload_bits", prefetch_slice_op, std::bind(compile_fetch_slice, _1, _2, false));
|
define_builtin_func("preload_bits", prefetch_slice_op, std::bind(compile_fetch_slice, _1, _2, false));
|
||||||
define_builtin_func("int_at", TypeExpr::new_map(TupleInt, Int), compile_tuple_at);
|
define_builtin_func("int_at", TypeExpr::new_map(TupleInt, Int), compile_tuple_at);
|
||||||
define_builtin_func("cell_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at);
|
define_builtin_func("cell_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at);
|
||||||
define_builtin_func("slice_at", TypeExpr::new_map(TupleInt, Cell), compile_tuple_at);
|
define_builtin_func("slice_at", TypeExpr::new_map(TupleInt, Slice), compile_tuple_at);
|
||||||
define_builtin_func("tuple_at", TypeExpr::new_map(TupleInt, Tuple), compile_tuple_at);
|
define_builtin_func("tuple_at", TypeExpr::new_map(TupleInt, Tuple), compile_tuple_at);
|
||||||
define_builtin_func("at", TypeExpr::new_forall({X}, TypeExpr::new_map(TupleInt, X)), compile_tuple_at);
|
define_builtin_func("at", TypeExpr::new_forall({X}, TypeExpr::new_map(TupleInt, X)), compile_tuple_at);
|
||||||
define_builtin_func("touch", TypeExpr::new_forall({X}, TypeExpr::new_map(X, X)), AsmOp::Nop());
|
define_builtin_func("touch", TypeExpr::new_forall({X}, TypeExpr::new_map(X, X)), AsmOp::Nop());
|
||||||
|
|
|
@ -60,21 +60,36 @@ void generate_output_func(SymDef* func_sym) {
|
||||||
code.print(std::cerr, 9);
|
code.print(std::cerr, 9);
|
||||||
}
|
}
|
||||||
code.simplify_var_types();
|
code.simplify_var_types();
|
||||||
// std::cerr << "after simplify_var_types: \n"; code.print(std::cerr, 0);
|
if (verbosity >= 5) {
|
||||||
|
std::cerr << "after simplify_var_types: \n";
|
||||||
|
code.print(std::cerr, 0);
|
||||||
|
}
|
||||||
code.prune_unreachable_code();
|
code.prune_unreachable_code();
|
||||||
// std::cerr << "after prune_unreachable: \n"; code.print(std::cerr, 0);
|
if (verbosity >= 5) {
|
||||||
|
std::cerr << "after prune_unreachable: \n";
|
||||||
|
code.print(std::cerr, 0);
|
||||||
|
}
|
||||||
code.split_vars(true);
|
code.split_vars(true);
|
||||||
// std::cerr << "after split_vars: \n"; code.print(std::cerr, 0);
|
if (verbosity >= 5) {
|
||||||
|
std::cerr << "after split_vars: \n";
|
||||||
|
code.print(std::cerr, 0);
|
||||||
|
}
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
code.compute_used_code_vars();
|
code.compute_used_code_vars();
|
||||||
if (verbosity >= 5) {
|
if (verbosity >= 4) {
|
||||||
std::cerr << "after compute_used_vars: \n";
|
std::cerr << "after compute_used_vars: \n";
|
||||||
code.print(std::cerr, 6);
|
code.print(std::cerr, 6);
|
||||||
}
|
}
|
||||||
code.fwd_analyze();
|
code.fwd_analyze();
|
||||||
// std::cerr << "after fwd_analyze: \n"; code.print(std::cerr, 6);
|
if (verbosity >= 5) {
|
||||||
|
std::cerr << "after fwd_analyze: \n";
|
||||||
|
code.print(std::cerr, 6);
|
||||||
|
}
|
||||||
code.prune_unreachable_code();
|
code.prune_unreachable_code();
|
||||||
// std::cerr << "after prune_unreachable: \n"; code.print(std::cerr, 6);
|
if (verbosity >= 5) {
|
||||||
|
std::cerr << "after prune_unreachable: \n";
|
||||||
|
code.print(std::cerr, 6);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
code.mark_noreturn();
|
code.mark_noreturn();
|
||||||
if (verbosity >= 3) {
|
if (verbosity >= 3) {
|
||||||
|
|
|
@ -397,6 +397,7 @@ inline std::ostream& operator<<(std::ostream& os, const VarDescr& vd) {
|
||||||
|
|
||||||
struct VarDescrList {
|
struct VarDescrList {
|
||||||
std::vector<VarDescr> list;
|
std::vector<VarDescr> list;
|
||||||
|
bool unreachable{false};
|
||||||
VarDescrList() : list() {
|
VarDescrList() : list() {
|
||||||
}
|
}
|
||||||
VarDescrList(const std::vector<VarDescr>& _list) : list(_list) {
|
VarDescrList(const std::vector<VarDescr>& _list) : list(_list) {
|
||||||
|
@ -430,6 +431,10 @@ struct VarDescrList {
|
||||||
VarDescrList operator|(const VarDescrList& y) const;
|
VarDescrList operator|(const VarDescrList& y) const;
|
||||||
VarDescrList& operator|=(const VarDescrList& values);
|
VarDescrList& operator|=(const VarDescrList& values);
|
||||||
void show(std::ostream& os) const;
|
void show(std::ostream& os) const;
|
||||||
|
void set_unreachable() {
|
||||||
|
list.clear();
|
||||||
|
unreachable = true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const VarDescrList& values) {
|
inline std::ostream& operator<<(std::ostream& os, const VarDescrList& values) {
|
||||||
|
|
13
crypto/func/test/w3.fc
Normal file
13
crypto/func/test/w3.fc
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
() main(cs) impure {
|
||||||
|
int i = 0;
|
||||||
|
if (cs.slice_refs()) {
|
||||||
|
do {
|
||||||
|
i = i + 1;
|
||||||
|
} until(i > 10);
|
||||||
|
}
|
||||||
|
set_data(begin_cell()
|
||||||
|
.store_uint(1, 32)
|
||||||
|
.store_uint(2, 32)
|
||||||
|
.store_uint(i, 32)
|
||||||
|
.end_cell());
|
||||||
|
}
|
13
crypto/func/test/w4.fc
Normal file
13
crypto/func/test/w4.fc
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
_ main(cell dict, int t3) {
|
||||||
|
int index = -1;
|
||||||
|
do {
|
||||||
|
(index, slice value, int found) = dict.udict_get_next?(32, index);
|
||||||
|
if (found) {
|
||||||
|
(int temp1, int temp2) = (value~load_uint(16), value~load_uint(32));
|
||||||
|
if (t3 > temp2) {
|
||||||
|
dict~udict_delete_get?(32, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} until ( ~ found);
|
||||||
|
return dict;
|
||||||
|
}
|
14
crypto/func/test/w5.fc
Normal file
14
crypto/func/test/w5.fc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
(cell) recv_external(slice in_msg) impure {
|
||||||
|
cell mydict = new_dict();
|
||||||
|
builder r = begin_cell().store_int(10, 16);
|
||||||
|
mydict~udict_set_builder(32, 1, r );
|
||||||
|
int index = -1;
|
||||||
|
do {
|
||||||
|
(var index, var value, var found) = mydict.udict_get_next?(32, index);
|
||||||
|
} until ( ~ found );
|
||||||
|
return mydict;
|
||||||
|
}
|
||||||
|
|
||||||
|
() recv_internal() impure {
|
||||||
|
;; Nothing
|
||||||
|
}
|
12
crypto/func/test/w6.fc
Normal file
12
crypto/func/test/w6.fc
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
int test(int x) method_id {
|
||||||
|
int i = 0;
|
||||||
|
;; int f = false;
|
||||||
|
do {
|
||||||
|
i = i + 1;
|
||||||
|
if (i > 5) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int f = (i * i == 64);
|
||||||
|
} until (f);
|
||||||
|
return -1;
|
||||||
|
}
|
14
crypto/func/test/w7.fc
Normal file
14
crypto/func/test/w7.fc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
int test(int y) {
|
||||||
|
int x = 1;
|
||||||
|
if (y > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return x > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f(int y) {
|
||||||
|
if (y > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 2;
|
||||||
|
}
|
|
@ -182,3 +182,48 @@ dictnew constant special-dict
|
||||||
-2 constant run_ticktock
|
-2 constant run_ticktock
|
||||||
-3 constant split_prepare
|
-3 constant split_prepare
|
||||||
-4 constant split_install
|
-4 constant split_install
|
||||||
|
|
||||||
|
// public key conversion
|
||||||
|
|
||||||
|
|
||||||
|
// restricted wallet creation
|
||||||
|
"auto/restricted-wallet-code.fif" include =: RWCode1
|
||||||
|
"auto/restricted-wallet2-code.fif" include =: RWCode2
|
||||||
|
|
||||||
|
// pubkey amount --
|
||||||
|
{ over ."Key " pubkey>$ type ." -> "
|
||||||
|
RWCode1 // code
|
||||||
|
<b 1 32 u, 3 roll 256 u, b> // data
|
||||||
|
empty_cell // libs
|
||||||
|
3 roll // balance
|
||||||
|
0 // split_depth
|
||||||
|
0 // ticktock
|
||||||
|
2 // mode: create
|
||||||
|
register_smc
|
||||||
|
Masterchain 6 .Addr cr
|
||||||
|
} : create-wallet1
|
||||||
|
|
||||||
|
// D x t -- D'
|
||||||
|
{ <b rot Gram, swap rot 16 b>idict! not abort"cannot add value"
|
||||||
|
} : rdict-entry
|
||||||
|
// balance -- dict
|
||||||
|
{ dictnew
|
||||||
|
over -32768 rdict-entry
|
||||||
|
over 3/4 */ 92 rdict-entry
|
||||||
|
over 1/2 */ 183 rdict-entry
|
||||||
|
swap 1/4 */ 366 rdict-entry
|
||||||
|
0 548 rdict-entry
|
||||||
|
} : make-rdict
|
||||||
|
|
||||||
|
// pubkey amount --
|
||||||
|
{ over ."Key " pubkey>$ type ." -> "
|
||||||
|
RWCode2 // code
|
||||||
|
<b 1 32 u, 3 pick 256 u, 3 roll make-rdict dict, b> // data
|
||||||
|
empty_cell // libs
|
||||||
|
3 roll // balance
|
||||||
|
0 // split_depth
|
||||||
|
0 // ticktock
|
||||||
|
2 // mode: create
|
||||||
|
register_smc
|
||||||
|
Masterchain 6 .Addr cr
|
||||||
|
} : create-wallet2
|
||||||
|
|
31
crypto/smartcont/asm-to-cpp.fif
Executable file
31
crypto/smartcont/asm-to-cpp.fif
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/fift -s
|
||||||
|
"TonUtil.fif" include
|
||||||
|
"Asm.fif" include
|
||||||
|
|
||||||
|
{ ."usage: " @' $0 type ." <source> <destination> <name>" cr
|
||||||
|
."Compiles asm from <source> file and stores serialization in a way prepared for usage from c++ to <destination> " cr 1 halt
|
||||||
|
} : usage
|
||||||
|
|
||||||
|
|
||||||
|
$# 3 - ' usage if
|
||||||
|
|
||||||
|
|
||||||
|
$1 =: source
|
||||||
|
$2 =: destination
|
||||||
|
$3 =: name
|
||||||
|
|
||||||
|
."Include source from " source type cr
|
||||||
|
source include
|
||||||
|
|
||||||
|
boc>B
|
||||||
|
."Convert boc to base64" cr
|
||||||
|
B>base64
|
||||||
|
|
||||||
|
{ char " chr tuck $+ $+ } : wrp
|
||||||
|
wrp // "<code>"
|
||||||
|
"with_tvm_code(" name wrp $+ +", " swap ");" 10 hold $+ $+ // "with_tm_code("<code>");\n"
|
||||||
|
|
||||||
|
$>B
|
||||||
|
|
||||||
|
."Store tvm code to " destination type cr
|
||||||
|
destination B>file
|
1
crypto/smartcont/auto/config-code.cpp
Normal file
1
crypto/smartcont/auto/config-code.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
with_tvm_code("config", "te6ccgECEwEAAhQAART/APSkE/Sg8sgLAQIBIAIDAgLPBAUCAvEPEAIBIAYHAgEgDA0CASAICQIBIAoLAOkAdDTA/pAMCD6RAGkA3GwE7EjxwCxkl8D4ALTH9M/IoIQTlZTVLqOPTIB1NFx+DMgbpIwf5TQ1wv/4gNwBLqbMiHwAiH4I7wCvLCRAuKdgCRY8AGCEO52T0vwBOAxghDudk9v8AXgECRfBCDAAAGDHrCx8qWAAJTtRNDUUDOAIPQVyMwBzxbJ7VSAAMzQ0wcBwBHyidMf0x/TD9MPMCDCAPKJvvKJgACscIAYyMsFUAXPFhTLbssfyz/JAfsAgAgEgDg4AW0cfgz0NcL//gjghBOQ29kcIIAxP/IyxAUy/+DHfoCE8tqEssfyz8BzxbJcPsAgACSAQPADgAK0MO1E0NSAIIAkUzH0aiBukxAjW444INAg10nCJ44p0wfXCx8BwBH4IxK+sI4VAYAiVBBE9G5UUyH0bjCAJEAT9FowkxAjW+KUEDRfA+LiyMwBzxbJ7VSABASARAf6DCNcYINMf0x/TH/gjErnyY+1E0NTTH9P/0VFBuvKhBfkBVBBj+RDyovgAIoIQQ2ZQIbqcMgHTH9TRQBSAIPQVjjcighBOQ29kupYyAdTR+wSOJCKCEFBiSyG6lTEx0//RjhMighBOQ+8FupQyAfAGlDAB8mDi4uIC4gGkyBLMEgAOyx/L/8ntVA==");
|
323
crypto/smartcont/auto/config-code.fif
Normal file
323
crypto/smartcont/auto/config-code.fif
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
// automatically generated from `smartcont/stdlib.fc` `smartcont/config-code.fc`
|
||||||
|
PROGRAM{
|
||||||
|
DECLPROC set_conf_param
|
||||||
|
DECLPROC check_validator_set
|
||||||
|
DECLPROC send_answer
|
||||||
|
DECLPROC send_confirmation
|
||||||
|
DECLPROC send_error
|
||||||
|
DECLPROC recv_internal
|
||||||
|
DECLPROC change_elector_code
|
||||||
|
DECLPROC recv_external
|
||||||
|
DECLPROC run_ticktock
|
||||||
|
set_conf_param PROC:<{
|
||||||
|
// index value
|
||||||
|
c4 PUSH // index value _3
|
||||||
|
CTOS // index value cs
|
||||||
|
LDREF // index value cfg_dict cs
|
||||||
|
s3 s3 XCHG2
|
||||||
|
32 PUSHINT // cs value index cfg_dict _9=32
|
||||||
|
DICTISETREF // cs cfg_dict
|
||||||
|
NEWC // cs cfg_dict _11
|
||||||
|
STREF // cs _12
|
||||||
|
SWAP // _12 cs
|
||||||
|
STSLICER // _13
|
||||||
|
ENDC // _14
|
||||||
|
c4 POP
|
||||||
|
}>
|
||||||
|
check_validator_set PROC:<{
|
||||||
|
// vset
|
||||||
|
CTOS // cs
|
||||||
|
8 LDU // _4 cs
|
||||||
|
SWAP // cs _4
|
||||||
|
17 EQINT // cs _8
|
||||||
|
9 THROWIFNOT
|
||||||
|
32 LDU // utime_since cs
|
||||||
|
32 LDU // utime_since utime_until cs
|
||||||
|
16 LDU // utime_since utime_until total cs
|
||||||
|
16 LDU // utime_since utime_until total _42 _41
|
||||||
|
DROP // utime_since utime_until total main
|
||||||
|
DUP // utime_since utime_until total main main
|
||||||
|
0 GTINT // utime_since utime_until total main _28
|
||||||
|
9 THROWIFNOT
|
||||||
|
GEQ // utime_since utime_until _31
|
||||||
|
9 THROWIFNOT
|
||||||
|
}>
|
||||||
|
send_answer PROC:<{
|
||||||
|
// addr query_id ans_tag mode
|
||||||
|
0 PUSHINT // addr query_id ans_tag mode _4=0
|
||||||
|
24 PUSHINT // addr query_id ans_tag mode _4=0 _5=24
|
||||||
|
NEWC // addr query_id ans_tag mode _4=0 _5=24 _6
|
||||||
|
6 STU // addr query_id ans_tag mode _4=0 _8
|
||||||
|
s0 s5 XCHG2 // _4=0 query_id ans_tag mode _8 addr
|
||||||
|
STSLICER // _4=0 query_id ans_tag mode _9
|
||||||
|
s1 s4 XCHG // mode query_id ans_tag _4=0 _9
|
||||||
|
111 STU // mode query_id ans_tag _23
|
||||||
|
32 STU // mode query_id _25
|
||||||
|
64 STU // mode _27
|
||||||
|
ENDC // mode _28
|
||||||
|
SWAP // _28 mode
|
||||||
|
SENDRAWMSG
|
||||||
|
}>
|
||||||
|
send_confirmation PROC:<{
|
||||||
|
// addr query_id ans_tag
|
||||||
|
64 PUSHINT // addr query_id ans_tag _3=64
|
||||||
|
send_answer CALLDICT
|
||||||
|
}>
|
||||||
|
send_error PROC:<{
|
||||||
|
// addr query_id ans_tag
|
||||||
|
64 PUSHINT // addr query_id ans_tag _3=64
|
||||||
|
send_answer CALLDICT
|
||||||
|
}>
|
||||||
|
recv_internal PROC:<{
|
||||||
|
// in_msg_cell in_msg
|
||||||
|
SWAP // in_msg in_msg_cell
|
||||||
|
CTOS // in_msg cs
|
||||||
|
4 LDU // in_msg flags cs
|
||||||
|
LDMSGADDR // in_msg flags _74 _73
|
||||||
|
DROP // in_msg flags s_addr
|
||||||
|
DUP // in_msg flags s_addr s_addr
|
||||||
|
REWRITESTDADDR // in_msg flags s_addr src_wc src_addr
|
||||||
|
SWAP // in_msg flags s_addr src_addr src_wc
|
||||||
|
INC // in_msg flags s_addr src_addr _15
|
||||||
|
s0 s3 XCHG
|
||||||
|
1 PUSHINT // in_msg _15 s_addr src_addr flags _16=1
|
||||||
|
AND // in_msg _15 s_addr src_addr _17
|
||||||
|
s1 s3 XCHG // in_msg src_addr s_addr _15 _17
|
||||||
|
OR // in_msg src_addr s_addr _18
|
||||||
|
s3 PUSH // in_msg src_addr s_addr _18 in_msg
|
||||||
|
SEMPTY // in_msg src_addr s_addr _18 _19
|
||||||
|
OR // in_msg src_addr s_addr _20
|
||||||
|
IFJMP:<{ // in_msg src_addr s_addr
|
||||||
|
3 BLKDROP //
|
||||||
|
}> // in_msg src_addr s_addr
|
||||||
|
s0 s2 XCHG // s_addr src_addr in_msg
|
||||||
|
32 LDU // s_addr src_addr tag in_msg
|
||||||
|
64 LDU // s_addr src_addr tag query_id in_msg
|
||||||
|
s2 PUSH
|
||||||
|
1314280276 PUSHINT // s_addr src_addr tag query_id in_msg tag _29=1314280276
|
||||||
|
EQUAL // s_addr src_addr tag query_id in_msg _30
|
||||||
|
IFJMP:<{ // s_addr src_addr tag query_id in_msg
|
||||||
|
s2 POP // s_addr src_addr in_msg query_id
|
||||||
|
SWAP // s_addr src_addr query_id in_msg
|
||||||
|
LDREF // s_addr src_addr query_id vset in_msg
|
||||||
|
ENDS
|
||||||
|
1 PUSHINT // s_addr src_addr query_id vset _36=1
|
||||||
|
CONFIGOPTPARAM // s_addr src_addr query_id vset elector_param
|
||||||
|
DUP // s_addr src_addr query_id vset elector_param elector_param
|
||||||
|
ISNULL // s_addr src_addr query_id vset elector_param _39
|
||||||
|
IF:<{ // s_addr src_addr query_id vset elector_param
|
||||||
|
DROP // s_addr src_addr query_id vset
|
||||||
|
-1 PUSHINT // s_addr src_addr query_id vset _40=-1
|
||||||
|
}>ELSE<{ // s_addr src_addr query_id vset elector_param
|
||||||
|
CTOS // s_addr src_addr query_id vset _42
|
||||||
|
256 PLDU // s_addr src_addr query_id vset _40
|
||||||
|
}> // s_addr src_addr query_id vset elector_addr
|
||||||
|
s0 s3 XCHG
|
||||||
|
FALSE
|
||||||
|
s0 s4 XCHG // s_addr ok query_id vset src_addr elector_addr
|
||||||
|
EQUAL // s_addr ok query_id vset _47
|
||||||
|
IF:<{ // s_addr ok query_id vset
|
||||||
|
s2 POP // s_addr vset query_id
|
||||||
|
OVER // s_addr vset query_id vset
|
||||||
|
check_validator_set CALLDICT // s_addr vset query_id t_since t_until
|
||||||
|
OVER
|
||||||
|
NOW // s_addr vset query_id t_since t_until t_since t
|
||||||
|
GREATER // s_addr vset query_id t_since t_until _53
|
||||||
|
s0 s2 XCHG // s_addr vset query_id _53 t_until t_since
|
||||||
|
GREATER // s_addr vset query_id _53 _54
|
||||||
|
AND // s_addr vset query_id ok
|
||||||
|
}>ELSE<{
|
||||||
|
s0 s2 XCHG // s_addr vset query_id ok
|
||||||
|
}>
|
||||||
|
IFJMP:<{ // s_addr vset query_id
|
||||||
|
36 PUSHINT // s_addr vset query_id _56=36
|
||||||
|
ROT // s_addr query_id _56=36 vset
|
||||||
|
set_conf_param CALLDICT
|
||||||
|
4000730955 PUSHINT // s_addr query_id _58=4000730955
|
||||||
|
send_confirmation CALLDICT
|
||||||
|
}> // s_addr vset query_id
|
||||||
|
NIP // s_addr query_id
|
||||||
|
4000730991 PUSHINT // s_addr query_id _60=4000730991
|
||||||
|
send_error CALLDICT
|
||||||
|
}> // s_addr src_addr tag query_id in_msg
|
||||||
|
s2 s4 XCHG
|
||||||
|
4 BLKDROP // tag
|
||||||
|
DUP // tag tag
|
||||||
|
0 EQINT // tag _64
|
||||||
|
SWAP
|
||||||
|
31 PUSHPOW2 // _64 tag _67
|
||||||
|
AND // _64 _68
|
||||||
|
OR // _69
|
||||||
|
37 THROWIFNOT
|
||||||
|
}>
|
||||||
|
change_elector_code PROC:<{
|
||||||
|
// cs
|
||||||
|
1 PUSHINT // cs _2=1
|
||||||
|
CONFIGOPTPARAM // cs _3
|
||||||
|
CTOS // cs _4
|
||||||
|
256 PLDU // cs dest_addr
|
||||||
|
NOW // cs dest_addr query_id
|
||||||
|
1313042276 PUSHINT // cs dest_addr query_id _9=1313042276
|
||||||
|
0 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0
|
||||||
|
50431 PUSHINT // cs dest_addr query_id _9=1313042276 _10=0 _11=50431
|
||||||
|
NEWC // cs dest_addr query_id _9=1313042276 _10=0 _11=50431 _12
|
||||||
|
17 STU // cs dest_addr query_id _9=1313042276 _10=0 _14
|
||||||
|
s1 s4 XCHG // cs _10=0 query_id _9=1313042276 dest_addr _14
|
||||||
|
256 STU // cs _10=0 query_id _9=1313042276 _16
|
||||||
|
30 PUSHPOW2 // cs _10=0 query_id _9=1313042276 _16 _19
|
||||||
|
STGRAMS // cs _10=0 query_id _9=1313042276 _20
|
||||||
|
s1 s3 XCHG // cs _9=1313042276 query_id _10=0 _20
|
||||||
|
107 STU // cs _9=1313042276 query_id _34
|
||||||
|
s1 s2 XCHG // cs query_id _9=1313042276 _34
|
||||||
|
32 STU // cs query_id _36
|
||||||
|
64 STU // cs _38
|
||||||
|
SWAP // _38 cs
|
||||||
|
STSLICER // _39
|
||||||
|
ENDC // _40
|
||||||
|
0 PUSHINT // _40 _41=0
|
||||||
|
SENDRAWMSG
|
||||||
|
}>
|
||||||
|
recv_external PROC:<{
|
||||||
|
// in_msg
|
||||||
|
9 PUSHPOW2 // in_msg _3=512
|
||||||
|
LDSLICEX // signature in_msg
|
||||||
|
DUP // signature in_msg cs
|
||||||
|
32 LDU // signature in_msg action cs
|
||||||
|
32 LDU // signature in_msg action msg_seqno cs
|
||||||
|
32 LDU // signature in_msg action msg_seqno valid_until cs
|
||||||
|
NOW // signature in_msg action msg_seqno valid_until cs _19
|
||||||
|
s1 s2 XCHG // signature in_msg action msg_seqno cs valid_until _19
|
||||||
|
LESS // signature in_msg action msg_seqno cs _20
|
||||||
|
35 THROWIF
|
||||||
|
c4 PUSH // signature in_msg action msg_seqno cs _23
|
||||||
|
CTOS // signature in_msg action msg_seqno cs cs2
|
||||||
|
LDREF // signature in_msg action msg_seqno cs cfg_dict cs2
|
||||||
|
32 LDU // signature in_msg action msg_seqno cs cfg_dict stored_seqno cs2
|
||||||
|
256 LDU // signature in_msg action msg_seqno cs cfg_dict stored_seqno public_key cs2
|
||||||
|
ENDS
|
||||||
|
s4 s1 XCPU // signature in_msg action public_key cs cfg_dict stored_seqno msg_seqno stored_seqno
|
||||||
|
EQUAL // signature in_msg action public_key cs cfg_dict stored_seqno _38
|
||||||
|
33 THROWIFNOT
|
||||||
|
s0 s5 XCHG // signature stored_seqno action public_key cs cfg_dict in_msg
|
||||||
|
HASHSU // signature stored_seqno action public_key cs cfg_dict _41
|
||||||
|
s0 s6 s3 XC2PU // cfg_dict stored_seqno action public_key cs _41 signature public_key
|
||||||
|
CHKSIGNU // cfg_dict stored_seqno action public_key cs _42
|
||||||
|
34 THROWIFNOT
|
||||||
|
ACCEPT
|
||||||
|
s2 PUSH
|
||||||
|
1130778657 PUSHINT // cfg_dict stored_seqno action public_key cs action _45=1130778657
|
||||||
|
EQUAL // cfg_dict stored_seqno action public_key cs _46
|
||||||
|
IF:<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
s2 POP // cfg_dict stored_seqno cs public_key
|
||||||
|
SWAP // cfg_dict stored_seqno public_key cs
|
||||||
|
32 LDU // cfg_dict stored_seqno public_key param_index cs
|
||||||
|
LDREF // cfg_dict stored_seqno public_key param_index param_value cs
|
||||||
|
ENDS
|
||||||
|
s0 s1 s4 XCHG3
|
||||||
|
32 PUSHINT // public_key stored_seqno param_value param_index cfg_dict _56=32
|
||||||
|
DICTISETREF // public_key stored_seqno cfg_dict
|
||||||
|
}>ELSE<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
s2 PUSH
|
||||||
|
1313042276 PUSHINT // cfg_dict stored_seqno action public_key cs action _58=1313042276
|
||||||
|
EQUAL // cfg_dict stored_seqno action public_key cs _59
|
||||||
|
IF:<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
s2 POP // cfg_dict stored_seqno cs public_key
|
||||||
|
SWAP // cfg_dict stored_seqno public_key cs
|
||||||
|
LDREF // cfg_dict stored_seqno public_key new_code cs
|
||||||
|
ENDS
|
||||||
|
SETCODE
|
||||||
|
}>ELSE<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
s2 PUSH
|
||||||
|
1348619041 PUSHINT // cfg_dict stored_seqno action public_key cs action _65=1348619041
|
||||||
|
EQUAL // cfg_dict stored_seqno action public_key cs _66
|
||||||
|
IF:<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
NIP
|
||||||
|
NIP // cfg_dict stored_seqno cs
|
||||||
|
256 LDU // cfg_dict stored_seqno public_key cs
|
||||||
|
ENDS
|
||||||
|
}>ELSE<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
s2 PUSH
|
||||||
|
1313074949 PUSHINT // cfg_dict stored_seqno action public_key cs action _71=1313074949
|
||||||
|
EQUAL // cfg_dict stored_seqno action public_key cs _72
|
||||||
|
IF:<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
s2 POP // cfg_dict stored_seqno cs public_key
|
||||||
|
SWAP // cfg_dict stored_seqno public_key cs
|
||||||
|
change_elector_code CALLDICT
|
||||||
|
}>ELSE<{ // cfg_dict stored_seqno action public_key cs
|
||||||
|
DROP // cfg_dict stored_seqno action public_key
|
||||||
|
SWAP // cfg_dict stored_seqno public_key action
|
||||||
|
32 THROWIF
|
||||||
|
}>
|
||||||
|
}>
|
||||||
|
}>
|
||||||
|
s0 s2 XCHG // public_key stored_seqno cfg_dict
|
||||||
|
}>
|
||||||
|
SWAP // public_key cfg_dict stored_seqno
|
||||||
|
INC // public_key cfg_dict _77
|
||||||
|
NEWC // public_key cfg_dict _77 _78
|
||||||
|
s1 s2 XCHG // public_key _77 cfg_dict _78
|
||||||
|
STREF // public_key _77 _79
|
||||||
|
32 STU // public_key _81
|
||||||
|
256 STU // _83
|
||||||
|
ENDC // _84
|
||||||
|
c4 POP
|
||||||
|
}>
|
||||||
|
run_ticktock PROC:<{
|
||||||
|
// is_tock
|
||||||
|
DROP //
|
||||||
|
c4 PUSH // _2
|
||||||
|
CTOS // cs
|
||||||
|
LDREF // cfg_dict cs
|
||||||
|
32 PUSHINT // cfg_dict cs kl=32
|
||||||
|
36 PUSHINT // cfg_dict cs kl=32 _10=36
|
||||||
|
s3 s1 PUSH2 // cfg_dict cs kl=32 _10=36 cfg_dict kl=32
|
||||||
|
DICTIGETOPTREF // cfg_dict cs kl=32 next_vset
|
||||||
|
DUP // cfg_dict cs kl=32 next_vset next_vset
|
||||||
|
ISNULL // cfg_dict cs kl=32 next_vset _12
|
||||||
|
IFNOT:<{ // cfg_dict cs kl=32 next_vset
|
||||||
|
DUP // cfg_dict cs kl=32 next_vset next_vset
|
||||||
|
CTOS // cfg_dict cs kl=32 next_vset ds
|
||||||
|
DUP // cfg_dict cs kl=32 next_vset ds ds
|
||||||
|
SBITS // cfg_dict cs kl=32 next_vset ds _15
|
||||||
|
39 GTINT // cfg_dict cs kl=32 next_vset ds _17
|
||||||
|
IF:<{ // cfg_dict cs kl=32 next_vset ds
|
||||||
|
8 LDU // cfg_dict cs kl=32 next_vset tag ds
|
||||||
|
32 PLDU // cfg_dict cs kl=32 next_vset tag since
|
||||||
|
SWAP // cfg_dict cs kl=32 next_vset since tag
|
||||||
|
17 EQINT // cfg_dict cs kl=32 next_vset since _26
|
||||||
|
NOW // cfg_dict cs kl=32 next_vset since _26 _27
|
||||||
|
s1 s2 XCHG // cfg_dict cs kl=32 next_vset _26 since _27
|
||||||
|
GEQ // cfg_dict cs kl=32 next_vset _26 _28
|
||||||
|
AND // cfg_dict cs kl=32 next_vset _29
|
||||||
|
IF:<{ // cfg_dict cs kl=32 next_vset
|
||||||
|
SWAP
|
||||||
|
34 PUSHINT
|
||||||
|
s0 s4 s4 XC2PU // kl=32 cs next_vset _32=34 cfg_dict kl=32
|
||||||
|
DICTISETGETOPTREF // kl=32 cs cfg_dict cur_vset
|
||||||
|
s3 s1 s0 PUXCPU // kl=32 cs cur_vset _35=32 cfg_dict kl=32
|
||||||
|
DICTISETGETOPTREF // kl=32 cs _51 _52
|
||||||
|
DROP // kl=32 cs cfg_dict
|
||||||
|
36 PUSHINT // kl=32 cs cfg_dict _38=36
|
||||||
|
s0 s1 s3 XCHG3 // cs _38=36 cfg_dict kl=32
|
||||||
|
DICTIDEL // cs _53 _54
|
||||||
|
DROP // cs cfg_dict
|
||||||
|
}>ELSE<{
|
||||||
|
s2 s3 XCHG
|
||||||
|
2DROP // cs cfg_dict
|
||||||
|
}>
|
||||||
|
}>ELSE<{
|
||||||
|
s3 s4 XCHG
|
||||||
|
3 BLKDROP // cs cfg_dict
|
||||||
|
}>
|
||||||
|
}>ELSE<{
|
||||||
|
s2 s3 XCHG
|
||||||
|
2DROP // cs cfg_dict
|
||||||
|
}>
|
||||||
|
NEWC // cs cfg_dict _40
|
||||||
|
STREF // cs _41
|
||||||
|
SWAP // _41 cs
|
||||||
|
STSLICER // _42
|
||||||
|
ENDC // _43
|
||||||
|
c4 POP
|
||||||
|
}>
|
||||||
|
}END>c
|
1
crypto/smartcont/auto/elector-code.cpp
Normal file
1
crypto/smartcont/auto/elector-code.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
with_tvm_code("elector-code", "te6ccgECVAEACrkAART/APSkE/Sg8sgLAQIBIAIDAgFIBAUAUaX//xh2omh6AnoCETdKrPgN+SBOKjgQ+At5ICz4DPkgcXgL+SB4DRhAAgLFBgcCASAKCwIBywgJACyqgjGCEE5Db2SCEM5Db2RwQzCAQPAGAgEgEBECASAzNAIDeqAMDQIBbg4PACSqB+1E0PQFIG6SMHCU0NcLH+IAQqss7UTQ9AUgbpJbcODwAxAmXwaDB/QOb6GT+gAwkjBw4gBzsKV7UTQ9AUgbpIwbeDwAxAmXwZthP+OHiKDB/R+b6FvoSCcAvoAMFIQbwJQA28Cklow4gGzEuYwMYAAzs+A7UTQ9AQx9AQwgwf0Dm+hk/oAMJIwcOKACASASEwIBICMkAgEgFBUCASAdHgIBIBYXAgEgGxwBASAYACE7UTQ9AT0BPQE+gDTH9P/0YAL8AdDTAwFxsJJfA+D6QDAhxwCUMQHwEOAB0x8hwACUWwHwEODTPyKCEE5zdEu6lTIQI/AL4DQhghBHZXQkupMT8BHgIYIQTkNvZLqOGVRSRPASloIQzkNvZJKEH+JwEDRDMIBA8AbgIYIQ7nZPS7oighDudk9vulIQsYrgMDMgGRoADDIQIwHwDwAkgx6wm4QfcBA0QzCAQPAG4V8DACkyBb0ABT0ABL0AAH6Assfy//J7VSAAITQ0x/TH/oA+gD0BNIA0gDRgAgEgHyACASAhIgArMgXyx8Vyx9QA/oCAfoC9ADKAMoAyYAAdIAP+DPQ0h/SH9If1wofgAEUcIAYyMsFUAfPFlj6AhXLahPLH8s/IcL/kssfkTHiyQH7AIAAbIIQ7m9FTHBDMIBA8AaACASAlJgIBIC0uAgEgJygCASApKgAjIIQ83RITIIQO5rKAEMwcvAGgAEcghBOVlNUcIIAxP/IyxAVy/+DHfoCFMtqE8sfEss/zMlx+wCAAMxTEoMH9A5voZT6ADCgkTDiyAH6AgKDB/RDgAQEgKwH+I/pE7UTQ9AQhbgSkFLGXEDVfBXDwB+AE0//TH9Mf0//UAdCDCNcZAdGCEGVMUHTIyx9SQMsfUjDLH1Jgy/9SIMv/ydBRFfkRlxBoXwhx8AfhIYMPuZcQaF8IdvAH4AfwAzEF/iANghA7msoAoSCqCyO5mBC8XwwxcvAH4FEioCwA/lF9vZcQrF8Mc/AH4ASXEJtfC3DwB+BTY4MH9A5voSCfMPoAWaAB0z8x0/8wUoC9kTHilxCbXwt08AfgUwG5lxCbXwt18AfgIPKs+AD4I8hY+gLLHxTLHxbL/xjL/0A3gwf0Q3AQVxA0ECMQJnDwBMj0AAHPFsntVCCTcPAI4FsCASAvMAIBIDEyAHkcCB/jjAkgwf0fG+hb6EgjhwC0//TPzH6ANIA0ZQxUTOgl1QYiPAKBwPiUEOgk1BCMOIBsxPmMDMBuvK7gAKEcFMAf447JoMH9HxvoW+hII4nAtP/0z8x+gDSANGUMVEzoI4RVHcIqYRRZqBSF6BLsPAKCQPiUFOgk1BSMOIBsxTmMDUDulMhu7DyuxKgAaGAAVwBgCD0Zm+hkjBw4dM/MdP/MfQE+gD6APQEMdEgwgCUEDTwDZUwECPwDOISgAKMMgL6RHD4M9DXC//tRND0BASkWr2xIW6xkl8E4PADBV8FUhW9BLMUsZJfA+D4AAGRW44d9AT0BPoAQzTwDnDIygAT9AD0AFmg+gIBzxbJ7VTigAgEgNTYCAUhOTwIBIDc4AgEgPT4CASA5OgIBIDs8AKU8AEH+kQBpLEhwACxlwWgVRMB8ALgUwKAIPQOb6GOJ9M/0//0BPoA+gALoMgVyz8Ty//0AAH6AgH6AlAGzxYBgCBURkT0Q5QwBaAB4hA1QUPwAoADZDEh+kQBpJ8wghD////+cBA0E4BA8Abg7UTQ9AT0BFAzgwf0Zm+hjhBfBIIQ/////nAQNBOAQPAG4TYF+gDRyBL0ABX0AAHPFsntVIIQ+W9zJHCAGMjLBVAEzxZQBPoCEstqEssfyz/JgED7AIABpHD4MyBuk18EcODQ1wv/I/pEAaQCvbGTXwNw4PgAAdQh+wQgxwCSXwSZAe1TAfEGgvIA4n+AAAxwgAgEgP0ACASBJSgA1HACjhMCbyIhbxACbxEkqKsPErYIEqBY5DAxgAQEgQQP+gBD4M9DTD9MPMdMP0XG2CXBtf45GKYMH9HxvoW+hII4wAvoA0x/TH9P/0//RA6PIFct/FMofUkDL/8nQURq2CMjLHxPL/8v/QBSBAaD0QQOklBA0WjDiAbNDMOYwNFi2CFMBuZZfB21tcCDgbYrmMzSlXJJvEeRwIIrmMjI0NEJDRABqA4EBoPSSb6FvoSCOIAHTf1EZtggB0x8x1wv/A9Mf0/8x1wv/QTAUbwRQBW8Ck0YWW+IEsxQASgJvIgFvEASkU0i+jhBUZQbwFFMCvJMyMiKSEzDik1A0MOJTNr4BXiLAAFJDuRKxll8EbW1wIOAg/iAipZJvEeRvEG8QcCBtbYrmMzMzNVIUuvKxECMBRQL+BW8iAW8kUxyDB/QOb6HyvfoAMdM/MdcL/1OLuY5XUTmoqw9SQLYIUUShJKo7LakEUYWgghCOgSeKI5KAc5KAU+LIywfLH1JAy/9SkMs/I5MTy/+TUAMw4gGAEFRKmfRDcCTIy/8Zyz9QBfoCF8oAQBmDB/RDlgoQRgNfA+IjikZHAAhLc/AKARiK4gOkKW4QShBGREBIAAZLc1sBASBLAa08AGAIvgz+QBTAbqTXwdw4CKOL1MkgCD0Dm+hjh/THzEg0x/T/zBQBLryufgjUAOgyMsfWM8WQASAIPRDlBUTXwPik0QUW+J/iuYgbpIwcJDiUAPwAn+BNAf4B8AM0+CMluZNfCHDgcPgzbpRfCPAT4IAR+DPQ+gD6APoA0x/RU2G5lF8M8BPgBJRfC/AT4AaTXwpw4BA4KFEyUHfwFSDAACCzKgYQWhBJEDhMzPAEIo4TMjIyMjLIEvQA9AABzxbJ7VTwE+HwBTL4IwGgpsQotgmAEPgz0IAQTADI1yHXCw9SYLYIUxOggBHIywdSMMsfyx8Xyw8Wyw8J0BnPFslw+DPQ1wv/UxjwCQn0BHAL+QBQY6ApoMjLHxnLH8v/FfQAUAP6AnD6AhbKAEA0gCD0Q8gT9AD0APQAAc8Wye1UfwCkIYAg9HxvoW+hII4/AtM/0/9TF7qOLTQD9AT6APoAKKsCUZmhUCmgyBXLPxbL/xL0AAH6AgH6AljPFgGAIFRBRPRDcJYQNRA0XwPik0MDMOKzEgIBIFBRAgEgUlMAGQhbpJbcJUB+QABuuKAAlQB8AMFXwWTXwNw4QL0BFExgCD0Dm+hk18EcOGAQNch1wv/gCL4MyHwGIAk+DNY8BixjhNwyMoAEvQA9AABzxbJ7VTwFzB/4F8DcIACTPABf44+JIAg9HxvoW+hII4kAtMfMPgju1MUvbCOETFUFUTwDhSgVHYTVHNY8AJwlEYVUETilhA3FkUFMOKzECYQRRTmBl8GbrOAA4QxgCT4M26SW3Dhcfgz0NcL//go+kQBpAK9sZJbcOCAIvgzIG6TXwNw4PAFMDIC0IAo1yHXCx/4I1EToVy5k18GcOBcocE8kTGRMOKAEfgz0PoAMAOg/iBSAqFwbXAQRRA0cPAEyPQA9AABzxbJ7VR/g");
|
1712
crypto/smartcont/auto/elector-code.fif
Normal file
1712
crypto/smartcont/auto/elector-code.fif
Normal file
File diff suppressed because it is too large
Load diff
1
crypto/smartcont/auto/highload-wallet-code.cpp
Normal file
1
crypto/smartcont/auto/highload-wallet-code.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
with_tvm_code("highload-wallet", "te6ccgEBBgEAhgABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQC88oMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj9ATR+AB/jhghgBD0eG+hb6EgmALTB9QwAfsAkTLiAbPmWwGkyMsfyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==");
|
79
crypto/smartcont/auto/highload-wallet-code.fif
Normal file
79
crypto/smartcont/auto/highload-wallet-code.fif
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-code.fc`
|
||||||
|
PROGRAM{
|
||||||
|
DECLPROC recv_internal
|
||||||
|
DECLPROC recv_external
|
||||||
|
85143 DECLMETHOD seqno
|
||||||
|
recv_internal PROC:<{
|
||||||
|
// in_msg
|
||||||
|
DROP //
|
||||||
|
}>
|
||||||
|
recv_external PROC:<{
|
||||||
|
// in_msg
|
||||||
|
9 PUSHPOW2 // in_msg _3=512
|
||||||
|
LDSLICEX // signature in_msg
|
||||||
|
DUP // signature in_msg cs
|
||||||
|
32 LDU // signature in_msg _9 cs
|
||||||
|
32 LDU // signature in_msg _9 _12 cs
|
||||||
|
32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
|
||||||
|
NOW // signature in_msg subwallet_id valid_until msg_seqno cs _19
|
||||||
|
s1 s3 XCHG // signature in_msg subwallet_id cs msg_seqno valid_until _19
|
||||||
|
LEQ // signature in_msg subwallet_id cs msg_seqno _20
|
||||||
|
35 THROWIF
|
||||||
|
c4 PUSH // signature in_msg subwallet_id cs msg_seqno _23
|
||||||
|
CTOS // signature in_msg subwallet_id cs msg_seqno ds
|
||||||
|
32 LDU // signature in_msg subwallet_id cs msg_seqno _28 ds
|
||||||
|
32 LDU // signature in_msg subwallet_id cs msg_seqno _28 _31 ds
|
||||||
|
256 LDU // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key ds
|
||||||
|
ENDS
|
||||||
|
s3 s2 XCPU // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet msg_seqno stored_seqno
|
||||||
|
EQUAL // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet _39
|
||||||
|
33 THROWIFNOT
|
||||||
|
s4 s4 XCPU // signature in_msg stored_subwallet cs public_key stored_seqno subwallet_id stored_subwallet
|
||||||
|
EQUAL // signature in_msg stored_subwallet cs public_key stored_seqno _42
|
||||||
|
34 THROWIFNOT
|
||||||
|
s0 s4 XCHG // signature stored_seqno stored_subwallet cs public_key in_msg
|
||||||
|
HASHSU // signature stored_seqno stored_subwallet cs public_key _45
|
||||||
|
s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs _45 signature public_key
|
||||||
|
CHKSIGNU // public_key stored_seqno stored_subwallet cs _46
|
||||||
|
35 THROWIFNOT
|
||||||
|
LDDICT // public_key stored_seqno stored_subwallet dict cs
|
||||||
|
ENDS
|
||||||
|
ACCEPT
|
||||||
|
-1 PUSHINT // public_key stored_seqno stored_subwallet dict i=-1
|
||||||
|
UNTIL:<{
|
||||||
|
OVER
|
||||||
|
16 PUSHINT // public_key stored_seqno stored_subwallet dict i dict _57=16
|
||||||
|
DICTIGETNEXT
|
||||||
|
NULLSWAPIFNOT
|
||||||
|
NULLSWAPIFNOT // public_key stored_seqno stored_subwallet dict cs i f
|
||||||
|
DUP // public_key stored_seqno stored_subwallet dict cs i f f
|
||||||
|
IF:<{ // public_key stored_seqno stored_subwallet dict cs i f
|
||||||
|
s0 s2 XCHG // public_key stored_seqno stored_subwallet dict f i cs
|
||||||
|
8 LDU // public_key stored_seqno stored_subwallet dict f i mode cs
|
||||||
|
LDREF // public_key stored_seqno stored_subwallet dict f i mode _100 _99
|
||||||
|
DROP // public_key stored_seqno stored_subwallet dict f i mode _63
|
||||||
|
SWAP // public_key stored_seqno stored_subwallet dict f i _63 mode
|
||||||
|
SENDRAWMSG
|
||||||
|
}>ELSE<{
|
||||||
|
s2 POP // public_key stored_seqno stored_subwallet dict f i
|
||||||
|
}>
|
||||||
|
SWAP // public_key stored_seqno stored_subwallet dict i f
|
||||||
|
NOT // public_key stored_seqno stored_subwallet dict i _66
|
||||||
|
}> // public_key stored_seqno stored_subwallet dict i
|
||||||
|
2DROP // public_key stored_seqno stored_subwallet
|
||||||
|
SWAP // public_key stored_subwallet stored_seqno
|
||||||
|
INC // public_key stored_subwallet _68
|
||||||
|
NEWC // public_key stored_subwallet _68 _69
|
||||||
|
32 STU // public_key stored_subwallet _71
|
||||||
|
32 STU // public_key _73
|
||||||
|
256 STU // _75
|
||||||
|
ENDC // _76
|
||||||
|
c4 POP
|
||||||
|
}>
|
||||||
|
seqno PROC:<{
|
||||||
|
//
|
||||||
|
c4 PUSH // _0
|
||||||
|
CTOS // _1
|
||||||
|
32 PLDU // _3
|
||||||
|
}>
|
||||||
|
}END>c
|
1
crypto/smartcont/auto/highload-wallet-v2-code.cpp
Normal file
1
crypto/smartcont/auto/highload-wallet-v2-code.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
with_tvm_code("highoad-wallet-v2", "te6ccgEBBwEA1wABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQHu8oMI1xgg0x/TP/gjqh9TILnyY+1E0NMf0z/T//QE0VNggED0Dm+hMfJgUXO68qIH+QFUEIf5EPKjAvQE0fgAf44YIYAQ9HhvoW+hIJgC0wfUMAH7AJEy4gGz5luDJaHIQDSAQPRDiuYxyBLLHxPLP8v/9ADJ7VQGAATQMABBoZfl2omhpj5jpn+n/mPoCaKkQQCB6BzfQmMktv8ld0fFADoggED0lm+hb6EyURCUMFMDud4gkjM2k0MTW+IBsw==");
|
134
crypto/smartcont/auto/highload-wallet-v2-code.fif
Normal file
134
crypto/smartcont/auto/highload-wallet-v2-code.fif
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
// automatically generated from `smartcont/stdlib.fc` `smartcont/highload-wallet-v2-code.fc`
|
||||||
|
PROGRAM{
|
||||||
|
DECLPROC recv_internal
|
||||||
|
DECLPROC recv_external
|
||||||
|
117746 DECLMETHOD processed?
|
||||||
|
recv_internal PROC:<{
|
||||||
|
// in_msg
|
||||||
|
DROP //
|
||||||
|
}>
|
||||||
|
recv_external PROC:<{
|
||||||
|
// in_msg
|
||||||
|
9 PUSHPOW2 // in_msg _3=512
|
||||||
|
LDSLICEX // signature in_msg
|
||||||
|
DUP // signature in_msg cs
|
||||||
|
32 LDU // signature in_msg _8 cs
|
||||||
|
64 LDU // signature in_msg subwallet_id query_id cs
|
||||||
|
NOW // signature in_msg subwallet_id query_id cs _15
|
||||||
|
32 LSHIFT# // signature in_msg subwallet_id query_id cs bound
|
||||||
|
s2 s0 PUSH2 // signature in_msg subwallet_id query_id cs bound query_id bound
|
||||||
|
LESS // signature in_msg subwallet_id query_id cs bound _19
|
||||||
|
35 THROWIF
|
||||||
|
c4 PUSH // signature in_msg subwallet_id query_id cs bound _22
|
||||||
|
CTOS // signature in_msg subwallet_id query_id cs bound ds
|
||||||
|
32 LDU // signature in_msg subwallet_id query_id cs bound _28 ds
|
||||||
|
64 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 ds
|
||||||
|
256 LDU // signature in_msg subwallet_id query_id cs bound _28 _31 _34 ds
|
||||||
|
LDDICT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries ds
|
||||||
|
ENDS
|
||||||
|
s6 s0 PUSH2
|
||||||
|
64 PUSHINT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries query_id old_queries _42=64
|
||||||
|
DICTUGET
|
||||||
|
NULLSWAPIFNOT // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries _115 _116
|
||||||
|
NIP // signature in_msg subwallet_id query_id cs bound stored_subwallet last_cleaned public_key old_queries found?
|
||||||
|
32 THROWIF
|
||||||
|
s7 s3 XCPU // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key subwallet_id stored_subwallet
|
||||||
|
EQUAL // signature in_msg old_queries query_id cs bound stored_subwallet last_cleaned public_key _47
|
||||||
|
34 THROWIFNOT
|
||||||
|
s0 s7 XCHG // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned in_msg
|
||||||
|
HASHSU // signature public_key old_queries query_id cs bound stored_subwallet last_cleaned _50
|
||||||
|
s0 s8 s7 XC2PU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _50 signature public_key
|
||||||
|
CHKSIGNU // last_cleaned public_key old_queries query_id cs bound stored_subwallet _51
|
||||||
|
35 THROWIFNOT
|
||||||
|
s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound cs
|
||||||
|
LDDICT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs
|
||||||
|
ENDS
|
||||||
|
ACCEPT
|
||||||
|
-1 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i=-1
|
||||||
|
UNTIL:<{
|
||||||
|
OVER
|
||||||
|
16 PUSHINT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i dict _62=16
|
||||||
|
DICTIGETNEXT
|
||||||
|
NULLSWAPIFNOT
|
||||||
|
NULLSWAPIFNOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f
|
||||||
|
DUP // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f f
|
||||||
|
IF:<{ // last_cleaned public_key old_queries query_id stored_subwallet bound dict cs i f
|
||||||
|
s0 s2 XCHG // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i cs
|
||||||
|
8 LDU // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode cs
|
||||||
|
LDREF // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _125 _124
|
||||||
|
DROP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i mode _68
|
||||||
|
SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i _68 mode
|
||||||
|
SENDRAWMSG
|
||||||
|
}>ELSE<{
|
||||||
|
s2 POP // last_cleaned public_key old_queries query_id stored_subwallet bound dict f i
|
||||||
|
}>
|
||||||
|
SWAP // last_cleaned public_key old_queries query_id stored_subwallet bound dict i f
|
||||||
|
NOT // last_cleaned public_key old_queries query_id stored_subwallet bound dict i _71
|
||||||
|
}> // last_cleaned public_key old_queries query_id stored_subwallet bound dict i
|
||||||
|
2DROP // last_cleaned public_key old_queries query_id stored_subwallet bound
|
||||||
|
38 PUSHPOW2 // last_cleaned public_key old_queries query_id stored_subwallet bound _74
|
||||||
|
SUB // last_cleaned public_key old_queries query_id stored_subwallet bound
|
||||||
|
NEWC // last_cleaned public_key old_queries query_id stored_subwallet bound _77
|
||||||
|
s0 s3 s4 XCHG3
|
||||||
|
64 PUSHINT // last_cleaned public_key stored_subwallet bound _77 query_id old_queries _78=64
|
||||||
|
DICTUSETB // last_cleaned public_key stored_subwallet bound old_queries
|
||||||
|
UNTIL:<{
|
||||||
|
DUP
|
||||||
|
64 PUSHINT // last_cleaned public_key stored_subwallet bound old_queries old_queries _85=64
|
||||||
|
DICTUREMMIN
|
||||||
|
NULLSWAPIFNOT
|
||||||
|
NULLSWAPIFNOT // last_cleaned public_key stored_subwallet bound old_queries _126 _128 _127 _129
|
||||||
|
s2 POP // last_cleaned public_key stored_subwallet bound old_queries old_queries' f i
|
||||||
|
s1 s0 XCPU // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f
|
||||||
|
IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||||
|
DROP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i
|
||||||
|
s0 s3 PUSH2 // last_cleaned public_key stored_subwallet bound old_queries old_queries' i i bound
|
||||||
|
LESS // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||||
|
}> // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||||
|
DUP // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f f
|
||||||
|
IF:<{ // last_cleaned public_key stored_subwallet bound old_queries old_queries' i f
|
||||||
|
s3 POP
|
||||||
|
s6 POP // last_cleaned public_key stored_subwallet bound f old_queries
|
||||||
|
}>ELSE<{
|
||||||
|
s3 s1 s3 XCHG3
|
||||||
|
2DROP // last_cleaned public_key stored_subwallet bound f old_queries
|
||||||
|
}>
|
||||||
|
SWAP // last_cleaned public_key stored_subwallet bound old_queries f
|
||||||
|
NOT // last_cleaned public_key stored_subwallet bound old_queries _90
|
||||||
|
}> // last_cleaned public_key stored_subwallet bound old_queries
|
||||||
|
NIP // last_cleaned public_key stored_subwallet old_queries
|
||||||
|
NEWC // last_cleaned public_key stored_subwallet old_queries _91
|
||||||
|
s1 s2 XCHG // last_cleaned public_key old_queries stored_subwallet _91
|
||||||
|
32 STU // last_cleaned public_key old_queries _93
|
||||||
|
s1 s3 XCHG // old_queries public_key last_cleaned _93
|
||||||
|
64 STU // old_queries public_key _95
|
||||||
|
256 STU // old_queries _97
|
||||||
|
STDICT // _98
|
||||||
|
ENDC // _99
|
||||||
|
c4 POP
|
||||||
|
}>
|
||||||
|
processed? PROC:<{
|
||||||
|
// query_id
|
||||||
|
c4 PUSH // query_id _2
|
||||||
|
CTOS // query_id ds
|
||||||
|
32 LDU // query_id _29 _28
|
||||||
|
NIP // query_id ds
|
||||||
|
64 LDU // query_id _11 ds
|
||||||
|
256 LDU // query_id _11 _33 _32
|
||||||
|
NIP // query_id _11 ds
|
||||||
|
LDDICT // query_id last_cleaned old_queries ds
|
||||||
|
ENDS
|
||||||
|
s2 s(-1) PUXC
|
||||||
|
64 PUSHINT // query_id last_cleaned query_id old_queries _22=64
|
||||||
|
DICTUGET
|
||||||
|
NULLSWAPIFNOT // query_id last_cleaned _36 _37
|
||||||
|
NIP // query_id last_cleaned found
|
||||||
|
IF:<{ // query_id last_cleaned
|
||||||
|
2DROP //
|
||||||
|
TRUE // _24
|
||||||
|
}>ELSE<{ // query_id last_cleaned
|
||||||
|
LEQ // _26
|
||||||
|
NEGATE // _24
|
||||||
|
}>
|
||||||
|
}>
|
||||||
|
}END>c
|
1
crypto/smartcont/auto/simple-wallet-code.cpp
Normal file
1
crypto/smartcont/auto/simple-wallet-code.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
with_tvm_code("simple-wallet", "te6ccgEBBAEATwABFP8A9KQT9KDyyAsBAgEgAgMABNIwAG7ygwjXGCDTH+1E0NMf0//RUTG68qED+QFUEEL5EPKi+ABRINdKltMH1AL7AN7RpMjLH8v/ye1U");
|
45
crypto/smartcont/auto/simple-wallet-code.fif
Normal file
45
crypto/smartcont/auto/simple-wallet-code.fif
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
// automatically generated from `smartcont/stdlib.fc` `smartcont/simple-wallet-code.fc`
|
||||||
|
PROGRAM{
|
||||||
|
DECLPROC recv_internal
|
||||||
|
DECLPROC recv_external
|
||||||
|
recv_internal PROC:<{
|
||||||
|
// in_msg
|
||||||
|
DROP //
|
||||||
|
}>
|
||||||
|
recv_external PROC:<{
|
||||||
|
// in_msg
|
||||||
|
9 PUSHPOW2 // in_msg _3=512
|
||||||
|
LDSLICEX // signature in_msg
|
||||||
|
DUP // signature in_msg cs
|
||||||
|
32 LDU // signature in_msg msg_seqno cs
|
||||||
|
c4 PUSH // signature in_msg msg_seqno cs _11
|
||||||
|
CTOS // signature in_msg msg_seqno cs cs2
|
||||||
|
32 LDU // signature in_msg msg_seqno cs stored_seqno cs2
|
||||||
|
256 LDU // signature in_msg msg_seqno cs stored_seqno public_key cs2
|
||||||
|
ENDS
|
||||||
|
s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno
|
||||||
|
EQUAL // signature in_msg public_key cs stored_seqno _23
|
||||||
|
33 THROWIFNOT
|
||||||
|
s0 s3 XCHG // signature stored_seqno public_key cs in_msg
|
||||||
|
HASHSU // signature stored_seqno public_key cs _26
|
||||||
|
s0 s4 s2 XC2PU // cs stored_seqno public_key _26 signature public_key
|
||||||
|
CHKSIGNU // cs stored_seqno public_key _27
|
||||||
|
34 THROWIFNOT
|
||||||
|
ACCEPT
|
||||||
|
s2 s0 XCPU // public_key stored_seqno cs cs
|
||||||
|
SREFS // public_key stored_seqno cs _32
|
||||||
|
IF:<{ // public_key stored_seqno cs
|
||||||
|
8 LDU // public_key stored_seqno mode cs
|
||||||
|
LDREF // public_key stored_seqno mode _37 cs
|
||||||
|
s0 s2 XCHG // public_key stored_seqno cs _37 mode
|
||||||
|
SENDRAWMSG
|
||||||
|
}> // public_key stored_seqno cs
|
||||||
|
ENDS
|
||||||
|
INC // public_key _42
|
||||||
|
NEWC // public_key _42 _43
|
||||||
|
32 STU // public_key _45
|
||||||
|
256 STU // _47
|
||||||
|
ENDC // _48
|
||||||
|
c4 POP
|
||||||
|
}>
|
||||||
|
}END>c
|
1
crypto/smartcont/auto/wallet-code.cpp
Normal file
1
crypto/smartcont/auto/wallet-code.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
with_tvm_code("wallet", "te6ccgEBBgEAaAABFP8A9KQT9KDyyAsBAgEgAgMCAUgEBQCA8oMI1xgg0x/TH/gjErvyY+1E0NMf0//RUTG68qED+QFUEEL5EPKi+AACkyDXSpbTB9QC+wDo0aTIyx/L/8ntVAAE0DAAEaCZL9qJoa4WPw==");
|
59
crypto/smartcont/auto/wallet-code.fif
Normal file
59
crypto/smartcont/auto/wallet-code.fif
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// automatically generated from `smartcont/stdlib.fc` `smartcont/wallet-code.fc`
|
||||||
|
PROGRAM{
|
||||||
|
DECLPROC recv_internal
|
||||||
|
DECLPROC recv_external
|
||||||
|
85143 DECLMETHOD seqno
|
||||||
|
recv_internal PROC:<{
|
||||||
|
// in_msg
|
||||||
|
DROP //
|
||||||
|
}>
|
||||||
|
recv_external PROC:<{
|
||||||
|
// in_msg
|
||||||
|
9 PUSHPOW2 // in_msg _3=512
|
||||||
|
LDSLICEX // signature in_msg
|
||||||
|
DUP // signature in_msg cs
|
||||||
|
32 LDU // signature in_msg _8 cs
|
||||||
|
32 LDU // signature in_msg msg_seqno valid_until cs
|
||||||
|
NOW // signature in_msg msg_seqno valid_until cs _15
|
||||||
|
s1 s2 XCHG // signature in_msg msg_seqno cs valid_until _15
|
||||||
|
LEQ // signature in_msg msg_seqno cs _16
|
||||||
|
35 THROWIF
|
||||||
|
c4 PUSH // signature in_msg msg_seqno cs _19
|
||||||
|
CTOS // signature in_msg msg_seqno cs ds
|
||||||
|
32 LDU // signature in_msg msg_seqno cs _23 ds
|
||||||
|
256 LDU // signature in_msg msg_seqno cs stored_seqno public_key ds
|
||||||
|
ENDS
|
||||||
|
s3 s1 XCPU // signature in_msg public_key cs stored_seqno msg_seqno stored_seqno
|
||||||
|
EQUAL // signature in_msg public_key cs stored_seqno _31
|
||||||
|
33 THROWIFNOT
|
||||||
|
s0 s3 XCHG // signature stored_seqno public_key cs in_msg
|
||||||
|
HASHSU // signature stored_seqno public_key cs _34
|
||||||
|
s0 s4 s2 XC2PU // cs stored_seqno public_key _34 signature public_key
|
||||||
|
CHKSIGNU // cs stored_seqno public_key _35
|
||||||
|
34 THROWIFNOT
|
||||||
|
ACCEPT
|
||||||
|
s0 s2 XCHG // public_key stored_seqno cs
|
||||||
|
WHILE:<{
|
||||||
|
DUP // public_key stored_seqno cs cs
|
||||||
|
SREFS // public_key stored_seqno cs _40
|
||||||
|
}>DO<{ // public_key stored_seqno cs
|
||||||
|
8 LDU // public_key stored_seqno mode cs
|
||||||
|
LDREF // public_key stored_seqno mode _45 cs
|
||||||
|
s0 s2 XCHG // public_key stored_seqno cs _45 mode
|
||||||
|
SENDRAWMSG
|
||||||
|
}> // public_key stored_seqno cs
|
||||||
|
ENDS
|
||||||
|
INC // public_key _50
|
||||||
|
NEWC // public_key _50 _51
|
||||||
|
32 STU // public_key _53
|
||||||
|
256 STU // _55
|
||||||
|
ENDC // _56
|
||||||
|
c4 POP
|
||||||
|
}>
|
||||||
|
seqno PROC:<{
|
||||||
|
//
|
||||||
|
c4 PUSH // _0
|
||||||
|
CTOS // _1
|
||||||
|
32 PLDU // _3
|
||||||
|
}>
|
||||||
|
}END>c
|
|
@ -121,7 +121,7 @@ dup make_special dup constant smc3_addr
|
||||||
."address = " x. cr
|
."address = " x. cr
|
||||||
|
|
||||||
// SmartContract #4 (elector)
|
// SmartContract #4 (elector)
|
||||||
"elector-code.fif" include // code in separate source file
|
"auto/elector-code.fif" include // code in separate source file
|
||||||
<b 0 1 1+ 1+ 5 + u, 0 256 u, b> // data
|
<b 0 1 1+ 1+ 5 + u, 0 256 u, b> // data
|
||||||
GR$10 // balance: 10 grams
|
GR$10 // balance: 10 grams
|
||||||
0 // split_depth
|
0 // split_depth
|
||||||
|
|
|
@ -133,7 +133,7 @@ dup make_special dup constant smc3_addr
|
||||||
* SmartContract #4 (elector)
|
* SmartContract #4 (elector)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
"elector-code.fif" include // code in separate source file
|
"auto/elector-code.fif" include // code in separate source file
|
||||||
<b 0 1 1+ 1+ 4 + 32 + u, 0 256 u, b> // data: dict dict dict grams uint32 uint256
|
<b 0 1 1+ 1+ 4 + 32 + u, 0 256 u, b> // data: dict dict dict grams uint32 uint256
|
||||||
empty_cell // libraries
|
empty_cell // libraries
|
||||||
GR$10 // balance: 10 grams
|
GR$10 // balance: 10 grams
|
||||||
|
@ -202,8 +202,7 @@ smc1_addr config.minter_smc!
|
||||||
// 17 add-validator
|
// 17 add-validator
|
||||||
// newkeypair nip dup ."Validator #2 public key = " Bx. cr
|
// newkeypair nip dup ."Validator #2 public key = " Bx. cr
|
||||||
// 239 add-validator
|
// 239 add-validator
|
||||||
// 100000 =: orig_vset_valid_for
|
100000 =: orig_vset_valid_for // original validator set valid 100000 seconds
|
||||||
100 =: orig_vset_valid_for // original validator set valid 100 seconds only (DEBUG)
|
|
||||||
now dup orig_vset_valid_for + 0 config.validators!
|
now dup orig_vset_valid_for + 0 config.validators!
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -211,7 +210,7 @@ now dup orig_vset_valid_for + 0 config.validators!
|
||||||
* SmartContract #5 (Configuration smart contract)
|
* SmartContract #5 (Configuration smart contract)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
"config-code.fif" include // code in separate source file
|
"auto/config-code.fif" include // code in separate source file
|
||||||
<b 0 32 u,
|
<b 0 32 u,
|
||||||
"config-master" +suffix +".pk" load-generate-keypair drop
|
"config-master" +suffix +".pk" load-generate-keypair drop
|
||||||
B,
|
B,
|
||||||
|
|
|
@ -19,8 +19,8 @@ def? $3 { @' $3 } { "new-wallet" } cond constant file-base
|
||||||
."Creating new v2 high-load wallet in workchain " wc .
|
."Creating new v2 high-load wallet in workchain " wc .
|
||||||
."with subwallet id " subwallet-id . cr
|
."with subwallet id " subwallet-id . cr
|
||||||
|
|
||||||
// Create new high-load wallet; source code included from `highload-wallet-v2-code.fif`
|
// Create new high-load wallet; source code included from `auto/highload-wallet-v2-code.fif`
|
||||||
"highload-wallet-v2-code.fif" include
|
"auto/highload-wallet-v2-code.fif" include
|
||||||
// code
|
// code
|
||||||
<b subwallet-id 32 i, 0 64 u,
|
<b subwallet-id 32 i, 0 64 u,
|
||||||
file-base +".pk" load-generate-keypair
|
file-base +".pk" load-generate-keypair
|
||||||
|
|
|
@ -18,8 +18,8 @@ def? $3 { @' $3 } { "new-wallet" } cond constant file-base
|
||||||
."Creating new high-load wallet in workchain " wc .
|
."Creating new high-load wallet in workchain " wc .
|
||||||
."with subwallet id " subwallet-id . cr
|
."with subwallet id " subwallet-id . cr
|
||||||
|
|
||||||
// Create new high-load wallet; source code included from `highload-wallet-code.fif`
|
// Create new high-load wallet; source code included from `auto/highload-wallet-code.fif`
|
||||||
"highload-wallet-code.fif" include
|
"auto/highload-wallet-code.fif" include
|
||||||
// code
|
// code
|
||||||
<b 0 32 u, subwallet-id 32 i,
|
<b 0 32 u, subwallet-id 32 i,
|
||||||
file-base +".pk" load-generate-keypair
|
file-base +".pk" load-generate-keypair
|
||||||
|
|
33
crypto/smartcont/new-restricted-wallet.fif
Normal file
33
crypto/smartcont/new-restricted-wallet.fif
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/fift -s
|
||||||
|
"TonUtil.fif" include
|
||||||
|
"Asm.fif" include
|
||||||
|
|
||||||
|
{ ."usage: " @' $0 type ." <public-key> [<savefile>]" cr
|
||||||
|
."Creates a restricted wallet in the masterchain controlled by the private key corresponding to the specified public key" cr
|
||||||
|
."and saves its address into <savefile>.addr ('rwallet.addr' by default)" cr 1 halt
|
||||||
|
} : usage
|
||||||
|
$# 1- -2 and ' usage if
|
||||||
|
|
||||||
|
-1 =: wc
|
||||||
|
$1 parse-pubkey =: PubKey
|
||||||
|
def? $2 { @' $2 } { "rwallet" } cond constant file-base
|
||||||
|
|
||||||
|
."Creating new restricted wallet in workchain " wc . ."controlled by public key " PubKey .pubkey cr
|
||||||
|
|
||||||
|
// Create new restricted wallet; code taken from `auto/restricted-wallet-code.fif`
|
||||||
|
"auto/restricted-wallet-code.fif" include // code
|
||||||
|
<b 0 32 u, PubKey 256 u, b> // data
|
||||||
|
null // no libraries
|
||||||
|
<b b{0011} s, 3 roll ref, rot ref, swap dict, b> // create StateInit
|
||||||
|
dup ."StateInit: " <s csr. cr
|
||||||
|
dup hashu wc swap 2dup 2constant wallet_addr
|
||||||
|
."new wallet address = " 2dup .addr cr
|
||||||
|
2dup file-base +".addr" save-address-verbose
|
||||||
|
."Non-bounceable address (for init): " 2dup 7 .Addr cr
|
||||||
|
."Bounceable address (for later access): " 6 .Addr cr
|
||||||
|
<b b{1000100} s, wallet_addr addr, b{000010} s, swap
|
||||||
|
<s s, b{0} s, 0 256 u, 0 256 u, 0 32 u, -1 32 i, b>
|
||||||
|
dup ."External message for initialization is " <s csr. cr
|
||||||
|
2 boc+>B dup Bx. cr
|
||||||
|
file-base +"-query.boc" tuck B>file
|
||||||
|
."(Saved wallet creating query to file " type .")" cr
|
47
crypto/smartcont/new-restricted-wallet2.fif
Normal file
47
crypto/smartcont/new-restricted-wallet2.fif
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/fift -s
|
||||||
|
"TonUtil.fif" include
|
||||||
|
"Asm.fif" include
|
||||||
|
|
||||||
|
{ ."usage: " @' $0 type ." <public-key> <amount> [<savefile>]" cr
|
||||||
|
."Creates a restricted lockup wallet in the masterchain controlled by the private key corresponding to the specified public key" cr
|
||||||
|
."and saves its address into <savefile>.addr ('rwallet.addr' by default)" cr 1 halt
|
||||||
|
} : usage
|
||||||
|
$# 2- -2 and ' usage if
|
||||||
|
|
||||||
|
-1 =: wc
|
||||||
|
$1 parse-pubkey =: PubKey
|
||||||
|
$2 $>GR =: amount
|
||||||
|
def? $3 { @' $3 } { "rwallet" } cond constant file-base
|
||||||
|
|
||||||
|
."Creating new restricted lockup wallet in workchain " wc . ."controlled by public key " PubKey .pubkey
|
||||||
|
." with nominal amount " amount .GR cr
|
||||||
|
|
||||||
|
// D x t -- D'
|
||||||
|
{ <b rot Gram, swap rot 16 b>idict! not abort"cannot add value"
|
||||||
|
} : rdict-entry
|
||||||
|
// balance -- dict
|
||||||
|
{ dictnew
|
||||||
|
over -32768 rdict-entry
|
||||||
|
over 3/4 */ 92 rdict-entry
|
||||||
|
over 1/2 */ 183 rdict-entry
|
||||||
|
swap 1/4 */ 366 rdict-entry
|
||||||
|
0 548 rdict-entry
|
||||||
|
} : make-rdict
|
||||||
|
|
||||||
|
// Create new restricted wallet; code taken from `auto/restricted-wallet2-code.fif`
|
||||||
|
"auto/restricted-wallet-code.fif" include // code
|
||||||
|
<b 0 32 u, PubKey 256 u, amount make-rdict dict, b> // data
|
||||||
|
null // no libraries
|
||||||
|
<b b{0011} s, 3 roll ref, rot ref, swap dict, b> // create StateInit
|
||||||
|
dup ."StateInit: " <s csr. cr
|
||||||
|
dup hashu wc swap 2dup 2constant wallet_addr
|
||||||
|
."new wallet address = " 2dup .addr cr
|
||||||
|
2dup file-base +".addr" save-address-verbose
|
||||||
|
."Non-bounceable address (for init): " 2dup 7 .Addr cr
|
||||||
|
."Bounceable address (for later access): " 6 .Addr cr
|
||||||
|
<b b{1000100} s, wallet_addr addr, b{000010} s, swap
|
||||||
|
<s s, b{0} s, 0 256 u, 0 256 u, 0 32 u, -1 32 i, b>
|
||||||
|
dup ."External message for initialization is " <s csr. cr
|
||||||
|
2 boc+>B dup Bx. cr
|
||||||
|
file-base +"-query.boc" tuck B>file
|
||||||
|
."(Saved wallet creating query to file " type .")" cr
|
|
@ -13,7 +13,7 @@ def? $2 { @' $2 } { "new-wallet" } cond constant file-base
|
||||||
|
|
||||||
."Creating new advanced wallet in workchain " wc . cr
|
."Creating new advanced wallet in workchain " wc . cr
|
||||||
|
|
||||||
// Create new advanced wallet; code adapted from `wallet-code.fif`
|
// Create new advanced wallet; code adapted from `auto/wallet-code.fif`
|
||||||
<{ SETCP0 DUP IFNOTRET // return if recv_internal
|
<{ SETCP0 DUP IFNOTRET // return if recv_internal
|
||||||
DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method
|
DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method
|
||||||
DROP c4 PUSHCTR CTOS 32 PLDU // cnt
|
DROP c4 PUSHCTR CTOS 32 PLDU // cnt
|
||||||
|
|
67
crypto/smartcont/restricted-wallet-code.fc
Normal file
67
crypto/smartcont/restricted-wallet-code.fc
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
;; Restricted wallet (a variant of wallet-code.fc)
|
||||||
|
;; until configuration parameter -13 is set, accepts messages only to elector smc
|
||||||
|
|
||||||
|
() recv_internal(slice in_msg) impure {
|
||||||
|
;; do nothing for internal messages
|
||||||
|
}
|
||||||
|
|
||||||
|
_ restricted?() inline {
|
||||||
|
var p = config_param(-13);
|
||||||
|
return null?(p) ? true : begin_parse(p).preload_uint(32) > now();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ check_destination(msg, dest) inline_ref {
|
||||||
|
var cs = msg.begin_parse();
|
||||||
|
var flags = cs~load_uint(4);
|
||||||
|
if (flags & 8) {
|
||||||
|
;; external messages are always valid
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var (s_addr, d_addr) = (cs~load_msg_addr(), cs~load_msg_addr());
|
||||||
|
var (dest_wc, dest_addr) = parse_std_addr(d_addr);
|
||||||
|
return (dest_wc == -1) & (dest_addr == dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
() recv_external(slice in_msg) impure {
|
||||||
|
var signature = in_msg~load_bits(512);
|
||||||
|
var cs = in_msg;
|
||||||
|
var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32));
|
||||||
|
throw_if(35, valid_until <= now());
|
||||||
|
var ds = get_data().begin_parse();
|
||||||
|
var (stored_seqno, public_key) = (ds~load_uint(32), ds~load_uint(256));
|
||||||
|
ds.end_parse();
|
||||||
|
throw_unless(33, msg_seqno == stored_seqno);
|
||||||
|
ifnot (msg_seqno) {
|
||||||
|
accept_message();
|
||||||
|
set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell());
|
||||||
|
return ();
|
||||||
|
}
|
||||||
|
throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key));
|
||||||
|
accept_message();
|
||||||
|
var restrict = restricted?();
|
||||||
|
var elector = config_param(1).begin_parse().preload_uint(256);
|
||||||
|
cs~touch();
|
||||||
|
while (cs.slice_refs()) {
|
||||||
|
var mode = cs~load_uint(8);
|
||||||
|
var msg = cs~load_ref();
|
||||||
|
var ok = true;
|
||||||
|
if (restrict) {
|
||||||
|
ok = check_destination(msg, elector);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
send_raw_message(msg, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cs.end_parse();
|
||||||
|
set_data(begin_cell().store_uint(stored_seqno + 1, 32).store_uint(public_key, 256).end_cell());
|
||||||
|
}
|
||||||
|
|
||||||
|
;; Get methods
|
||||||
|
|
||||||
|
int seqno() method_id {
|
||||||
|
return get_data().begin_parse().preload_uint(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
int balance() method_id {
|
||||||
|
return restricted?() ? 0 : get_balance().first();
|
||||||
|
}
|
69
crypto/smartcont/restricted-wallet2-code.fc
Normal file
69
crypto/smartcont/restricted-wallet2-code.fc
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
;; Restricted wallet (a variant of wallet-code.fc)
|
||||||
|
;; until configuration parameter -13 is set, accepts messages only to elector smc
|
||||||
|
|
||||||
|
() recv_internal(slice in_msg) impure {
|
||||||
|
;; do nothing for internal messages
|
||||||
|
}
|
||||||
|
|
||||||
|
_ days_passed() inline {
|
||||||
|
var p = config_param(-13);
|
||||||
|
return null?(p) ? -1 : (now() - begin_parse(p).preload_uint(32)) / 86400;
|
||||||
|
}
|
||||||
|
|
||||||
|
() recv_external(slice in_msg) impure {
|
||||||
|
var signature = in_msg~load_bits(512);
|
||||||
|
var cs = in_msg;
|
||||||
|
var (msg_seqno, valid_until) = (cs~load_uint(32), cs~load_uint(32));
|
||||||
|
throw_if(35, valid_until <= now());
|
||||||
|
var ds = get_data().begin_parse();
|
||||||
|
var (stored_seqno, public_key, rdict) = (ds~load_uint(32), ds~load_uint(256), ds~load_dict());
|
||||||
|
ds.end_parse();
|
||||||
|
throw_unless(33, msg_seqno == stored_seqno);
|
||||||
|
ifnot (msg_seqno) {
|
||||||
|
accept_message();
|
||||||
|
set_data(begin_cell()
|
||||||
|
.store_uint(stored_seqno + 1, 32)
|
||||||
|
.store_uint(public_key, 256)
|
||||||
|
.store_dict(rdict)
|
||||||
|
.end_cell());
|
||||||
|
return ();
|
||||||
|
}
|
||||||
|
throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key));
|
||||||
|
accept_message();
|
||||||
|
var ts = days_passed();
|
||||||
|
var (_, value, found) = rdict.idict_get_preveq?(16, ts);
|
||||||
|
if (found) {
|
||||||
|
raw_reserve(value~load_grams(), 2);
|
||||||
|
}
|
||||||
|
cs~touch();
|
||||||
|
while (cs.slice_refs()) {
|
||||||
|
var mode = cs~load_uint(8);
|
||||||
|
var msg = cs~load_ref();
|
||||||
|
send_raw_message(msg, mode);
|
||||||
|
}
|
||||||
|
cs.end_parse();
|
||||||
|
set_data(begin_cell()
|
||||||
|
.store_uint(stored_seqno + 1, 32)
|
||||||
|
.store_uint(public_key, 256)
|
||||||
|
.store_dict(rdict)
|
||||||
|
.end_cell());
|
||||||
|
}
|
||||||
|
|
||||||
|
;; Get methods
|
||||||
|
|
||||||
|
int seqno() method_id {
|
||||||
|
return get_data().begin_parse().preload_uint(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
int balance() method_id {
|
||||||
|
var ds = get_data().begin_parse().skip_bits(32 + 256);
|
||||||
|
var rdict = ds~load_dict();
|
||||||
|
ds.end_parse();
|
||||||
|
var ts = days_passed();
|
||||||
|
var balance = get_balance().first();
|
||||||
|
var (_, value, found) = rdict.idict_get_preveq?(16, ts);
|
||||||
|
if (found) {
|
||||||
|
balance = max(balance - value~load_grams(), 0);
|
||||||
|
}
|
||||||
|
return balance;
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
int now() asm "NOW";
|
int now() asm "NOW";
|
||||||
slice my_address() asm "MYADDR";
|
slice my_address() asm "MYADDR";
|
||||||
|
tuple get_balance() asm "BALANCE";
|
||||||
|
|
||||||
int cell_hash(cell c) asm "HASHCU";
|
int cell_hash(cell c) asm "HASHCU";
|
||||||
int slice_hash(slice s) asm "HASHSU";
|
int slice_hash(slice s) asm "HASHSU";
|
||||||
|
@ -100,9 +101,13 @@ cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(va
|
||||||
(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
|
(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
|
(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
|
(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
|
(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT" "NULLSWAPIFNOT";
|
||||||
cell new_dict() asm "NEWDICT";
|
cell new_dict() asm "NEWDICT";
|
||||||
int dict_empty?(cell c) asm "DICTEMPTY";
|
int dict_empty?(cell c) asm "DICTEMPTY";
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"TonUtil.fif" include
|
"TonUtil.fif" include
|
||||||
|
|
||||||
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr
|
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr
|
||||||
."Creates a request to simple configuration smart contract requesting to change configuration smart contract code to the one currently stored in config-code.fif, "
|
."Creates a request to simple configuration smart contract requesting to change configuration smart contract code to the one currently stored in auto/config-code.fif, "
|
||||||
."with private key loaded from file <filename-base>.pk, "
|
."with private key loaded from file <filename-base>.pk, "
|
||||||
."and saves it into <savefile>.boc ('config-query.boc' by default)" cr 1 halt
|
."and saves it into <savefile>.boc ('config-query.boc' by default)" cr 1 halt
|
||||||
} : usage
|
} : usage
|
||||||
|
@ -12,7 +12,7 @@ $# dup 2 < swap 3 > or ' usage if
|
||||||
0 constant seqno
|
0 constant seqno
|
||||||
-1 constant idx
|
-1 constant idx
|
||||||
true constant bounce
|
true constant bounce
|
||||||
"config-code.fif" constant config-source
|
"auto/config-code.fif" constant config-source
|
||||||
100 constant interval // valid for 100 seconds
|
100 constant interval // valid for 100 seconds
|
||||||
|
|
||||||
$1 =: file-base
|
$1 =: file-base
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"TonUtil.fif" include
|
"TonUtil.fif" include
|
||||||
|
|
||||||
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr
|
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr
|
||||||
."Creates a request to simple configuration smart contract requesting to change elector smart contract code to the one currently stored in elector-code.fif, "
|
."Creates a request to simple configuration smart contract requesting to change elector smart contract code to the one currently stored in auto/elector-code.fif, "
|
||||||
."with private key loaded from file <filename-base>.pk, "
|
."with private key loaded from file <filename-base>.pk, "
|
||||||
."and saves it into <savefile>.boc ('config-query.boc' by default)" cr 1 halt
|
."and saves it into <savefile>.boc ('config-query.boc' by default)" cr 1 halt
|
||||||
} : usage
|
} : usage
|
||||||
|
@ -12,7 +12,7 @@ $# dup 2 < swap 3 > or ' usage if
|
||||||
0 constant seqno
|
0 constant seqno
|
||||||
-1 constant idx
|
-1 constant idx
|
||||||
true constant bounce
|
true constant bounce
|
||||||
"elector-code.fif" constant elector-source
|
"auto/elector-code.fif" constant elector-source
|
||||||
100 constant interval // valid for 100 seconds
|
100 constant interval // valid for 100 seconds
|
||||||
|
|
||||||
$1 =: file-base
|
$1 =: file-base
|
||||||
|
|
12
doc/tvm.tex
12
doc/tvm.tex
|
@ -2173,11 +2173,13 @@ The pseudo-random number generator uses the random seed and (sometimes) other da
|
||||||
The following primitives read configuration data provided in the {\em Tuple\/} stored in the first component of the {\em Tuple\/} at {\tt c7}. Whenever TVM is invoked for executing TON Blockchain smart contracts, this {\em Tuple\/} is initialized by a {\em SmartContractInfo\/} structure; configuration primitives assume that it has remained intact.
|
The following primitives read configuration data provided in the {\em Tuple\/} stored in the first component of the {\em Tuple\/} at {\tt c7}. Whenever TVM is invoked for executing TON Blockchain smart contracts, this {\em Tuple\/} is initialized by a {\em SmartContractInfo\/} structure; configuration primitives assume that it has remained intact.
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item {\tt F82$i$} --- {\tt GETPARAM $i$} ( -- $x$), returns the $i$-th parameter from the {\em Tuple\/} provided at {\tt c7} for $0\leq i<16$. Equivalent to {\tt PUSH c7}; {\tt FIRST}; {\tt INDEX $i$}. If one of these internal operations fails, throws an appropriate type checking or range checking exception.
|
\item {\tt F82$i$} --- {\tt GETPARAM $i$} ( -- $x$), returns the $i$-th parameter from the {\em Tuple\/} provided at {\tt c7} for $0\leq i<16$. Equivalent to {\tt PUSH c7}; {\tt FIRST}; {\tt INDEX $i$}. If one of these internal operations fails, throws an appropriate type checking or range checking exception.
|
||||||
\item {\tt F823} --- {\tt NOW} ( -- $x$), returns the current Unix time as an {\em Integer}. If it is impossible to recover the requested value starting from {\tt c7}, throws a type checking or range checking exception as appropriate. Equivalent to {\tt PUSH c7}; {\tt FIRST}; {\tt INDEX 3}.
|
\item {\tt F823} --- {\tt NOW} ( -- $x$), returns the current Unix time as an {\em Integer}. If it is impossible to recover the requested value starting from {\tt c7}, throws a type checking or range checking exception as appropriate. Equivalent to {\tt GETPARAM 3}.
|
||||||
\item {\tt F824} --- {\tt BLOCKLT} ( -- $x$), returns the starting logical time of the current block. Equivalent to {\tt PUSH c7}; {\tt FIRST}; {\tt INDEX 4}.
|
\item {\tt F824} --- {\tt BLOCKLT} ( -- $x$), returns the starting logical time of the current block. Equivalent to {\tt GETPARAM 4}.
|
||||||
\item {\tt F825} --- {\tt LTIME} ( -- $x$), returns the logical time of the current transaction. Equivalent to {\tt PUSH c7}; {\tt FIRST}; {\tt INDEX 5}.
|
\item {\tt F825} --- {\tt LTIME} ( -- $x$), returns the logical time of the current transaction. Equivalent to {\tt GETPARAM 5}.
|
||||||
\item {\tt F828} --- {\tt MYADDR} ( -- $s$), returns the internal address of the current smart contract as a {\em Slice\/} with a {\tt MsgAddressInt}. If necessary, it can be parsed further using primitives such as {\tt PARSESTDADDR} or {\tt REWRITESTDADDR}. Equivalent to {\tt PUSH c7}; {\tt FIRST}; {\tt INDEX 8}.
|
\item {\tt F826} --- {\tt BALANCE} ( -- $t$), returns the remaining balance of the smart contract as a {\em Tuple\/} consisting of an {\em Integer} (the remaining Gram balance in nanograms) and a {\em Maybe Cell} (a dictionary with 32-bit keys representing the balance of ``extra currencies''). Equivalent to {\tt GETPARAM 6}. Note that {\tt RAW} primitives such as {\tt SENDRAWMSG} do not update this field.
|
||||||
\item {\tt F829} --- {\tt CONFIGROOT} ( -- $D$), returns the {\em Maybe Cell\/}~$D$ with the current global configuration dictionary. Equivalent to {\tt PUSH c7}; {\tt FIRST}; {\tt INDEX 9}.
|
\item {\tt F827} --- {\tt RANDSEED} ( -- $x$), returns the current random seed as an unsigned 256-bit {\em Integer}. Equivalent to {\tt GETPARAM 7}.
|
||||||
|
\item {\tt F828} --- {\tt MYADDR} ( -- $s$), returns the internal address of the current smart contract as a {\em Slice\/} with a {\tt MsgAddressInt}. If necessary, it can be parsed further using primitives such as {\tt PARSESTDADDR} or {\tt REWRITESTDADDR}. Equivalent to {\tt GETPARAM 8}.
|
||||||
|
\item {\tt F829} --- {\tt CONFIGROOT} ( -- $D$), returns the {\em Maybe Cell\/}~$D$ with the current global configuration dictionary. Equivalent to {\tt GETPARAM 9}.
|
||||||
\item {\tt F830} --- {\tt CONFIGDICT} ( -- $D$ $32$), returns the global configuration dictionary along with its key length (32). Equivalent to {\tt CONFIGROOT}; {\tt PUSHINT 32}.
|
\item {\tt F830} --- {\tt CONFIGDICT} ( -- $D$ $32$), returns the global configuration dictionary along with its key length (32). Equivalent to {\tt CONFIGROOT}; {\tt PUSHINT 32}.
|
||||||
\item {\tt F832} --- {\tt CONFIGPARAM} ($i$ -- $c$ $-1$ or $0$), returns the value of the global configuration parameter with integer index $i$ as a {\em Cell\/}~$c$, and a flag to indicate success. Equivalent to {\tt CONFIGDICT}; {\tt DICTIGETREF}.
|
\item {\tt F832} --- {\tt CONFIGPARAM} ($i$ -- $c$ $-1$ or $0$), returns the value of the global configuration parameter with integer index $i$ as a {\em Cell\/}~$c$, and a flag to indicate success. Equivalent to {\tt CONFIGDICT}; {\tt DICTIGETREF}.
|
||||||
\item {\tt F833} --- {\tt CONFIGOPTPARAM} ($i$ -- $c^?$), returns the value of the global configuration parameter with integer index $i$ as a {\em Maybe Cell\/}~$c^?$. Equivalent to {\tt CONFIGDICT}; {\tt DICTIGETOPTREF}.
|
\item {\tt F833} --- {\tt CONFIGOPTPARAM} ($i$ -- $c^?$), returns the value of the global configuration parameter with integer index $i$ as a {\em Maybe Cell\/}~$c^?$. Equivalent to {\tt CONFIGDICT}; {\tt DICTIGETOPTREF}.
|
||||||
|
|
|
@ -1680,7 +1680,7 @@ bool TestNode::get_config_params(ton::BlockIdExt blkid, int mode, std::string fi
|
||||||
true);
|
true);
|
||||||
LOG(INFO) << "requesting " << params.size() << " configuration parameters with respect to masterchain block "
|
LOG(INFO) << "requesting " << params.size() << " configuration parameters with respect to masterchain block "
|
||||||
<< blkid.to_str();
|
<< blkid.to_str();
|
||||||
return envelope_send_query(std::move(b), [ Self = actor_id(this), mode, filename,
|
return envelope_send_query(std::move(b), [ Self = actor_id(this), mode, filename, blkid,
|
||||||
params = std::move(params) ](td::Result<td::BufferSlice> R) mutable {
|
params = std::move(params) ](td::Result<td::BufferSlice> R) mutable {
|
||||||
if (R.is_error()) {
|
if (R.is_error()) {
|
||||||
return;
|
return;
|
||||||
|
@ -1690,20 +1690,25 @@ bool TestNode::get_config_params(ton::BlockIdExt blkid, int mode, std::string fi
|
||||||
LOG(ERROR) << "cannot parse answer to liteServer.getConfigParams";
|
LOG(ERROR) << "cannot parse answer to liteServer.getConfigParams";
|
||||||
} else {
|
} else {
|
||||||
auto f = F.move_as_ok();
|
auto f = F.move_as_ok();
|
||||||
td::actor::send_closure_later(Self, &TestNode::got_config_params, ton::create_block_id(f->id_),
|
td::actor::send_closure_later(Self, &TestNode::got_config_params, blkid, ton::create_block_id(f->id_),
|
||||||
std::move(f->state_proof_), std::move(f->config_proof_), mode, filename,
|
std::move(f->state_proof_), std::move(f->config_proof_), mode, filename,
|
||||||
std::move(params));
|
std::move(params));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestNode::got_config_params(ton::BlockIdExt blkid, td::BufferSlice state_proof, td::BufferSlice cfg_proof,
|
void TestNode::got_config_params(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, td::BufferSlice state_proof,
|
||||||
int mode, std::string filename, std::vector<int> params) {
|
td::BufferSlice cfg_proof, int mode, std::string filename, std::vector<int> params) {
|
||||||
LOG(INFO) << "got configuration parameters";
|
LOG(INFO) << "got configuration parameters";
|
||||||
if (!blkid.is_masterchain_ext()) {
|
if (!blkid.is_masterchain_ext()) {
|
||||||
LOG(ERROR) << "reference block " << blkid.to_str() << " for the configuration is not a valid masterchain block";
|
LOG(ERROR) << "reference block " << blkid.to_str() << " for the configuration is not a valid masterchain block";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (blkid != req_blkid) {
|
||||||
|
LOG(ERROR) << "got configuration parameters with respect to block " << blkid.to_str() << " instead of "
|
||||||
|
<< req_blkid.to_str();
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto R = block::check_extract_state_proof(blkid, state_proof.as_slice(), cfg_proof.as_slice());
|
auto R = block::check_extract_state_proof(blkid, state_proof.as_slice(), cfg_proof.as_slice());
|
||||||
if (R.is_error()) {
|
if (R.is_error()) {
|
||||||
LOG(ERROR) << "masterchain state proof for " << blkid.to_str() << " is invalid : " << R.move_as_error().to_string();
|
LOG(ERROR) << "masterchain state proof for " << blkid.to_str() << " is invalid : " << R.move_as_error().to_string();
|
||||||
|
|
|
@ -122,8 +122,8 @@ class TestNode : public td::actor::Actor {
|
||||||
bool get_all_shards(bool use_last = true, ton::BlockIdExt blkid = {});
|
bool get_all_shards(bool use_last = true, ton::BlockIdExt blkid = {});
|
||||||
void got_all_shards(ton::BlockIdExt blk, td::BufferSlice proof, td::BufferSlice data);
|
void got_all_shards(ton::BlockIdExt blk, td::BufferSlice proof, td::BufferSlice data);
|
||||||
bool get_config_params(ton::BlockIdExt blkid, int mode = 0, std::string filename = "");
|
bool get_config_params(ton::BlockIdExt blkid, int mode = 0, std::string filename = "");
|
||||||
void got_config_params(ton::BlockIdExt blkid, td::BufferSlice state_proof, td::BufferSlice cfg_proof, int mode,
|
void got_config_params(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, td::BufferSlice state_proof,
|
||||||
std::string filename, std::vector<int> params);
|
td::BufferSlice cfg_proof, int mode, std::string filename, std::vector<int> params);
|
||||||
bool get_block(ton::BlockIdExt blk, bool dump = false);
|
bool get_block(ton::BlockIdExt blk, bool dump = false);
|
||||||
void got_block(ton::BlockIdExt blkid, td::BufferSlice data, bool dump);
|
void got_block(ton::BlockIdExt blkid, td::BufferSlice data, bool dump);
|
||||||
bool get_state(ton::BlockIdExt blk, bool dump = false);
|
bool get_state(ton::BlockIdExt blk, bool dump = false);
|
||||||
|
|
|
@ -76,7 +76,7 @@ void ActorExecutor::send(ActorSignals signals) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorExecutor::start() noexcept {
|
void ActorExecutor::start() noexcept {
|
||||||
//LOG(ERROR) << "START " << actor_info_.get_name() << " " << tag("from_queue", options.from_queue);
|
//LOG(ERROR) << "START " << actor_info_.get_name() << " " << tag("from_queue", options_.from_queue);
|
||||||
if (is_closed()) {
|
if (is_closed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,7 @@ void Scheduler::ContextImpl::add_to_queue(ActorInfoPtr actor_info_ptr, Scheduler
|
||||||
if (!scheduler_id.is_valid()) {
|
if (!scheduler_id.is_valid()) {
|
||||||
scheduler_id = get_scheduler_id();
|
scheduler_id = get_scheduler_id();
|
||||||
}
|
}
|
||||||
|
//LOG(ERROR) << "Add to queue: " << actor_info_ptr->get_name() << " " << scheduler_id.value();
|
||||||
auto &info = scheduler_group()->schedulers.at(scheduler_id.value());
|
auto &info = scheduler_group()->schedulers.at(scheduler_id.value());
|
||||||
if (need_poll || !info.cpu_queue) {
|
if (need_poll || !info.cpu_queue) {
|
||||||
info.io_queue->writer_put(std::move(actor_info_ptr));
|
info.io_queue->writer_put(std::move(actor_info_ptr));
|
||||||
|
|
|
@ -32,8 +32,13 @@ struct RawCancellationToken {
|
||||||
class CancellationToken {
|
class CancellationToken {
|
||||||
public:
|
public:
|
||||||
explicit operator bool() const {
|
explicit operator bool() const {
|
||||||
|
// Empty CancellationToken is never cancelled
|
||||||
|
if (!token_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return token_->is_cancelled_.load(std::memory_order_acquire);
|
return token_->is_cancelled_.load(std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
CancellationToken() = default;
|
||||||
explicit CancellationToken(std::shared_ptr<detail::RawCancellationToken> token) : token_(std::move(token)) {
|
explicit CancellationToken(std::shared_ptr<detail::RawCancellationToken> token) : token_(std::move(token)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,11 @@ generic.accountStateUninited account_state:uninited.accountState = generic.Accou
|
||||||
|
|
||||||
sendGramsResult sent_until:int53 body_hash:bytes = SendGramsResult;
|
sendGramsResult sent_until:int53 body_hash:bytes = SendGramsResult;
|
||||||
|
|
||||||
|
syncStateDone = SyncState;
|
||||||
|
syncStateInProgress from_seqno:int32 to_seqno:int32 current_seqno:int32 = SyncState;
|
||||||
|
|
||||||
updateSendLiteServerQuery id:int64 data:bytes = Update;
|
updateSendLiteServerQuery id:int64 data:bytes = Update;
|
||||||
|
updateSyncState sync_state:SyncState = Update;
|
||||||
|
|
||||||
//@class LogStream @description Describes a stream to which TDLib internal log is written
|
//@class LogStream @description Describes a stream to which TDLib internal log is written
|
||||||
|
|
||||||
|
@ -134,6 +138,8 @@ testGiver.getAccountState = testGiver.AccountState;
|
||||||
testGiver.getAccountAddress = AccountAddress;
|
testGiver.getAccountAddress = AccountAddress;
|
||||||
testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 message:bytes = SendGramsResult;
|
testGiver.sendGrams destination:accountAddress seqno:int32 amount:int64 message:bytes = SendGramsResult;
|
||||||
|
|
||||||
|
sync = Ok;
|
||||||
|
|
||||||
//generic.getAccountAddress initital_account_state:generic.InitialAccountState = AccountAddress;
|
//generic.getAccountAddress initital_account_state:generic.InitialAccountState = AccountAddress;
|
||||||
generic.getAccountState account_address:accountAddress = generic.AccountState;
|
generic.getAccountState account_address:accountAddress = generic.AccountState;
|
||||||
generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 timeout:int32 allow_send_to_uninited:Bool message:bytes = SendGramsResult;
|
generic.sendGrams private_key:inputKey source:accountAddress destination:accountAddress amount:int64 timeout:int32 allow_send_to_uninited:Bool message:bytes = SendGramsResult;
|
||||||
|
|
Binary file not shown.
|
@ -56,8 +56,10 @@ class Client::Impl final {
|
||||||
std::shared_ptr<OutputQueue> output_queue_;
|
std::shared_ptr<OutputQueue> output_queue_;
|
||||||
};
|
};
|
||||||
|
|
||||||
scheduler_.run_in_context(
|
scheduler_.run_in_context([&] {
|
||||||
[&] { tonlib_ = td::actor::create_actor<TonlibClient>("Tonlib", td::make_unique<Callback>(output_queue_)); });
|
tonlib_ = td::actor::create_actor<TonlibClient>(td::actor::ActorOptions().with_name("Tonlib").with_poll(),
|
||||||
|
td::make_unique<Callback>(output_queue_));
|
||||||
|
});
|
||||||
|
|
||||||
scheduler_thread_ = td::thread([&] { scheduler_.run(); });
|
scheduler_thread_ = td::thread([&] { scheduler_.run(); });
|
||||||
}
|
}
|
||||||
|
@ -107,7 +109,7 @@ class Client::Impl final {
|
||||||
std::atomic<bool> receive_lock_{false};
|
std::atomic<bool> receive_lock_{false};
|
||||||
bool is_closed_{false};
|
bool is_closed_{false};
|
||||||
|
|
||||||
td::actor::Scheduler scheduler_{{0}};
|
td::actor::Scheduler scheduler_{{1}};
|
||||||
td::thread scheduler_thread_;
|
td::thread scheduler_thread_;
|
||||||
td::actor::ActorOwn<TonlibClient> tonlib_;
|
td::actor::ActorOwn<TonlibClient> tonlib_;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
#include "tonlib/LastBlock.h"
|
#include "tonlib/LastBlock.h"
|
||||||
|
|
||||||
namespace tonlib {
|
namespace tonlib {
|
||||||
|
ExtClient::~ExtClient() {
|
||||||
|
last_block_queries_.for_each([](auto id, auto &promise) { promise.set_error(TonlibError::Cancelled()); });
|
||||||
|
queries_.for_each([](auto id, auto &promise) { promise.set_error(TonlibError::Cancelled()); });
|
||||||
|
}
|
||||||
void ExtClient::with_last_block(td::Promise<LastBlockState> promise) {
|
void ExtClient::with_last_block(td::Promise<LastBlockState> promise) {
|
||||||
auto query_id = last_block_queries_.create(std::move(promise));
|
auto query_id = last_block_queries_.create(std::move(promise));
|
||||||
td::Promise<LastBlockState> P = [query_id, self = this,
|
td::Promise<LastBlockState> P = [query_id, self = this,
|
||||||
|
|
|
@ -53,6 +53,7 @@ class ExtClient {
|
||||||
ExtClientRef get_client() {
|
ExtClientRef get_client() {
|
||||||
return client_;
|
return client_;
|
||||||
}
|
}
|
||||||
|
~ExtClient();
|
||||||
|
|
||||||
void with_last_block(td::Promise<LastBlockState> promise);
|
void with_last_block(td::Promise<LastBlockState> promise);
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,22 @@ td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state
|
||||||
<< td::tag("init_block", state.init_block_id.to_str());
|
<< td::tag("init_block", state.init_block_id.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr<Callback> callback)
|
LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::CancellationToken cancellation_token,
|
||||||
: state_(std::move(state)), config_(std::move(config)), callback_(std::move(callback)) {
|
td::unique_ptr<Callback> callback)
|
||||||
|
: callback_(std::move(callback))
|
||||||
|
, state_(std::move(state))
|
||||||
|
, config_(std::move(config))
|
||||||
|
, cancellation_token_(std::move(cancellation_token)) {
|
||||||
client_.set_client(client);
|
client_.set_client(client);
|
||||||
state_.last_block_id = state_.last_key_block_id;
|
state_.last_block_id = state_.last_key_block_id;
|
||||||
|
|
||||||
|
if (state_.last_key_block_id.is_valid()) {
|
||||||
|
min_seqno_ = state_.last_key_block_id.id.seqno;
|
||||||
|
}
|
||||||
|
if (config_.init_block_id.is_valid() && config_.init_block_id != state_.init_block_id) {
|
||||||
|
min_seqno_ = td::min(min_seqno_, config_.init_block_id.id.seqno);
|
||||||
|
}
|
||||||
|
current_seqno_ = min_seqno_;
|
||||||
VLOG(last_block) << "State: " << state_;
|
VLOG(last_block) << "State: " << state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +72,9 @@ void LastBlock::get_last_block(td::Promise<LastBlockState> promise) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastBlock::sync_loop() {
|
void LastBlock::sync_loop() {
|
||||||
|
SCOPE_EXIT {
|
||||||
|
update_sync_state();
|
||||||
|
};
|
||||||
if (promises_.empty()) {
|
if (promises_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -147,7 +161,7 @@ td::Result<std::unique_ptr<block::BlockProofChain>> LastBlock::process_block_pro
|
||||||
return td::Status::Error(PSLICE() << "block proof chain starts from block " << chain->from.to_str()
|
return td::Status::Error(PSLICE() << "block proof chain starts from block " << chain->from.to_str()
|
||||||
<< ", not from requested block " << from.to_str());
|
<< ", not from requested block " << from.to_str());
|
||||||
}
|
}
|
||||||
TRY_STATUS(chain->validate());
|
TRY_STATUS(chain->validate(cancellation_token_));
|
||||||
return std::move(chain);
|
return std::move(chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +169,8 @@ void LastBlock::update_state(block::BlockProofChain& chain) {
|
||||||
// Update state_
|
// Update state_
|
||||||
bool is_changed = false;
|
bool is_changed = false;
|
||||||
is_changed |= update_mc_last_block(chain.to);
|
is_changed |= update_mc_last_block(chain.to);
|
||||||
|
current_seqno_ = td::max(current_seqno_, chain.to.id.seqno);
|
||||||
|
max_seqno_ = td::max(max_seqno_, current_seqno_);
|
||||||
if (chain.has_key_block) {
|
if (chain.has_key_block) {
|
||||||
is_changed |= update_mc_last_key_block(chain.key_blkid);
|
is_changed |= update_mc_last_key_block(chain.key_blkid);
|
||||||
}
|
}
|
||||||
|
@ -193,10 +209,10 @@ void LastBlock::on_block_proof(
|
||||||
if (chain->complete) {
|
if (chain->complete) {
|
||||||
VLOG(last_block) << "get_last_block: done\n" << get_last_block_stats_;
|
VLOG(last_block) << "get_last_block: done\n" << get_last_block_stats_;
|
||||||
get_last_block_state_ = QueryState::Done;
|
get_last_block_state_ = QueryState::Done;
|
||||||
sync_loop();
|
|
||||||
} else {
|
} else {
|
||||||
do_get_last_block();
|
do_get_last_block();
|
||||||
}
|
}
|
||||||
|
sync_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastBlock::on_init_block_proof(
|
void LastBlock::on_init_block_proof(
|
||||||
|
@ -209,6 +225,7 @@ void LastBlock::on_init_block_proof(
|
||||||
check_init_block_state_ = QueryState::Empty;
|
check_init_block_state_ = QueryState::Empty;
|
||||||
VLOG(last_block) << "check_init_block: error " << r_chain.error();
|
VLOG(last_block) << "check_init_block: error " << r_chain.error();
|
||||||
on_sync_error(r_chain.move_as_error_suffix("(during check init block)"));
|
on_sync_error(r_chain.move_as_error_suffix("(during check init block)"));
|
||||||
|
sync_loop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto chain = r_chain.move_as_ok();
|
auto chain = r_chain.move_as_ok();
|
||||||
|
@ -220,10 +237,10 @@ void LastBlock::on_init_block_proof(
|
||||||
if (update_init_block(config_.init_block_id)) {
|
if (update_init_block(config_.init_block_id)) {
|
||||||
save_state();
|
save_state();
|
||||||
}
|
}
|
||||||
sync_loop();
|
|
||||||
} else {
|
} else {
|
||||||
do_check_init_block(chain->to, to);
|
do_check_init_block(chain->to, to);
|
||||||
}
|
}
|
||||||
|
sync_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LastBlock::on_masterchain_info(
|
void LastBlock::on_masterchain_info(
|
||||||
|
@ -233,6 +250,7 @@ void LastBlock::on_masterchain_info(
|
||||||
update_zero_state(create_zero_state_id(info->init_), "masterchain info");
|
update_zero_state(create_zero_state_id(info->init_), "masterchain info");
|
||||||
// last block is not validated! Do not update it
|
// last block is not validated! Do not update it
|
||||||
get_mc_info_state_ = QueryState::Done;
|
get_mc_info_state_ = QueryState::Done;
|
||||||
|
max_seqno_ = td::max(max_seqno_, (unsigned)info->last_->seqno_);
|
||||||
VLOG(last_block) << "get_masterchain_info: done";
|
VLOG(last_block) << "get_masterchain_info: done";
|
||||||
} else {
|
} else {
|
||||||
get_mc_info_state_ = QueryState::Empty;
|
get_mc_info_state_ = QueryState::Empty;
|
||||||
|
@ -334,6 +352,9 @@ void LastBlock::on_sync_ok() {
|
||||||
}
|
}
|
||||||
void LastBlock::on_sync_error(td::Status status) {
|
void LastBlock::on_sync_error(td::Status status) {
|
||||||
VLOG(last_block) << "sync: error " << status;
|
VLOG(last_block) << "sync: error " << status;
|
||||||
|
if (cancellation_token_) {
|
||||||
|
status = TonlibError::Cancelled();
|
||||||
|
}
|
||||||
for (auto& promise : promises_) {
|
for (auto& promise : promises_) {
|
||||||
promise.set_error(status.clone());
|
promise.set_error(status.clone());
|
||||||
}
|
}
|
||||||
|
@ -348,4 +369,32 @@ void LastBlock::on_fatal_error(td::Status status) {
|
||||||
bool LastBlock::has_fatal_error() const {
|
bool LastBlock::has_fatal_error() const {
|
||||||
return fatal_error_.is_error();
|
return fatal_error_.is_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LastBlockSyncState LastBlock::get_sync_state() {
|
||||||
|
LastBlockSyncState state;
|
||||||
|
if (promises_.empty()) {
|
||||||
|
state.type = LastBlockSyncState::Done;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
state.type = LastBlockSyncState::InProgress;
|
||||||
|
state.from_seqno = min_seqno_;
|
||||||
|
state.to_seqno = max_seqno_;
|
||||||
|
state.current_seqno = current_seqno_;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastBlock::update_sync_state() {
|
||||||
|
auto new_state = get_sync_state();
|
||||||
|
if (new_state == sync_state_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sync_state_ = new_state;
|
||||||
|
VLOG(last_block) << "Sync state: " << current_seqno_ - min_seqno_ << " / " << max_seqno_ - min_seqno_;
|
||||||
|
callback_->on_sync_state_changed(sync_state_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LastBlock::tear_down() {
|
||||||
|
on_sync_error(TonlibError::Cancelled());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace tonlib
|
} // namespace tonlib
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "tonlib/Config.h"
|
#include "tonlib/Config.h"
|
||||||
#include "tonlib/ExtClient.h"
|
#include "tonlib/ExtClient.h"
|
||||||
|
|
||||||
|
#include "td/utils/CancellationToken.h"
|
||||||
#include "td/utils/tl_helpers.h"
|
#include "td/utils/tl_helpers.h"
|
||||||
|
|
||||||
namespace block {
|
namespace block {
|
||||||
|
@ -132,6 +133,20 @@ struct LastBlockState {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LastBlockSyncState {
|
||||||
|
enum Type { Invalid, InProgress, Done } type = Invalid;
|
||||||
|
td::int32 from_seqno{0};
|
||||||
|
td::int32 to_seqno{0};
|
||||||
|
td::int32 current_seqno{0};
|
||||||
|
|
||||||
|
auto as_key() const {
|
||||||
|
return std::tie(type, from_seqno, to_seqno, current_seqno);
|
||||||
|
}
|
||||||
|
bool operator==(const LastBlockSyncState &other) const {
|
||||||
|
return as_key() == other.as_key();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class LastBlock : public td::actor::Actor {
|
class LastBlock : public td::actor::Actor {
|
||||||
public:
|
public:
|
||||||
class Callback {
|
class Callback {
|
||||||
|
@ -139,16 +154,19 @@ class LastBlock : public td::actor::Actor {
|
||||||
virtual ~Callback() {
|
virtual ~Callback() {
|
||||||
}
|
}
|
||||||
virtual void on_state_changed(LastBlockState state) = 0;
|
virtual void on_state_changed(LastBlockState state) = 0;
|
||||||
|
virtual void on_sync_state_changed(LastBlockSyncState state) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr<Callback> callback);
|
explicit LastBlock(ExtClientRef client, LastBlockState state, Config config, td::CancellationToken cancellation_token,
|
||||||
|
td::unique_ptr<Callback> callback);
|
||||||
void get_last_block(td::Promise<LastBlockState> promise);
|
void get_last_block(td::Promise<LastBlockState> promise);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
td::unique_ptr<Callback> callback_;
|
||||||
ExtClient client_;
|
ExtClient client_;
|
||||||
LastBlockState state_;
|
LastBlockState state_;
|
||||||
Config config_;
|
Config config_;
|
||||||
td::unique_ptr<Callback> callback_;
|
td::CancellationToken cancellation_token_;
|
||||||
|
|
||||||
td::Status fatal_error_;
|
td::Status fatal_error_;
|
||||||
|
|
||||||
|
@ -157,6 +175,11 @@ class LastBlock : public td::actor::Actor {
|
||||||
QueryState check_init_block_state_{QueryState::Empty}; // init_block <---> last_key_block (from older to newer)
|
QueryState check_init_block_state_{QueryState::Empty}; // init_block <---> last_key_block (from older to newer)
|
||||||
QueryState get_last_block_state_{QueryState::Empty}; // last_key_block_id --> ?
|
QueryState get_last_block_state_{QueryState::Empty}; // last_key_block_id --> ?
|
||||||
|
|
||||||
|
unsigned min_seqno_ = 0;
|
||||||
|
unsigned current_seqno_ = 0;
|
||||||
|
unsigned max_seqno_ = 0;
|
||||||
|
LastBlockSyncState sync_state_;
|
||||||
|
|
||||||
// stats
|
// stats
|
||||||
struct Stats {
|
struct Stats {
|
||||||
td::Timer total_sync_;
|
td::Timer total_sync_;
|
||||||
|
@ -209,6 +232,10 @@ class LastBlock : public td::actor::Actor {
|
||||||
void on_fatal_error(td::Status status);
|
void on_fatal_error(td::Status status);
|
||||||
bool has_fatal_error() const;
|
bool has_fatal_error() const;
|
||||||
|
|
||||||
|
LastBlockSyncState get_sync_state();
|
||||||
|
void update_sync_state();
|
||||||
void sync_loop();
|
void sync_loop();
|
||||||
|
|
||||||
|
void tear_down() override;
|
||||||
};
|
};
|
||||||
} // namespace tonlib
|
} // namespace tonlib
|
||||||
|
|
|
@ -166,6 +166,9 @@ class GetTransactionHistory : public td::actor::Actor {
|
||||||
hash_),
|
hash_),
|
||||||
[self = this](auto r_transactions) { self->with_transactions(std::move(r_transactions)); });
|
[self = this](auto r_transactions) { self->with_transactions(std::move(r_transactions)); });
|
||||||
}
|
}
|
||||||
|
void hangup() override {
|
||||||
|
check(TonlibError::Cancelled());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetRawAccountState : public td::actor::Actor {
|
class GetRawAccountState : public td::actor::Actor {
|
||||||
|
@ -277,6 +280,9 @@ class GetRawAccountState : public td::actor::Actor {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void hangup() override {
|
||||||
|
check(TonlibError::Cancelled());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TonlibClient::TonlibClient(td::unique_ptr<TonlibCallback> callback) : callback_(std::move(callback)) {
|
TonlibClient::TonlibClient(td::unique_ptr<TonlibCallback> callback) : callback_(std::move(callback)) {
|
||||||
|
@ -284,6 +290,7 @@ TonlibClient::TonlibClient(td::unique_ptr<TonlibCallback> callback) : callback_(
|
||||||
TonlibClient::~TonlibClient() = default;
|
TonlibClient::~TonlibClient() = default;
|
||||||
|
|
||||||
void TonlibClient::hangup() {
|
void TonlibClient::hangup() {
|
||||||
|
source_.cancel();
|
||||||
is_closing_ = true;
|
is_closing_ = true;
|
||||||
ref_cnt_--;
|
ref_cnt_--;
|
||||||
raw_client_ = {};
|
raw_client_ = {};
|
||||||
|
@ -300,7 +307,7 @@ ExtClientRef TonlibClient::get_client_ref() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TonlibClient::proxy_request(td::int64 query_id, std::string data) {
|
void TonlibClient::proxy_request(td::int64 query_id, std::string data) {
|
||||||
callback_->on_result(0, tonlib_api::make_object<tonlib_api::updateSendLiteServerQuery>(query_id, data));
|
on_update(tonlib_api::make_object<tonlib_api::updateSendLiteServerQuery>(query_id, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TonlibClient::init_ext_client() {
|
void TonlibClient::init_ext_client() {
|
||||||
|
@ -342,8 +349,28 @@ void TonlibClient::init_ext_client() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TonlibClient::update_last_block_state(LastBlockState state, td::uint32 config_generation) {
|
void TonlibClient::update_last_block_state(LastBlockState state, td::uint32 config_generation) {
|
||||||
if (config_generation == config_generation_) {
|
if (config_generation != config_generation_) {
|
||||||
last_block_storage_.save_state(blockchain_name_, state);
|
return;
|
||||||
|
}
|
||||||
|
last_block_storage_.save_state(blockchain_name_, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TonlibClient::update_sync_state(LastBlockSyncState state, td::uint32 config_generation) {
|
||||||
|
if (config_generation != config_generation_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (state.type) {
|
||||||
|
case LastBlockSyncState::Done:
|
||||||
|
on_update(
|
||||||
|
tonlib_api::make_object<tonlib_api::updateSyncState>(tonlib_api::make_object<tonlib_api::syncStateDone>()));
|
||||||
|
break;
|
||||||
|
case LastBlockSyncState::InProgress:
|
||||||
|
on_update(
|
||||||
|
tonlib_api::make_object<tonlib_api::updateSyncState>(tonlib_api::make_object<tonlib_api::syncStateInProgress>(
|
||||||
|
state.from_seqno, state.to_seqno, state.current_seqno)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG(ERROR) << "Unknown LastBlockSyncState type " << state.type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,6 +384,9 @@ void TonlibClient::init_last_block() {
|
||||||
void on_state_changed(LastBlockState state) override {
|
void on_state_changed(LastBlockState state) override {
|
||||||
send_closure(client_, &TonlibClient::update_last_block_state, std::move(state), config_generation_);
|
send_closure(client_, &TonlibClient::update_last_block_state, std::move(state), config_generation_);
|
||||||
}
|
}
|
||||||
|
void on_sync_state_changed(LastBlockSyncState sync_state) override {
|
||||||
|
send_closure(client_, &TonlibClient::update_sync_state, std::move(sync_state), config_generation_);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
td::actor::ActorShared<TonlibClient> client_;
|
td::actor::ActorShared<TonlibClient> client_;
|
||||||
|
@ -379,19 +409,23 @@ void TonlibClient::init_last_block() {
|
||||||
state = r_state.move_as_ok();
|
state = r_state.move_as_ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_last_block_ =
|
raw_last_block_ = td::actor::create_actor<LastBlock>(
|
||||||
td::actor::create_actor<LastBlock>("LastBlock", get_client_ref(), std::move(state), config_,
|
td::actor::ActorOptions().with_name("LastBlock").with_poll(false), get_client_ref(), std::move(state), config_,
|
||||||
td::make_unique<Callback>(td::actor::actor_shared(this), config_generation_));
|
source_.get_cancellation_token(), td::make_unique<Callback>(td::actor::actor_shared(this), config_generation_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TonlibClient::on_result(td::uint64 id, tonlib_api::object_ptr<tonlib_api::Object> response) {
|
void TonlibClient::on_result(td::uint64 id, tonlib_api::object_ptr<tonlib_api::Object> response) {
|
||||||
VLOG(tonlib_query) << "Tonlib answer query " << td::tag("id", id) << " " << to_string(response);
|
VLOG_IF(tonlib_query, id != 0) << "Tonlib answer query " << td::tag("id", id) << " " << to_string(response);
|
||||||
|
VLOG_IF(tonlib_query, id == 0) << "Tonlib update " << to_string(response);
|
||||||
if (response->get_id() == tonlib_api::error::ID) {
|
if (response->get_id() == tonlib_api::error::ID) {
|
||||||
callback_->on_error(id, tonlib_api::move_object_as<tonlib_api::error>(response));
|
callback_->on_error(id, tonlib_api::move_object_as<tonlib_api::error>(response));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callback_->on_result(id, std::move(response));
|
callback_->on_result(id, std::move(response));
|
||||||
}
|
}
|
||||||
|
void TonlibClient::on_update(object_ptr<tonlib_api::Object> response) {
|
||||||
|
on_result(0, std::move(response));
|
||||||
|
}
|
||||||
|
|
||||||
void TonlibClient::request(td::uint64 id, tonlib_api::object_ptr<tonlib_api::Function> function) {
|
void TonlibClient::request(td::uint64 id, tonlib_api::object_ptr<tonlib_api::Function> function) {
|
||||||
VLOG(tonlib_query) << "Tonlib got query " << td::tag("id", id) << " " << to_string(function);
|
VLOG(tonlib_query) << "Tonlib got query " << td::tag("id", id) << " " << to_string(function);
|
||||||
|
@ -415,7 +449,9 @@ void TonlibClient::request(td::uint64 id, tonlib_api::object_ptr<tonlib_api::Fun
|
||||||
|
|
||||||
downcast_call(*function, [this, self = this, id](auto& request) {
|
downcast_call(*function, [this, self = this, id](auto& request) {
|
||||||
using ReturnType = typename std::decay_t<decltype(request)>::ReturnType;
|
using ReturnType = typename std::decay_t<decltype(request)>::ReturnType;
|
||||||
td::Promise<ReturnType> promise = [actor_id = actor_id(self), id](td::Result<ReturnType> r_result) {
|
ref_cnt_++;
|
||||||
|
td::Promise<ReturnType> promise = [actor_id = actor_id(self), id,
|
||||||
|
tmp = actor_shared(self)](td::Result<ReturnType> r_result) {
|
||||||
tonlib_api::object_ptr<tonlib_api::Object> result;
|
tonlib_api::object_ptr<tonlib_api::Object> result;
|
||||||
if (r_result.is_error()) {
|
if (r_result.is_error()) {
|
||||||
result = status_to_tonlib_api(r_result.error());
|
result = status_to_tonlib_api(r_result.error());
|
||||||
|
@ -647,6 +683,7 @@ td::Status TonlibClient::do_request(const tonlib_api::close& request,
|
||||||
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||||
CHECK(state_ != State::Closed);
|
CHECK(state_ != State::Closed);
|
||||||
state_ = State::Closed;
|
state_ = State::Closed;
|
||||||
|
source_.cancel();
|
||||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||||
return td::Status::OK();
|
return td::Status::OK();
|
||||||
}
|
}
|
||||||
|
@ -1257,6 +1294,9 @@ class GenericSendGrams : public TonlibQueryActor {
|
||||||
void start_up() override {
|
void start_up() override {
|
||||||
check(do_start_up());
|
check(do_start_up());
|
||||||
}
|
}
|
||||||
|
void hangup() override {
|
||||||
|
check(TonlibError::Cancelled());
|
||||||
|
}
|
||||||
|
|
||||||
td::Status do_start_up() {
|
td::Status do_start_up() {
|
||||||
if (!send_grams_.destination_) {
|
if (!send_grams_.destination_) {
|
||||||
|
@ -1426,6 +1466,15 @@ td::Status TonlibClient::do_request(tonlib_api::generic_sendGrams& request,
|
||||||
return td::Status::OK();
|
return td::Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td::Status TonlibClient::do_request(tonlib_api::sync& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise) {
|
||||||
|
client_.with_last_block([promise = std::move(promise)](td::Result<LastBlockState> r_last_block) mutable {
|
||||||
|
TRY_RESULT_PROMISE(promise, last_block, std::move(r_last_block));
|
||||||
|
(void)last_block;
|
||||||
|
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||||
|
});
|
||||||
|
return td::Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
td::Result<block::PublicKey> public_key_from_bytes(td::Slice bytes) {
|
td::Result<block::PublicKey> public_key_from_bytes(td::Slice bytes) {
|
||||||
TRY_RESULT_PREFIX(key_bytes, block::PublicKey::from_bytes(bytes), TonlibError::Internal());
|
TRY_RESULT_PREFIX(key_bytes, block::PublicKey::from_bytes(bytes), TonlibError::Internal());
|
||||||
return key_bytes;
|
return key_bytes;
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
|
|
||||||
|
#include "td/utils/CancellationToken.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace tonlib {
|
namespace tonlib {
|
||||||
|
@ -66,6 +68,8 @@ class TonlibClient : public td::actor::Actor {
|
||||||
td::actor::ActorOwn<LastBlock> raw_last_block_;
|
td::actor::ActorOwn<LastBlock> raw_last_block_;
|
||||||
ExtClient client_;
|
ExtClient client_;
|
||||||
|
|
||||||
|
td::CancellationTokenSource source_;
|
||||||
|
|
||||||
std::map<td::int64, td::actor::ActorOwn<>> actors_;
|
std::map<td::int64, td::actor::ActorOwn<>> actors_;
|
||||||
td::int64 actor_id_{1};
|
td::int64 actor_id_{1};
|
||||||
|
|
||||||
|
@ -92,7 +96,9 @@ class TonlibClient : public td::actor::Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_last_block_state(LastBlockState state, td::uint32 config_generation_);
|
void update_last_block_state(LastBlockState state, td::uint32 config_generation_);
|
||||||
|
void update_sync_state(LastBlockSyncState state, td::uint32 config_generation);
|
||||||
void on_result(td::uint64 id, object_ptr<tonlib_api::Object> response);
|
void on_result(td::uint64 id, object_ptr<tonlib_api::Object> response);
|
||||||
|
void on_update(object_ptr<tonlib_api::Object> response);
|
||||||
static bool is_static_request(td::int32 id);
|
static bool is_static_request(td::int32 id);
|
||||||
static bool is_uninited_request(td::int32 id);
|
static bool is_uninited_request(td::int32 id);
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -159,6 +165,8 @@ class TonlibClient : public td::actor::Actor {
|
||||||
td::Status do_request(tonlib_api::generic_sendGrams& request,
|
td::Status do_request(tonlib_api::generic_sendGrams& request,
|
||||||
td::Promise<object_ptr<tonlib_api::sendGramsResult>>&& promise);
|
td::Promise<object_ptr<tonlib_api::sendGramsResult>>&& promise);
|
||||||
|
|
||||||
|
td::Status do_request(tonlib_api::sync& request, td::Promise<object_ptr<tonlib_api::ok>>&& promise);
|
||||||
|
|
||||||
td::Status do_request(const tonlib_api::createNewKey& request, td::Promise<object_ptr<tonlib_api::key>>&& promise);
|
td::Status do_request(const tonlib_api::createNewKey& request, td::Promise<object_ptr<tonlib_api::key>>&& promise);
|
||||||
td::Status do_request(const tonlib_api::exportKey& request,
|
td::Status do_request(const tonlib_api::exportKey& request,
|
||||||
td::Promise<object_ptr<tonlib_api::exportedKey>>&& promise);
|
td::Promise<object_ptr<tonlib_api::exportedKey>>&& promise);
|
||||||
|
|
|
@ -94,7 +94,7 @@ class TonlibCli : public td::actor::Actor {
|
||||||
td::actor::ActorShared<TonlibCli> id_;
|
td::actor::ActorShared<TonlibCli> id_;
|
||||||
};
|
};
|
||||||
ref_cnt_++;
|
ref_cnt_++;
|
||||||
client_ = td::actor::create_actor<tonlib::TonlibClient>("Tonlib", td::make_unique<TonlibCb>(actor_shared(this)));
|
client_ = td::actor::create_actor<tonlib::TonlibClient>("Tonlib", td::make_unique<TonlibCb>(actor_shared(this, 1)));
|
||||||
|
|
||||||
td::mkdir(options_.key_dir).ignore();
|
td::mkdir(options_.key_dir).ignore();
|
||||||
|
|
||||||
|
@ -144,6 +144,9 @@ class TonlibCli : public td::actor::Actor {
|
||||||
void hangup_shared() override {
|
void hangup_shared() override {
|
||||||
CHECK(ref_cnt_ > 0);
|
CHECK(ref_cnt_ > 0);
|
||||||
ref_cnt_--;
|
ref_cnt_--;
|
||||||
|
if (get_link_token() == 1) {
|
||||||
|
io_.reset();
|
||||||
|
}
|
||||||
try_stop();
|
try_stop();
|
||||||
}
|
}
|
||||||
void try_stop() {
|
void try_stop() {
|
||||||
|
@ -221,7 +224,6 @@ class TonlibCli : public td::actor::Actor {
|
||||||
generate_key();
|
generate_key();
|
||||||
} else if (cmd == "exit") {
|
} else if (cmd == "exit") {
|
||||||
is_closing_ = true;
|
is_closing_ = true;
|
||||||
io_.reset();
|
|
||||||
client_.reset();
|
client_.reset();
|
||||||
ref_cnt_--;
|
ref_cnt_--;
|
||||||
try_stop();
|
try_stop();
|
||||||
|
@ -263,9 +265,20 @@ class TonlibCli : public td::actor::Actor {
|
||||||
set_bounceable(addr, to_bool(bounceable, true));
|
set_bounceable(addr, to_bool(bounceable, true));
|
||||||
} else if (cmd == "netstats") {
|
} else if (cmd == "netstats") {
|
||||||
dump_netstats();
|
dump_netstats();
|
||||||
|
} else if (cmd == "sync") {
|
||||||
|
sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sync() {
|
||||||
|
using tonlib_api::make_object;
|
||||||
|
send_query(make_object<tonlib_api::sync>(), [](auto r_ok) {
|
||||||
|
LOG_IF(ERROR, r_ok.is_error()) << r_ok.error();
|
||||||
|
if (r_ok.is_ok()) {
|
||||||
|
td::TerminalIO::out() << "synchronized\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
void dump_netstats() {
|
void dump_netstats() {
|
||||||
td::TerminalIO::out() << td::tag("snd", td::format::as_size(snd_bytes_)) << "\n";
|
td::TerminalIO::out() << td::tag("snd", td::format::as_size(snd_bytes_)) << "\n";
|
||||||
td::TerminalIO::out() << td::tag("rcv", td::format::as_size(rcv_bytes_)) << "\n";
|
td::TerminalIO::out() << td::tag("rcv", td::format::as_size(rcv_bytes_)) << "\n";
|
||||||
|
|
|
@ -215,12 +215,21 @@ void ValidatorManagerMasterchainReiniter::choose_masterchain_state() {
|
||||||
<< " is_persistent=" << (!p || ValidatorManager::is_persistent_state(h->unix_time(), p->unix_time()))
|
<< " is_persistent=" << (!p || ValidatorManager::is_persistent_state(h->unix_time(), p->unix_time()))
|
||||||
<< " ttl=" << ValidatorManager::persistent_state_ttl(h->unix_time())
|
<< " ttl=" << ValidatorManager::persistent_state_ttl(h->unix_time())
|
||||||
<< " syncbefore=" << opts_->sync_blocks_before();
|
<< " syncbefore=" << opts_->sync_blocks_before();
|
||||||
|
if (h->unix_time() + opts_->sync_blocks_before() > td::Clocks::system()) {
|
||||||
|
LOG(INFO) << "ignoring: too new block";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!p || ValidatorManager::is_persistent_state(h->unix_time(), p->unix_time())) {
|
if (!p || ValidatorManager::is_persistent_state(h->unix_time(), p->unix_time())) {
|
||||||
auto ttl = ValidatorManager::persistent_state_ttl(h->unix_time());
|
auto ttl = ValidatorManager::persistent_state_ttl(h->unix_time());
|
||||||
if (ttl > td::Clocks::system() + opts_->sync_blocks_before()) {
|
td::Clocks::Duration time_to_download = 3600;
|
||||||
|
if (ttl > td::Clocks::system() + time_to_download) {
|
||||||
handle = h;
|
handle = h;
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << "ignoring: state is expiring shortly: expire_at=" << ttl;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << "ignoring: state is not persistent";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue