diff --git a/crypto/fift/SourceLookup.h b/crypto/fift/SourceLookup.h index 33ee71d4..7d51396c 100644 --- a/crypto/fift/SourceLookup.h +++ b/crypto/fift/SourceLookup.h @@ -79,7 +79,7 @@ class SourceLookup { if (os_time_) { return os_time_->now(); } - return static_cast(td::Time::now()); + return static_cast(td::Clocks::system()); } protected: diff --git a/crypto/fift/words.cpp b/crypto/fift/words.cpp index ea4744c8..0b97ece9 100644 --- a/crypto/fift/words.cpp +++ b/crypto/fift/words.cpp @@ -942,7 +942,9 @@ void interpret_fetch(vm::Stack& stack, int mode) { auto n = stack.pop_smallint_range(256 + (mode & 1)); auto cs = stack.pop_cellslice(); if (!cs->have(n)) { - stack.push(std::move(cs)); + if (mode & 2) { + stack.push(std::move(cs)); + } stack.push_bool(false); if (!(mode & 4)) { throw IntError{"end of data while reading integer from cell"}; diff --git a/crypto/func/codegen.cpp b/crypto/func/codegen.cpp index 0efea4d6..7e0d873f 100644 --- a/crypto/func/codegen.cpp +++ b/crypto/func/codegen.cpp @@ -628,7 +628,7 @@ bool Op::generate_code_step(Stack& stack) { stack.opt_show(); StackLayout layout1 = stack.vars(); bool next_empty = next->is_empty(); - stack.o << (next_empty ? "WHILEEND:<{" : "WHILE:<{"); + stack.o << "WHILE:<{"; stack.o.indent(); stack.forget_const(); block0->generate_code_all(stack); @@ -638,7 +638,7 @@ bool Op::generate_code_step(Stack& stack) { stack.modified(); stack.o.undent(); Stack stack_copy{stack}; - stack.o << (next_empty ? "}>" : "}>DO<{"); + stack.o << (next_empty ? "}>DO:" : "}>DO<{"); if (!next_empty) { stack.o.indent(); } diff --git a/crypto/smartcont/highload-wallet-v2.fif b/crypto/smartcont/highload-wallet-v2.fif new file mode 100644 index 00000000..76f06ed5 --- /dev/null +++ b/crypto/smartcont/highload-wallet-v2.fif @@ -0,0 +1,69 @@ +#!/usr/bin/env fift -s +"TonUtil.fif" include + +{ ."usage: " @' $0 type ." []" cr + ."Creates a request with up to 254 orders loaded from to high-load v2 (sub)wallet created by new-highload-v2-wallet.fif, with private key loaded from file .pk " + ."and address from .addr, and saves it into .boc ('wallet-query.boc' by default)" cr + ." is a text file with lines `SEND `" cr 1 halt +} : usage +$# dup 3 < swap 4 > or ' usage if + +$1 =: file-base +$2 parse-int dup 32 fits ' usage ifnot =: subwallet-id // parse subwallet-id +{ subwallet-id (.) $+ } : +subwallet +$3 =: order-file +def? $4 { @' $4 } { "wallet-query" } cond constant savefile +3 constant send-mode // mode for SENDRAWMSG: +1 - sender pays fees, +2 - ignore errors +60 constant timeout // external message expires in 60 seconds + +file-base +subwallet +".addr" load-address +2dup 2constant wallet_addr +."Source wallet address = " 2dup .addr cr 6 .Addr cr +file-base +".pk" load-keypair nip constant wallet_pk + +variable orders dictnew orders ! +variable order# order# 0! +// c -- +{ = abort"more than 254 orders" + orders @ 16 udict!+ not abort"cannot add order to dictionary" + orders ! order# 1+! +} : add-order +// b body -- b' +{ tuck +} : create-int-msg +// ng wc addr bnc -- +{ ."Transferring " 3 roll .GR ."to account " + -rot 2dup 4 pick 7 + .Addr ." = " .addr ." bounce=" . cr +} : .transfer +// addr$ ng -- c +{ swap parse-smc-addr // ng wc addr bnc + 2over 2over .transfer + create-int-msg +} : create-simple-transfer +// c m -- c' +{ } : create-order + +// addr$ ng -- +{ create-simple-transfer send-mode create-order add-order } : send +{ bl word bl word $>GR send } : SEND + +// parse order file +order-file include + +// create external message +now timeout + 32 << hashu 32 1<<1- and + =: query_id + +dup ."signing message: " +dup ."resulting external message: " B dup Bx. cr +."Query_id is " query_id dup . ."= 0x" X. cr +savefile +".boc" tuck B>file +."(Saved to file " type .")" cr diff --git a/crypto/smartcont/new-highload-wallet-v2.fif b/crypto/smartcont/new-highload-wallet-v2.fif new file mode 100644 index 00000000..df386cc7 --- /dev/null +++ b/crypto/smartcont/new-highload-wallet-v2.fif @@ -0,0 +1,47 @@ +#!/usr/bin/env fift -s +"TonUtil.fif" include +"Asm.fif" include + +{ ."usage: " @' $0 type ." []" cr + ."Creates a new v2 high-load wallet in the specified workchain, with the controlling private key saved to or loaded from .pk " + ."('new-wallet.pk' by default)" cr + ." is the 32-bit identifier of this subwallet among all controlled by the same private key" cr 1 halt +} : usage +$# 2- -2 and ' usage if + +$1 parse-workchain-id =: wc // set workchain id from command line argument +$2 parse-int dup =: subwallet-id // parse subwallet-id +32 fits ' usage ifnot +{ subwallet-id (.) $+ } : +subwallet +def? $3 { @' $3 } { "new-wallet" } cond constant file-base +65536 constant timeout // init query times out in 65536 seconds + +."Creating new v2 high-load wallet in workchain " wc . +."with subwallet id " subwallet-id . cr + +// Create new high-load wallet; source code included from `highload-wallet-v2-code.fif` +"highload-wallet-v2-code.fif" include +// code + // data +null // no libraries + // create StateInit +dup ."StateInit: " +dup ."signing message: " +dup ."External message for initialization is " B dup Bx. cr +file-base +subwallet +"-query.boc" tuck B>file +."(Saved wallet creating query to file " type .")" cr diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 89827f7f..65593139 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -466,6 +466,7 @@ db.lt.status.value total_shards:int = db.lt.status.Value; validator.groupMember public_key_hash:int256 adnl:int256 weight:long = engine.validator.GroupMember; validator.group workchain:int shard:long catchain_seqno:int config_hash:int256 members:(vector validator.groupMember) = validator.Group; +validator.groupEx workchain:int shard:long vertical_seqno:int catchain_seqno:int config_hash:int256 members:(vector validator.groupMember) = validator.Group; ---functions--- diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index 6959d9a3..75381456 100644 Binary files a/tl/generate/scheme/ton_api.tlo and b/tl/generate/scheme/ton_api.tlo differ diff --git a/validator/fabric.h b/validator/fabric.h index 69f8fd3a..e7709f8d 100644 --- a/validator/fabric.h +++ b/validator/fabric.h @@ -27,6 +27,8 @@ namespace validator { td::actor::ActorOwn create_db_actor(td::actor::ActorId manager, std::string db_root_, td::uint32 depth); +td::actor::ActorOwn create_liteserver_cache_actor(td::actor::ActorId manager, + std::string db_root); td::Result> create_block(BlockIdExt block_id, td::BufferSlice data); td::Result> create_block(ReceivedBlock data); @@ -71,7 +73,7 @@ void run_collate_query(ShardIdFull shard, td::uint32 min_ts, const BlockIdExt& m td::actor::ActorId manager, td::Timestamp timeout, td::Promise promise); void run_liteserver_query(td::BufferSlice data, td::actor::ActorId manager, - td::Promise promise); + td::actor::ActorId cache, td::Promise promise); void run_validate_shard_block_description(td::BufferSlice data, BlockHandle masterchain_block, td::Ref masterchain_state, td::actor::ActorId manager, td::Timestamp timeout, diff --git a/validator/impl/fabric.cpp b/validator/impl/fabric.cpp index 5ad2a774..a037e122 100644 --- a/validator/impl/fabric.cpp +++ b/validator/impl/fabric.cpp @@ -43,6 +43,11 @@ td::actor::ActorOwn create_db_actor(td::actor::ActorId man return td::actor::create_actor("db", manager, db_root_, depth); } +td::actor::ActorOwn create_liteserver_cache_actor(td::actor::ActorId manager, + std::string db_root) { + return td::actor::create_actor("cache"); +} + td::Result> create_block(BlockIdExt block_id, td::BufferSlice data) { auto res = BlockQ::create(block_id, std::move(data)); if (res.is_error()) { @@ -196,7 +201,7 @@ void run_collate_query(ShardIdFull shard, td::uint32 min_ts, const BlockIdExt& m } void run_liteserver_query(td::BufferSlice data, td::actor::ActorId manager, - td::Promise promise) { + td::actor::ActorId cache, td::Promise promise) { LiteQuery::run_query(std::move(data), std::move(manager), std::move(promise)); } diff --git a/validator/interfaces/liteserver.h b/validator/interfaces/liteserver.h new file mode 100644 index 00000000..ff1bf165 --- /dev/null +++ b/validator/interfaces/liteserver.h @@ -0,0 +1,16 @@ +#pragma once + +#include "td/actor/actor.h" + +namespace ton { + +namespace validator { + +class LiteServerCache : public td::actor::Actor { + public: + virtual ~LiteServerCache() = default; +}; + +} // namespace validator + +} // namespace ton diff --git a/validator/interfaces/validator-manager.h b/validator/interfaces/validator-manager.h index a3260ab0..aaf40f49 100644 --- a/validator/interfaces/validator-manager.h +++ b/validator/interfaces/validator-manager.h @@ -26,6 +26,7 @@ #include "shard-block.h" #include "message-queue.h" #include "validator/validator.h" +#include "liteserver.h" namespace ton { @@ -147,7 +148,7 @@ class ValidatorManager : public ValidatorManagerInterface { virtual void allow_block_info_gc(BlockIdExt block_id, td::Promise promise) = 0; virtual void check_is_hardfork(BlockIdExt block_id, td::Promise promise) = 0; - virtual void get_vertical_height(BlockSeqno seqno, td::Promise promise) = 0; + virtual void get_vertical_seqno(BlockSeqno seqno, td::Promise promise) = 0; virtual void update_last_known_key_block(BlockHandle handle, bool send_request) = 0; virtual void update_gc_block_handle(BlockHandle handle, td::Promise promise) = 0; diff --git a/validator/manager-disk.hpp b/validator/manager-disk.hpp index 750a823f..c5fa38de 100644 --- a/validator/manager-disk.hpp +++ b/validator/manager-disk.hpp @@ -279,8 +279,8 @@ class ValidatorManagerImpl : public ValidatorManager { CHECK(block_id.is_masterchain()); promise.set_result(opts_->is_hardfork(block_id)); } - void get_vertical_height(BlockSeqno seqno, td::Promise promise) override { - promise.set_result(opts_->get_vertical_height(seqno)); + void get_vertical_seqno(BlockSeqno seqno, td::Promise promise) override { + promise.set_result(opts_->get_vertical_seqno(seqno)); } void run_ext_query(td::BufferSlice data, td::Promise promise) override { UNREACHABLE(); diff --git a/validator/manager.cpp b/validator/manager.cpp index 142107a4..2d5b1175 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -73,7 +73,8 @@ void ValidatorManagerImpl::validate_block_is_next_proof(BlockIdExt prev_block_id promise.set_value(td::Unit()); }); - run_check_proof_query(next_block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P)); + run_check_proof_query(next_block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P), + opts_->is_hardfork(next_block_id)); } void ValidatorManagerImpl::validate_block_proof(BlockIdExt block_id, td::BufferSlice proof, @@ -91,7 +92,8 @@ void ValidatorManagerImpl::validate_block_proof(BlockIdExt block_id, td::BufferS promise.set_value(td::Unit()); } }); - run_check_proof_query(block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P)); + run_check_proof_query(block_id, pp.move_as_ok(), actor_id(this), td::Timestamp::in(2.0), std::move(P), + opts_->is_hardfork(block_id)); } void ValidatorManagerImpl::validate_block_proof_link(BlockIdExt block_id, td::BufferSlice proof, @@ -129,28 +131,30 @@ void ValidatorManagerImpl::validate_block_proof_rel(BlockIdExt block_id, BlockId }); if (rel_block_id.id.seqno == 0) { - auto P = td::PromiseCreator::lambda([block_id, SelfId = actor_id(this), proof = pp.move_as_ok(), - promise = std::move(Q)](td::Result> R) mutable { - if (R.is_error()) { - promise.set_error(R.move_as_error()); - } else { - auto s = td::Ref{R.move_as_ok()}; + auto P = td::PromiseCreator::lambda( + [block_id, SelfId = actor_id(this), proof = pp.move_as_ok(), promise = std::move(Q), + skip_sig = opts_->is_hardfork(block_id)](td::Result> R) mutable { + if (R.is_error()) { + promise.set_error(R.move_as_error()); + } else { + auto s = td::Ref{R.move_as_ok()}; - run_check_proof_query(block_id, std::move(proof), SelfId, td::Timestamp::in(2.0), std::move(promise), - std::move(s)); - } - }); + run_check_proof_query(block_id, std::move(proof), SelfId, td::Timestamp::in(2.0), std::move(promise), + std::move(s), skip_sig); + } + }); get_shard_state_from_db_short(rel_block_id, std::move(P)); } else { - auto P = td::PromiseCreator::lambda([block_id, SelfId = actor_id(this), proof = pp.move_as_ok(), - promise = std::move(Q)](td::Result> R) mutable { - if (R.is_error()) { - promise.set_error(R.move_as_error()); - } else { - run_check_proof_query(block_id, std::move(proof), SelfId, td::Timestamp::in(2.0), std::move(promise), - R.move_as_ok()); - } - }); + auto P = + td::PromiseCreator::lambda([block_id, SelfId = actor_id(this), proof = pp.move_as_ok(), promise = std::move(Q), + skip_sig = opts_->is_hardfork(block_id)](td::Result> R) mutable { + if (R.is_error()) { + promise.set_error(R.move_as_error()); + } else { + run_check_proof_query(block_id, std::move(proof), SelfId, td::Timestamp::in(2.0), std::move(promise), + R.move_as_ok(), skip_sig); + } + }); get_block_proof_link_from_db_short(rel_block_id, std::move(P)); } } @@ -464,7 +468,7 @@ void ValidatorManagerImpl::run_ext_query(td::BufferSlice data, td::Promiseget_filedb_depth()); + lite_server_cache_ = create_liteserver_cache_actor(actor_id(this), db_root_); token_manager_ = td::actor::create_actor("tokenmanager"); auto Q = @@ -1583,13 +1588,19 @@ ValidatorSessionId ValidatorManagerImpl::get_validator_set_id(ShardIdFull shard, td::Bits256 opts_hash) { std::vector> vec; auto v = val_set->export_vector(); + auto vert_seqno = opts_->get_maximal_vertical_seqno(); for (auto &n : v) { auto pub_key = PublicKey{pubkeys::Ed25519{n.key}}; vec.push_back( create_tl_object(pub_key.compute_short_id().bits256_value(), n.addr, n.weight)); } - return create_hash_tl_object(shard.workchain, shard.shard, val_set->get_catchain_seqno(), - opts_hash, std::move(vec)); + if (vert_seqno == 0) { + return create_hash_tl_object(shard.workchain, shard.shard, val_set->get_catchain_seqno(), + opts_hash, std::move(vec)); + } else { + return create_hash_tl_object(shard.workchain, shard.shard, vert_seqno, + val_set->get_catchain_seqno(), opts_hash, std::move(vec)); + } } td::actor::ActorOwn ValidatorManagerImpl::create_validator_group( @@ -1975,8 +1986,6 @@ void ValidatorManagerImpl::send_peek_key_block_request() { void ValidatorManagerImpl::prepare_stats(td::Promise>> promise) { auto merger = StatsMerger::create(std::move(promise)); - td::actor::send_closure(db_, &Db::prepare_stats, merger.make_promise("db.")); - std::vector> vec; vec.emplace_back("unixtime", td::to_string(static_cast(td::Clocks::system()))); if (last_masterchain_block_handle_) { @@ -2004,6 +2013,8 @@ void ValidatorManagerImpl::prepare_stats(td::Promise ValidatorManagerFactory::create( diff --git a/validator/manager.hpp b/validator/manager.hpp index 2b88696a..082432fa 100644 --- a/validator/manager.hpp +++ b/validator/manager.hpp @@ -432,8 +432,8 @@ class ValidatorManagerImpl : public ValidatorManager { CHECK(block_id.is_masterchain()); promise.set_result(opts_->is_hardfork(block_id)); } - void get_vertical_height(BlockSeqno seqno, td::Promise promise) override { - promise.set_result(opts_->get_vertical_height(seqno)); + void get_vertical_seqno(BlockSeqno seqno, td::Promise promise) override { + promise.set_result(opts_->get_vertical_seqno(seqno)); } void add_shard_block_description(td::Ref desc); @@ -522,6 +522,7 @@ class ValidatorManagerImpl : public ValidatorManager { private: td::actor::ActorOwn lite_server_; + td::actor::ActorOwn lite_server_cache_; std::vector pending_ext_ports_; std::vector pending_ext_ids_; diff --git a/validator/validator-options.hpp b/validator/validator-options.hpp index 68711710..21bf79cb 100644 --- a/validator/validator-options.hpp +++ b/validator/validator-options.hpp @@ -67,7 +67,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { } return false; } - td::uint32 get_vertical_height(BlockSeqno seqno) const override { + td::uint32 get_vertical_seqno(BlockSeqno seqno) const override { size_t best = 0; for (size_t i = 0; i < hardforks_.size(); i++) { if (seqno >= hardforks_[i].seqno()) { @@ -76,6 +76,12 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { } return static_cast(best); } + td::uint32 get_maximal_vertical_seqno() const override { + return td::narrow_cast(hardforks_.size()); + } + td::uint32 get_last_fork_masterchain_seqno() const override { + return hardforks_.size() ? hardforks_.rbegin()->seqno() : 0; + } td::uint32 get_filedb_depth() const override { return db_depth_; } diff --git a/validator/validator.h b/validator/validator.h index 70b01e63..2e80c135 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -57,7 +57,9 @@ struct ValidatorManagerOptions : public td::CntObject { virtual td::ClocksBase::Duration key_proof_ttl() const = 0; virtual bool initial_sync_disabled() const = 0; virtual bool is_hardfork(BlockIdExt block_id) const = 0; - virtual td::uint32 get_vertical_height(BlockSeqno seqno) const = 0; + virtual td::uint32 get_vertical_seqno(BlockSeqno seqno) const = 0; + virtual td::uint32 get_maximal_vertical_seqno() const = 0; + virtual td::uint32 get_last_fork_masterchain_seqno() const = 0; virtual td::uint32 get_filedb_depth() const = 0; virtual td::uint32 key_block_utime_step() const { return 86400;