1
0
Fork 0
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:
ton 2019-10-14 11:13:23 +04:00
parent 38c3e39066
commit b978e27b2f
63 changed files with 3185 additions and 81 deletions

View file

@ -56,8 +56,10 @@ class Client::Impl final {
std::shared_ptr<OutputQueue> output_queue_;
};
scheduler_.run_in_context(
[&] { tonlib_ = td::actor::create_actor<TonlibClient>("Tonlib", td::make_unique<Callback>(output_queue_)); });
scheduler_.run_in_context([&] {
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(); });
}
@ -107,7 +109,7 @@ class Client::Impl final {
std::atomic<bool> receive_lock_{false};
bool is_closed_{false};
td::actor::Scheduler scheduler_{{0}};
td::actor::Scheduler scheduler_{{1}};
td::thread scheduler_thread_;
td::actor::ActorOwn<TonlibClient> tonlib_;

View file

@ -21,6 +21,10 @@
#include "tonlib/LastBlock.h"
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) {
auto query_id = last_block_queries_.create(std::move(promise));
td::Promise<LastBlockState> P = [query_id, self = this,

View file

@ -53,6 +53,7 @@ class ExtClient {
ExtClientRef get_client() {
return client_;
}
~ExtClient();
void with_last_block(td::Promise<LastBlockState> promise);

View file

@ -36,11 +36,22 @@ td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state
<< td::tag("init_block", state.init_block_id.to_str());
}
LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr<Callback> callback)
: state_(std::move(state)), config_(std::move(config)), callback_(std::move(callback)) {
LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::CancellationToken cancellation_token,
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);
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_;
}
@ -61,6 +72,9 @@ void LastBlock::get_last_block(td::Promise<LastBlockState> promise) {
}
void LastBlock::sync_loop() {
SCOPE_EXIT {
update_sync_state();
};
if (promises_.empty()) {
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()
<< ", not from requested block " << from.to_str());
}
TRY_STATUS(chain->validate());
TRY_STATUS(chain->validate(cancellation_token_));
return std::move(chain);
}
@ -155,6 +169,8 @@ void LastBlock::update_state(block::BlockProofChain& chain) {
// Update state_
bool is_changed = false;
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) {
is_changed |= update_mc_last_key_block(chain.key_blkid);
}
@ -193,10 +209,10 @@ void LastBlock::on_block_proof(
if (chain->complete) {
VLOG(last_block) << "get_last_block: done\n" << get_last_block_stats_;
get_last_block_state_ = QueryState::Done;
sync_loop();
} else {
do_get_last_block();
}
sync_loop();
}
void LastBlock::on_init_block_proof(
@ -209,6 +225,7 @@ void LastBlock::on_init_block_proof(
check_init_block_state_ = QueryState::Empty;
VLOG(last_block) << "check_init_block: error " << r_chain.error();
on_sync_error(r_chain.move_as_error_suffix("(during check init block)"));
sync_loop();
return;
}
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)) {
save_state();
}
sync_loop();
} else {
do_check_init_block(chain->to, to);
}
sync_loop();
}
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");
// last block is not validated! Do not update it
get_mc_info_state_ = QueryState::Done;
max_seqno_ = td::max(max_seqno_, (unsigned)info->last_->seqno_);
VLOG(last_block) << "get_masterchain_info: done";
} else {
get_mc_info_state_ = QueryState::Empty;
@ -334,6 +352,9 @@ void LastBlock::on_sync_ok() {
}
void LastBlock::on_sync_error(td::Status status) {
VLOG(last_block) << "sync: error " << status;
if (cancellation_token_) {
status = TonlibError::Cancelled();
}
for (auto& promise : promises_) {
promise.set_error(status.clone());
}
@ -348,4 +369,32 @@ void LastBlock::on_fatal_error(td::Status status) {
bool LastBlock::has_fatal_error() const {
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

View file

@ -22,6 +22,7 @@
#include "tonlib/Config.h"
#include "tonlib/ExtClient.h"
#include "td/utils/CancellationToken.h"
#include "td/utils/tl_helpers.h"
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 {
public:
class Callback {
@ -139,16 +154,19 @@ class LastBlock : public td::actor::Actor {
virtual ~Callback() {
}
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);
private:
td::unique_ptr<Callback> callback_;
ExtClient client_;
LastBlockState state_;
Config config_;
td::unique_ptr<Callback> callback_;
td::CancellationToken cancellation_token_;
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 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
struct Stats {
td::Timer total_sync_;
@ -209,6 +232,10 @@ class LastBlock : public td::actor::Actor {
void on_fatal_error(td::Status status);
bool has_fatal_error() const;
LastBlockSyncState get_sync_state();
void update_sync_state();
void sync_loop();
void tear_down() override;
};
} // namespace tonlib

View file

@ -166,6 +166,9 @@ class GetTransactionHistory : public td::actor::Actor {
hash_),
[self = this](auto r_transactions) { self->with_transactions(std::move(r_transactions)); });
}
void hangup() override {
check(TonlibError::Cancelled());
}
};
class GetRawAccountState : public td::actor::Actor {
@ -277,6 +280,9 @@ class GetRawAccountState : public td::actor::Actor {
stop();
}
}
void hangup() override {
check(TonlibError::Cancelled());
}
};
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;
void TonlibClient::hangup() {
source_.cancel();
is_closing_ = true;
ref_cnt_--;
raw_client_ = {};
@ -300,7 +307,7 @@ ExtClientRef TonlibClient::get_client_ref() {
}
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() {
@ -342,8 +349,28 @@ void TonlibClient::init_ext_client() {
}
void TonlibClient::update_last_block_state(LastBlockState state, td::uint32 config_generation) {
if (config_generation == config_generation_) {
last_block_storage_.save_state(blockchain_name_, state);
if (config_generation != config_generation_) {
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 {
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:
td::actor::ActorShared<TonlibClient> client_;
@ -379,19 +409,23 @@ void TonlibClient::init_last_block() {
state = r_state.move_as_ok();
}
raw_last_block_ =
td::actor::create_actor<LastBlock>("LastBlock", get_client_ref(), std::move(state), config_,
td::make_unique<Callback>(td::actor::actor_shared(this), config_generation_));
raw_last_block_ = td::actor::create_actor<LastBlock>(
td::actor::ActorOptions().with_name("LastBlock").with_poll(false), get_client_ref(), std::move(state), config_,
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) {
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) {
callback_->on_error(id, tonlib_api::move_object_as<tonlib_api::error>(response));
return;
}
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) {
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) {
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;
if (r_result.is_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) {
CHECK(state_ != State::Closed);
state_ = State::Closed;
source_.cancel();
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
return td::Status::OK();
}
@ -1257,6 +1294,9 @@ class GenericSendGrams : public TonlibQueryActor {
void start_up() override {
check(do_start_up());
}
void hangup() override {
check(TonlibError::Cancelled());
}
td::Status do_start_up() {
if (!send_grams_.destination_) {
@ -1426,6 +1466,15 @@ td::Status TonlibClient::do_request(tonlib_api::generic_sendGrams& request,
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) {
TRY_RESULT_PREFIX(key_bytes, block::PublicKey::from_bytes(bytes), TonlibError::Internal());
return key_bytes;

View file

@ -29,6 +29,8 @@
#include "td/actor/actor.h"
#include "td/utils/CancellationToken.h"
#include <map>
namespace tonlib {
@ -66,6 +68,8 @@ class TonlibClient : public td::actor::Actor {
td::actor::ActorOwn<LastBlock> raw_last_block_;
ExtClient client_;
td::CancellationTokenSource source_;
std::map<td::int64, td::actor::ActorOwn<>> actors_;
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_sync_state(LastBlockSyncState state, td::uint32 config_generation);
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_uninited_request(td::int32 id);
template <class T>
@ -159,6 +165,8 @@ class TonlibClient : public td::actor::Actor {
td::Status do_request(tonlib_api::generic_sendGrams& request,
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::exportKey& request,
td::Promise<object_ptr<tonlib_api::exportedKey>>&& promise);

View file

@ -94,7 +94,7 @@ class TonlibCli : public td::actor::Actor {
td::actor::ActorShared<TonlibCli> id_;
};
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();
@ -144,6 +144,9 @@ class TonlibCli : public td::actor::Actor {
void hangup_shared() override {
CHECK(ref_cnt_ > 0);
ref_cnt_--;
if (get_link_token() == 1) {
io_.reset();
}
try_stop();
}
void try_stop() {
@ -221,7 +224,6 @@ class TonlibCli : public td::actor::Actor {
generate_key();
} else if (cmd == "exit") {
is_closing_ = true;
io_.reset();
client_.reset();
ref_cnt_--;
try_stop();
@ -263,9 +265,20 @@ class TonlibCli : public td::actor::Actor {
set_bounceable(addr, to_bool(bounceable, true));
} else if (cmd == "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() {
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";