mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-12 11:12:16 +00:00
updated liteserver
- new methods for liteserver/liteclient - added ADNL/DHT client-only work mode - fixed crash in ADNL
This commit is contained in:
parent
acf16718e6
commit
53ec9684bd
70 changed files with 816 additions and 322 deletions
2
GPLv2
2
GPLv2
|
@ -23,5 +23,5 @@
|
|||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
|
|
2
LGPLv2
2
LGPLv2
|
@ -14,5 +14,5 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
|
|
|
@ -155,6 +155,16 @@ td::Result<AdnlAddressList> AdnlAddressList::create(const tl_object_ptr<ton_api:
|
|||
return A;
|
||||
}
|
||||
|
||||
td::Status AdnlAddressList::add_udp_address(td::IPAddress addr) {
|
||||
if (addr.is_ipv4()) {
|
||||
auto r = td::make_ref<AdnlAddressUdp>(addr.get_ipv4(), static_cast<td::uint16>(addr.get_port()));
|
||||
addrs_.push_back(std::move(r));
|
||||
return td::Status::OK();
|
||||
} else {
|
||||
return td::Status::Error(ErrorCode::protoviolation, "only works with ipv4");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -88,6 +88,7 @@ class AdnlAddressList {
|
|||
void add_addr(AdnlAddress addr) {
|
||||
addrs_.push_back(addr);
|
||||
}
|
||||
void update(td::IPAddress addr);
|
||||
bool public_only() const;
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(addrs_.size());
|
||||
|
@ -98,6 +99,7 @@ class AdnlAddressList {
|
|||
}
|
||||
|
||||
static td::Result<AdnlAddressList> create(const tl_object_ptr<ton_api::adnl_addressList> &addr_list);
|
||||
td::Status add_udp_address(td::IPAddress addr);
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
|
|
@ -111,13 +111,15 @@ void AdnlChannelImpl::send_message(td::uint32 priority, td::actor::ActorId<AdnlN
|
|||
td::actor::send_closure(conn, &AdnlNetworkConnection::send, local_id_, peer_id_, priority, std::move(B));
|
||||
}
|
||||
|
||||
void AdnlChannelImpl::receive(td::BufferSlice data) {
|
||||
void AdnlChannelImpl::receive(td::IPAddress addr, td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[peer = peer_pair_, channel_id = channel_in_id_, id = print_id()](td::Result<AdnlPacket> R) {
|
||||
[peer = peer_pair_, channel_id = channel_in_id_, addr, id = print_id()](td::Result<AdnlPacket> R) {
|
||||
if (R.is_error()) {
|
||||
VLOG(ADNL_WARNING) << id << ": dropping IN message: can not decrypt: " << R.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(peer, &AdnlPeerPair::receive_packet_from_channel, channel_id, R.move_as_ok());
|
||||
auto packet = R.move_as_ok();
|
||||
packet.set_remote_addr(addr);
|
||||
td::actor::send_closure(peer, &AdnlPeerPair::receive_packet_from_channel, channel_id, std::move(packet));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class AdnlChannel : public td::actor::Actor {
|
|||
AdnlNodeIdShort local_id, AdnlNodeIdShort peer_id,
|
||||
AdnlChannelIdShort &out_id, AdnlChannelIdShort &in_id,
|
||||
td::actor::ActorId<AdnlPeerPair> peer_pair);
|
||||
virtual void receive(td::BufferSlice data) = 0;
|
||||
virtual void receive(td::IPAddress addr, td::BufferSlice data) = 0;
|
||||
virtual void send_message(td::uint32 priority, td::actor::ActorId<AdnlNetworkConnection> conn,
|
||||
td::BufferSlice data) = 0;
|
||||
virtual ~AdnlChannel() = default;
|
||||
|
|
|
@ -33,7 +33,7 @@ class AdnlChannelImpl : public AdnlChannel {
|
|||
AdnlChannelIdShort in_id, AdnlChannelIdShort out_id, std::unique_ptr<Encryptor> encryptor,
|
||||
std::unique_ptr<Decryptor> decryptor);
|
||||
void decrypt(td::BufferSlice data, td::Promise<AdnlPacket> promise);
|
||||
void receive(td::BufferSlice data) override;
|
||||
void receive(td::IPAddress addr, td::BufferSlice data) override;
|
||||
void send_message(td::uint32 priority, td::actor::ActorId<AdnlNetworkConnection> conn, td::BufferSlice data) override;
|
||||
|
||||
struct AdnlChannelPrintId {
|
||||
|
|
|
@ -40,13 +40,15 @@ AdnlAddressList AdnlLocalId::get_addr_list() const {
|
|||
return addr_list_;
|
||||
}
|
||||
|
||||
void AdnlLocalId::receive(td::BufferSlice data) {
|
||||
void AdnlLocalId::receive(td::IPAddress addr, td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[peer_table = peer_table_, dst = short_id_, id = print_id()](td::Result<AdnlPacket> R) {
|
||||
[peer_table = peer_table_, dst = short_id_, addr, id = print_id()](td::Result<AdnlPacket> R) {
|
||||
if (R.is_error()) {
|
||||
VLOG(ADNL_WARNING) << id << ": dropping IN message: cannot decrypt: " << R.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(peer_table, &AdnlPeerTable::receive_decrypted_packet, dst, R.move_as_ok());
|
||||
auto packet = R.move_as_ok();
|
||||
packet.set_remote_addr(addr);
|
||||
td::actor::send_closure(peer_table, &AdnlPeerTable::receive_decrypted_packet, dst, std::move(packet));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -117,7 +119,7 @@ void AdnlLocalId::update_address_list(AdnlAddressList addr_list) {
|
|||
}
|
||||
|
||||
void AdnlLocalId::publish_address_list() {
|
||||
if (dht_node_.empty() || addr_list_.empty()) {
|
||||
if (dht_node_.empty() || addr_list_.empty() || addr_list_.size() == 0) {
|
||||
VLOG(ADNL_NOTICE) << this << ": skipping public addr list, because localid (or dht node) not fully initialized";
|
||||
return;
|
||||
}
|
||||
|
@ -178,7 +180,8 @@ AdnlLocalId::AdnlLocalId(AdnlNodeIdFull id, AdnlAddressList addr_list, td::actor
|
|||
id_ = std::move(id);
|
||||
short_id_ = id_.compute_short_id();
|
||||
addr_list_ = std::move(addr_list);
|
||||
if (addr_list_.addrs().size() > 0) {
|
||||
if (!addr_list_.empty()) {
|
||||
addr_list_.set_reinit_date(Adnl::adnl_start_time());
|
||||
addr_list_.set_version(static_cast<td::int32>(td::Clocks::system()));
|
||||
}
|
||||
peer_table_ = peer_table;
|
||||
|
|
|
@ -54,7 +54,7 @@ class AdnlLocalId : public td::actor::Actor {
|
|||
void decrypt_message(td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
||||
void deliver(AdnlNodeIdShort src, td::BufferSlice data);
|
||||
void deliver_query(AdnlNodeIdShort src, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
|
||||
void receive(td::BufferSlice data);
|
||||
void receive(td::IPAddress addr, td::BufferSlice data);
|
||||
|
||||
void subscribe(std::string prefix, std::unique_ptr<AdnlPeerTable::Callback> callback);
|
||||
void unsubscribe(std::string prefix);
|
||||
|
|
|
@ -132,6 +132,9 @@ class AdnlPacket {
|
|||
auto signature() const {
|
||||
return signature_.clone();
|
||||
}
|
||||
auto remote_addr() const {
|
||||
return remote_addr_;
|
||||
}
|
||||
|
||||
void init_random();
|
||||
|
||||
|
@ -188,6 +191,10 @@ class AdnlPacket {
|
|||
flags_ |= Flags::f_reinit_date;
|
||||
}
|
||||
|
||||
void set_remote_addr(td::IPAddress addr) {
|
||||
remote_addr_ = addr;
|
||||
}
|
||||
|
||||
private:
|
||||
td::BufferSlice rand1_;
|
||||
td::uint32 flags_{0};
|
||||
|
@ -204,6 +211,8 @@ class AdnlPacket {
|
|||
td::int32 dst_reinit_date_{0};
|
||||
td::BufferSlice signature_;
|
||||
td::BufferSlice rand2_;
|
||||
|
||||
td::IPAddress remote_addr_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
|
|
@ -49,7 +49,7 @@ td::actor::ActorOwn<Adnl> Adnl::create(std::string db, td::actor::ActorId<keyrin
|
|||
return td::actor::ActorOwn<Adnl>(td::actor::create_actor<AdnlPeerTableImpl>("PeerTable", db, keyring));
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::receive_packet(td::BufferSlice data) {
|
||||
void AdnlPeerTableImpl::receive_packet(td::IPAddress addr, td::BufferSlice data) {
|
||||
if (data.size() < 32) {
|
||||
VLOG(ADNL_WARNING) << this << ": dropping IN message [?->?]: message too short: len=" << data.size();
|
||||
return;
|
||||
|
@ -60,14 +60,14 @@ void AdnlPeerTableImpl::receive_packet(td::BufferSlice data) {
|
|||
|
||||
auto it = local_ids_own_.find(dst);
|
||||
if (it != local_ids_own_.end()) {
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::receive, std::move(data));
|
||||
td::actor::send_closure(it->second, &AdnlLocalId::receive, addr, std::move(data));
|
||||
return;
|
||||
}
|
||||
|
||||
AdnlChannelIdShort dst_chan_id{dst.pubkey_hash()};
|
||||
auto it2 = channels_.find(dst_chan_id);
|
||||
if (it2 != channels_.end()) {
|
||||
td::actor::send_closure(it2->second, &AdnlChannel::receive, std::move(data));
|
||||
td::actor::send_closure(it2->second, &AdnlChannel::receive, addr, std::move(data));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ void AdnlPeerTableImpl::register_network_manager(td::actor::ActorId<AdnlNetworkM
|
|||
class Cb : public AdnlNetworkManager::Callback {
|
||||
public:
|
||||
void receive_packet(td::IPAddress addr, td::BufferSlice data) override {
|
||||
td::actor::send_closure(id_, &AdnlPeerTableImpl::receive_packet, std::move(data));
|
||||
td::actor::send_closure(id_, &AdnlPeerTableImpl::receive_packet, addr, std::move(data));
|
||||
}
|
||||
Cb(td::actor::ActorId<AdnlPeerTableImpl> id) : id_(id) {
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ class AdnlPeerTable : public Adnl {
|
|||
|
||||
virtual void answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id, td::BufferSlice data) = 0;
|
||||
|
||||
virtual void receive_packet(td::BufferSlice data) = 0;
|
||||
virtual void receive_packet(td::IPAddress addr, td::BufferSlice data) = 0;
|
||||
virtual void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) = 0;
|
||||
virtual void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message) = 0;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
|
|||
void add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) override;
|
||||
void add_static_nodes_from_config(AdnlNodesList nodes) override;
|
||||
|
||||
void receive_packet(td::BufferSlice data) override;
|
||||
void receive_packet(td::IPAddress addr, td::BufferSlice data) override;
|
||||
void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket data) override;
|
||||
void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message) override;
|
||||
void send_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override {
|
||||
|
|
|
@ -131,7 +131,12 @@ void AdnlPeerPairImpl::receive_packet_checked(AdnlPacket packet) {
|
|||
}
|
||||
if (packet.dst_reinit_date() > 0 && packet.dst_reinit_date() < d) {
|
||||
if (!packet.addr_list().empty()) {
|
||||
update_addr_list(packet.addr_list());
|
||||
auto addr_list = packet.addr_list();
|
||||
if (packet.remote_addr().is_valid() && addr_list.size() == 0) {
|
||||
VLOG(ADNL_DEBUG) << "adding implicit address " << packet.remote_addr();
|
||||
addr_list.add_udp_address(packet.remote_addr());
|
||||
}
|
||||
update_addr_list(std::move(addr_list));
|
||||
}
|
||||
if (!packet.priority_addr_list().empty()) {
|
||||
update_addr_list(packet.priority_addr_list());
|
||||
|
@ -174,7 +179,12 @@ void AdnlPeerPairImpl::receive_packet_checked(AdnlPacket packet) {
|
|||
}
|
||||
|
||||
if (!packet.addr_list().empty()) {
|
||||
update_addr_list(packet.addr_list());
|
||||
auto addr_list = packet.addr_list();
|
||||
if (packet.remote_addr().is_valid() && addr_list.size() == 0) {
|
||||
VLOG(ADNL_DEBUG) << "adding implicit address " << packet.remote_addr();
|
||||
addr_list.add_udp_address(packet.remote_addr());
|
||||
}
|
||||
update_addr_list(std::move(addr_list));
|
||||
}
|
||||
if (!packet.priority_addr_list().empty()) {
|
||||
update_addr_list(packet.priority_addr_list());
|
||||
|
@ -642,7 +652,7 @@ void AdnlPeerPairImpl::update_addr_list(AdnlAddressList addr_list) {
|
|||
if (addr_list.empty()) {
|
||||
return;
|
||||
}
|
||||
CHECK(addr_list.size() > 0);
|
||||
//CHECK(addr_list.size() > 0);
|
||||
|
||||
if (addr_list.reinit_date() > td::Clocks::system() + 60) {
|
||||
VLOG(ADNL_WARNING) << "dropping addr list with too new reinit date";
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "blockchain-explorer-http.hpp"
|
||||
#include "block/block-db.h"
|
||||
|
@ -36,6 +36,8 @@
|
|||
#include "block/mc-config.h"
|
||||
#include "ton/ton-shard.h"
|
||||
|
||||
bool local_scripts{false};
|
||||
|
||||
HttpAnswer& HttpAnswer::operator<<(AddressCell addr_c) {
|
||||
ton::WorkchainId wc;
|
||||
ton::StdSmcAddress addr;
|
||||
|
@ -425,7 +427,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
|
|||
|
||||
HttpAnswer& HttpAnswer::operator<<(BlockHeaderCell head_c) {
|
||||
*this << "<div>";
|
||||
vm::CellSlice cs{vm::NoVm{}, head_c.root};
|
||||
vm::CellSlice cs{vm::NoVm(), head_c.root};
|
||||
auto block_id = head_c.block_id;
|
||||
try {
|
||||
auto virt_root = vm::MerkleProof::virtualize(head_c.root, 1);
|
||||
|
@ -676,13 +678,17 @@ std::string HttpAnswer::header() {
|
|||
"maximum-scale=1.0, user-scalable=no\" />\n"
|
||||
<< "<meta name=\"format-detection\" content=\"telephone=no\" />\n"
|
||||
<< "<!-- Latest compiled and minified CSS -->\n"
|
||||
<< "<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\">\n"
|
||||
<< "<link rel=\"stylesheet\" href=\"" << (local_scripts ? "/" : "https://")
|
||||
<< "maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css\">\n"
|
||||
<< "<!-- jQuery library -->"
|
||||
<< "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js\"></script>\n"
|
||||
<< "<script src=\"" << (local_scripts ? "/" : "https://")
|
||||
<< "ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js\"></script>\n"
|
||||
<< "<!-- Popper JS -->\n"
|
||||
<< "<script src=\"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js\"></script>\n"
|
||||
<< "<script src=\"" << (local_scripts ? "/" : "https://")
|
||||
<< "cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js\"></script>\n"
|
||||
<< "<!-- Latest compiled JavaScript -->\n"
|
||||
<< "<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js\"></script>\n"
|
||||
<< "<script src=\"" << (local_scripts ? "/" : "https://")
|
||||
<< "maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js\"></script>\n"
|
||||
<< "</head><body>\n"
|
||||
<< "<div class=\"container-fluid\">\n"
|
||||
<< "<nav class=\"navbar navbar-expand px-0 mt-1 flex-wrap\">\n"
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include "td/utils/Random.h"
|
||||
#include "block/block.h"
|
||||
|
||||
extern bool local_scripts;
|
||||
|
||||
class HttpAnswer {
|
||||
public:
|
||||
struct MessageCell {
|
||||
|
|
|
@ -639,6 +639,10 @@ int main(int argc, char* argv[]) {
|
|||
td::actor::send_closure(x, &CoreActor::set_http_port, td::to_integer<td::uint32>(arg));
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('L', "local-scripts", "use local copy of ajax/bootstrap/... JS", [&]() {
|
||||
local_scripts = true;
|
||||
return td::Status::OK();
|
||||
});
|
||||
#if TD_DARWIN || TD_LINUX
|
||||
p.add_option('l', "logname", "log to file", [&](td::Slice fname) {
|
||||
auto FileLog = td::FileFd::open(td::CSlice(fname.str().c_str()),
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
#define MAX_POST_SIZE (64 << 10)
|
||||
|
||||
extern bool local_scripts_;
|
||||
|
||||
class CoreActorInterface : public td::actor::Actor {
|
||||
public:
|
||||
struct RemoteNodeStatus {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "check-proof.h"
|
||||
#include "block/block.h"
|
||||
|
@ -219,7 +219,17 @@ td::Status check_account_proof(td::Slice proof, ton::BlockIdExt shard_blk, const
|
|||
}
|
||||
|
||||
td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, block::StdAddress addr) const {
|
||||
TRY_RESULT_PREFIX(root, vm::std_boc_deserialize(state.as_slice(), true), "cannot deserialize account state");
|
||||
TRY_RESULT_PREFIX(true_root, vm::std_boc_deserialize(state.as_slice(), true), "cannot deserialize account state");
|
||||
Ref<vm::Cell> root;
|
||||
|
||||
if (is_virtualized && true_root.not_null()) {
|
||||
root = vm::MerkleProof::virtualize(true_root, 1);
|
||||
if (root.is_null()) {
|
||||
return td::Status::Error("account state proof is invalid");
|
||||
}
|
||||
} else {
|
||||
root = true_root;
|
||||
}
|
||||
|
||||
if (blk != ref_blk && ref_blk.id.seqno != ~0U) {
|
||||
return td::Status::Error(PSLICE() << "obtained getAccountState() for a different reference block " << blk.to_str()
|
||||
|
@ -241,6 +251,7 @@ td::Result<AccountState::Info> AccountState::validate(ton::BlockIdExt ref_blk, b
|
|||
TRY_STATUS(block::check_account_proof(proof.as_slice(), shard_blk, addr, root, &res.last_trans_lt,
|
||||
&res.last_trans_hash, &res.gen_utime, &res.gen_lt));
|
||||
res.root = std::move(root);
|
||||
res.true_root = std::move(true_root);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -44,10 +44,11 @@ struct AccountState {
|
|||
td::BufferSlice shard_proof;
|
||||
td::BufferSlice proof;
|
||||
td::BufferSlice state;
|
||||
bool is_virtualized{false};
|
||||
|
||||
struct Info {
|
||||
td::Ref<vm::Cell> root;
|
||||
ton::LogicalTime last_trans_lt = 0;
|
||||
td::Ref<vm::Cell> root, true_root;
|
||||
ton::LogicalTime last_trans_lt{0};
|
||||
ton::Bits256 last_trans_hash;
|
||||
ton::LogicalTime gen_lt{0};
|
||||
td::uint32 gen_utime{0};
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "mc-config.h"
|
||||
#include "block/block.h"
|
||||
|
@ -752,8 +752,8 @@ Ref<McShardDescr> McShardDescr::from_block(Ref<vm::Cell> block_root, Ref<vm::Cel
|
|||
return {};
|
||||
}
|
||||
// TODO: use a suitable vm::MerkleUpdate method here
|
||||
vm::CellSlice cs(vm::NoVm(), rec.state_update);
|
||||
if (cs.special_type() != vm::Cell::SpecialType::MerkleUpdate) {
|
||||
vm::CellSlice cs(vm::NoVmSpec(), rec.state_update);
|
||||
if (!cs.is_valid() || cs.special_type() != vm::Cell::SpecialType::MerkleUpdate) {
|
||||
LOG(ERROR) << "state update in a block is not a Merkle update";
|
||||
return {};
|
||||
}
|
||||
|
@ -870,7 +870,7 @@ bool ShardConfig::get_shard_hash_raw_from(vm::Dictionary& dict, vm::CellSlice& c
|
|||
unsigned long long z = id.shard, m = std::numeric_limits<unsigned long long>::max();
|
||||
int len = id.pfx_len();
|
||||
while (true) {
|
||||
cs.load(vm::NoVmOrd{}, leaf ? root : std::move(root));
|
||||
cs.load(vm::NoVmOrd(), leaf ? root : std::move(root));
|
||||
int t = (int)cs.fetch_ulong(1);
|
||||
if (t < 0) {
|
||||
return false; // throw DictError ?
|
||||
|
@ -1108,7 +1108,7 @@ std::vector<ton::BlockId> ShardConfig::get_shard_hash_ids(
|
|||
std::stack<std::pair<Ref<vm::Cell>, unsigned long long>> stack;
|
||||
stack.emplace(cs_ref->prefetch_ref(), ton::shardIdAll);
|
||||
while (!stack.empty()) {
|
||||
vm::CellSlice cs{vm::NoVm{}, std::move(stack.top().first)};
|
||||
vm::CellSlice cs{vm::NoVmOrd(), std::move(stack.top().first)};
|
||||
unsigned long long shard = stack.top().second;
|
||||
stack.pop();
|
||||
int t = (int)cs.fetch_ulong(1);
|
||||
|
|
|
@ -965,6 +965,11 @@ x{F4B5} @Defop SUBDICTRPGET
|
|||
x{F4B6} @Defop SUBDICTIRPGET
|
||||
x{F4B7} @Defop SUBDICTURPGET
|
||||
|
||||
x{F4BC} @Defop DICTIGETJMPZ
|
||||
x{F4BD} @Defop DICTUGETJMPZ
|
||||
x{F4BE} @Defop DICTIGETEXECZ
|
||||
x{F4BF} @Defop DICTUGETEXECZ
|
||||
|
||||
//
|
||||
// blockchain-specific primitives
|
||||
|
||||
|
@ -1117,7 +1122,7 @@ variable @gvarcnt
|
|||
@procdict dup @ swap null!
|
||||
} : }END
|
||||
forget @proclist forget @proccnt
|
||||
{ }END <{ SETCP0 swap @procdictkeylen DICTPUSHCONST DICTIGETJMP 11 THROWARG }> } : }END>
|
||||
{ }END <{ SETCP0 swap @procdictkeylen DICTPUSHCONST DICTIGETJMPZ 11 THROWARG }> } : }END>
|
||||
{ }END> b> } : }END>c
|
||||
{ }END>c <s } : }END>s
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "words.h"
|
||||
|
||||
|
@ -1007,8 +1007,8 @@ void interpret_store_end(vm::Stack& stack, bool special) {
|
|||
|
||||
void interpret_from_cell(vm::Stack& stack) {
|
||||
auto cell = stack.pop_cell();
|
||||
Ref<vm::CellSlice> cs{true};
|
||||
if (!cs.unique_write().load(vm::NoVmOrd(), std::move(cell))) {
|
||||
Ref<vm::CellSlice> cs{true, vm::NoVmOrd(), std::move(cell)};
|
||||
if (!cs->is_valid()) {
|
||||
throw IntError{"deserializing a special cell as ordinary"};
|
||||
}
|
||||
stack.push(cs);
|
||||
|
@ -1117,7 +1117,10 @@ void interpret_fetch_ref(vm::Stack& stack, int mode) {
|
|||
stack.push(std::move(cs));
|
||||
}
|
||||
if (mode & 1) {
|
||||
Ref<vm::CellSlice> new_cs{true, vm::NoVm(), std::move(cell)};
|
||||
Ref<vm::CellSlice> new_cs{true, vm::NoVmOrd(), std::move(cell)};
|
||||
if (!new_cs->is_valid()) {
|
||||
throw IntError{"cannot load ordinary cell"};
|
||||
}
|
||||
stack.push(std::move(new_cs));
|
||||
} else {
|
||||
stack.push_cell(std::move(cell));
|
||||
|
|
|
@ -39,3 +39,9 @@
|
|||
int seqno() method_id {
|
||||
return get_data().begin_parse().preload_uint(32);
|
||||
}
|
||||
|
||||
int get_public_key() method_id {
|
||||
var cs = get_data().begin_parse();
|
||||
cs~load_uint(64);
|
||||
return cs.preload_uint(256);
|
||||
}
|
||||
|
|
|
@ -63,3 +63,9 @@ int processed?(int query_id) method_id {
|
|||
(_, var found) = old_queries.udict_get?(64, query_id);
|
||||
return found ? true : - (query_id <= last_cleaned);
|
||||
}
|
||||
|
||||
int get_public_key() method_id {
|
||||
var cs = get_data().begin_parse();
|
||||
cs~load_uint(32 + 64);
|
||||
return cs.preload_uint(256);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ def? $2 { @' $2 } { "new-wallet" } cond constant file-base
|
|||
|
||||
// Create new advanced wallet; code adapted from `auto/wallet-code.fif`
|
||||
<{ SETCP0 DUP IFNOTRET // return if recv_internal
|
||||
DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method
|
||||
DROP c4 PUSHCTR CTOS 32 PLDU // cnt
|
||||
DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods
|
||||
1 INT AND c4 PUSHCTR CTOS 32 LDU 256 PLDU CONDSEL // cnt or pubk
|
||||
}>
|
||||
INC 32 THROWIF // fail unless recv_external
|
||||
9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU // signature in_msg msg_seqno valid_until cs
|
||||
|
|
|
@ -18,8 +18,8 @@ $3 "new-wallet" replace-if-null =: file-base
|
|||
|
||||
// Create new advanced wallet; code adapted from `auto/wallet3-code.fif`
|
||||
<{ SETCP0 DUP IFNOTRET // return if recv_internal
|
||||
DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method
|
||||
DROP c4 PUSHCTR CTOS 32 PLDU // cnt
|
||||
DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods
|
||||
1 INT AND c4 PUSHCTR CTOS 32 LDU 32 LDU NIP 256 PLDU CONDSEL // cnt or pubk
|
||||
}>
|
||||
INC 32 THROWIF // fail unless recv_external
|
||||
9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
|
||||
|
|
|
@ -15,8 +15,8 @@ def? $2 { @' $2 } { "new-wallet" } cond constant file-base
|
|||
|
||||
// Create new simple wallet
|
||||
<{ SETCP0 DUP IFNOTRET // return if recv_internal
|
||||
DUP 85143 INT EQUAL IFJMP:<{ // "seqno" get-method
|
||||
DROP c4 PUSHCTR CTOS 32 PLDU // cnt
|
||||
DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods
|
||||
1 INT AND c4 PUSHCTR CTOS 32 LDU 256 PLDU CONDSEL // cnt or pubk
|
||||
}>
|
||||
INC 32 THROWIF // fail unless recv_external
|
||||
512 INT LDSLICEX DUP 32 PLDU // sign cs cnt
|
||||
|
|
|
@ -62,6 +62,12 @@ int seqno() method_id {
|
|||
return get_data().begin_parse().preload_uint(32);
|
||||
}
|
||||
|
||||
int get_public_key() method_id {
|
||||
var cs = get_data().begin_parse();
|
||||
cs~load_uint(32);
|
||||
return cs.preload_uint(256);
|
||||
}
|
||||
|
||||
int balance() method_id {
|
||||
return restricted?() ? 0 : get_balance().first();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,12 @@ int seqno() method_id {
|
|||
return get_data().begin_parse().preload_uint(32);
|
||||
}
|
||||
|
||||
int get_public_key() method_id {
|
||||
var cs = get_data().begin_parse();
|
||||
cs~load_uint(32);
|
||||
return cs.preload_uint(256);
|
||||
}
|
||||
|
||||
int balance() method_id {
|
||||
var ds = get_data().begin_parse().skip_bits(32 + 256);
|
||||
var rdict = ds~load_dict();
|
||||
|
|
|
@ -45,6 +45,11 @@ int seqno() method_id {
|
|||
return get_data().begin_parse().preload_uint(32);
|
||||
}
|
||||
|
||||
int get_public_key() method_id {
|
||||
var (seqno, public_key) = load_state();
|
||||
return public_key;
|
||||
}
|
||||
|
||||
cell create_init_state(int public_key) method_id {
|
||||
return create_state(0, public_key);
|
||||
}
|
||||
|
|
|
@ -29,3 +29,9 @@
|
|||
int seqno() method_id {
|
||||
return get_data().begin_parse().preload_uint(32);
|
||||
}
|
||||
|
||||
int get_public_key() method_id {
|
||||
var cs = get_data().begin_parse();
|
||||
cs~load_uint(32);
|
||||
return cs.preload_uint(256);
|
||||
}
|
||||
|
|
|
@ -33,3 +33,9 @@
|
|||
int seqno() method_id {
|
||||
return get_data().begin_parse().preload_uint(32);
|
||||
}
|
||||
|
||||
int get_public_key() method_id {
|
||||
var cs = get_data().begin_parse();
|
||||
cs~load_uint(64);
|
||||
return cs.preload_uint(256);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "vm/cells/CellBuilder.h"
|
||||
|
||||
|
@ -460,6 +460,16 @@ bool CellBuilder::append_cellslice_chk(Ref<CellSlice> cs_ref, unsigned size_ext)
|
|||
return cs_ref.not_null() && append_cellslice_chk(*cs_ref, size_ext);
|
||||
}
|
||||
|
||||
CellSlice CellSlice::clone() const {
|
||||
CellBuilder cb;
|
||||
Ref<Cell> cell;
|
||||
if (cb.append_cellslice_bool(*this) && cb.finalize_to(cell)) {
|
||||
return CellSlice{NoVmOrd(), std::move(cell)};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool CellBuilder::append_bitstring(const td::BitString& bs) {
|
||||
return store_bits_bool(bs.cbits(), bs.size());
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -275,6 +275,7 @@ class CellSlice : public td::CntObject {
|
|||
offs = std::min(offs, size());
|
||||
return CellSlice{*this, size() - offs, size_refs(), offs, 0};
|
||||
}
|
||||
CellSlice clone() const;
|
||||
|
||||
private:
|
||||
void init_bits_refs();
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "vm/dict.h"
|
||||
#include "vm/cells.h"
|
||||
|
@ -2535,7 +2535,7 @@ bool AugmentedDictionary::set(td::ConstBitPtr key, int key_len, const CellSlice&
|
|||
}
|
||||
auto res = dict_set(get_root_cell(), key, key_len, value, mode);
|
||||
if (res.second) {
|
||||
//vm::CellSlice cs{vm::NoVm{}, res.first};
|
||||
//vm::CellSlice cs{vm::NoVmOrd(), res.first};
|
||||
//std::cerr << "new augmented dictionary root is:\n";
|
||||
//cs.print_rec(std::cerr);
|
||||
set_root_cell(std::move(res.first));
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include <functional>
|
||||
#include "vm/log.h"
|
||||
|
@ -210,7 +210,7 @@ int exec_dict_get(VmState* st, unsigned args) {
|
|||
BitSlice key;
|
||||
unsigned char buffer[Dictionary::max_key_bytes];
|
||||
if (args & 4) {
|
||||
key = dict.integer_key(stack.pop_int(), n, !(args & 2), buffer, true);
|
||||
key = dict.integer_key(stack.pop_int_finite(), n, !(args & 2), buffer, true);
|
||||
if (!key.is_valid()) {
|
||||
stack.push_smallint(0);
|
||||
return 0;
|
||||
|
@ -250,7 +250,7 @@ int exec_dict_get_optref(VmState* st, unsigned args) {
|
|||
BitSlice key;
|
||||
unsigned char buffer[Dictionary::max_key_bytes];
|
||||
if (args & 2) {
|
||||
key = dict.integer_key(stack.pop_int(), n, !(args & 1), buffer, true);
|
||||
key = dict.integer_key(stack.pop_int_finite(), n, !(args & 1), buffer, true);
|
||||
if (!key.is_valid()) {
|
||||
stack.push_null();
|
||||
return 0;
|
||||
|
@ -377,7 +377,7 @@ int exec_dict_delete(VmState* st, unsigned args) {
|
|||
BitSlice key;
|
||||
unsigned char buffer[Dictionary::max_key_bytes];
|
||||
if (args & 2) {
|
||||
key = dict.integer_key(stack.pop_int(), n, !(args & 1), buffer);
|
||||
key = dict.integer_key(stack.pop_int_finite(), n, !(args & 1), buffer);
|
||||
if (!key.is_valid()) {
|
||||
push_dict(stack, std::move(dict));
|
||||
stack.push_smallint(0);
|
||||
|
@ -404,7 +404,7 @@ int exec_dict_deleteget(VmState* st, unsigned args) {
|
|||
BitSlice key;
|
||||
unsigned char buffer[Dictionary::max_key_bytes];
|
||||
if (args & 4) {
|
||||
key = dict.integer_key(stack.pop_int(), n, !(args & 2), buffer);
|
||||
key = dict.integer_key(stack.pop_int_finite(), n, !(args & 2), buffer);
|
||||
if (!key.is_valid()) {
|
||||
push_dict(stack, std::move(dict));
|
||||
stack.push_smallint(0);
|
||||
|
@ -588,23 +588,29 @@ int exec_pfx_dict_delete(VmState* st) {
|
|||
|
||||
int exec_dict_get_exec(VmState* st, unsigned args) {
|
||||
Stack& stack = st->get_stack();
|
||||
VM_LOG(st) << "execute DICT" << (args & 1 ? 'U' : 'I') << "GET" << (args & 2 ? "EXEC\n" : "JMP\n");
|
||||
VM_LOG(st) << "execute DICT" << (args & 1 ? 'U' : 'I') << "GET" << (args & 2 ? "EXEC" : "JMP")
|
||||
<< (args & 4 ? "Z" : "");
|
||||
stack.check_underflow(3);
|
||||
int n = stack.pop_smallint_range(Dictionary::max_key_bits);
|
||||
Dictionary dict{stack.pop_maybe_cell(), n};
|
||||
unsigned char buffer[Dictionary::max_key_bytes];
|
||||
dict.integer_key_simple(stack.pop_int(), n, !(args & 1), td::BitPtr{buffer});
|
||||
auto idx = stack.pop_int_finite();
|
||||
if (dict.integer_key_simple(idx, n, !(args & 1), td::BitPtr{buffer}, true)) {
|
||||
auto value = dict.lookup(td::BitPtr{buffer}, n);
|
||||
if (value.not_null()) {
|
||||
Ref<OrdCont> cont{true, std::move(value), st->get_cp()};
|
||||
return (args & 2) ? st->call(std::move(cont)) : st->jump(std::move(cont));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// key not found or out of range
|
||||
if (args & 4) {
|
||||
stack.push_int(std::move(idx));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string dump_dict_get_exec(CellSlice& cs, unsigned args) {
|
||||
return std::string{"DICT"} + (args & 1 ? 'U' : 'I') + "GET" + (args & 2 ? "EXEC" : "JMP");
|
||||
return std::string{"DICT"} + (args & 1 ? 'U' : 'I') + "GET" + (args & 2 ? "EXEC" : "JMP") + (args & 4 ? "Z" : "");
|
||||
}
|
||||
|
||||
int exec_push_const_dict(VmState* st, CellSlice& cs, unsigned args, int pfx_bits) {
|
||||
|
@ -720,7 +726,7 @@ int exec_subdict_get(VmState* st, unsigned args) {
|
|||
BitSlice key;
|
||||
unsigned char buffer[Dictionary::max_key_bytes];
|
||||
if (args & 2) {
|
||||
key = dict.integer_key(stack.pop_int(), k, !(args & 1), buffer, true);
|
||||
key = dict.integer_key(stack.pop_int_finite(), k, !(args & 1), buffer, true);
|
||||
} else {
|
||||
key = stack.pop_cellslice()->prefetch_bits(k);
|
||||
}
|
||||
|
@ -805,7 +811,8 @@ void register_dictionary_ops(OpcodeTable& cp0) {
|
|||
exec_const_pfx_dict_switch, compute_len_push_const_dict))
|
||||
.insert(OpcodeInstr::mkfixedrange(0xf4b1, 0xf4b4, 16, 3, std::bind(dump_subdictop2, _2, "GET"), exec_subdict_get))
|
||||
.insert(
|
||||
OpcodeInstr::mkfixedrange(0xf4b5, 0xf4b8, 16, 3, std::bind(dump_subdictop2, _2, "RPGET"), exec_subdict_get));
|
||||
OpcodeInstr::mkfixedrange(0xf4b5, 0xf4b8, 16, 3, std::bind(dump_subdictop2, _2, "RPGET"), exec_subdict_get))
|
||||
.insert(OpcodeInstr::mkfixed(0xf4bc >> 2, 14, 2, dump_dict_get_exec, exec_dict_get_exec));
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -33,6 +33,12 @@ struct VmLog {
|
|||
td::LogOptions log_options{td::log_options};
|
||||
enum { DumpStack = 2 };
|
||||
int log_mask{1};
|
||||
static VmLog Null() {
|
||||
VmLog res;
|
||||
res.log_options.level = 0;
|
||||
res.log_mask = 0;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template <class State>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "vm/stack.hpp"
|
||||
#include "vm/continuation.h"
|
||||
|
@ -824,7 +824,7 @@ bool StackEntry::deserialize(CellSlice& cs, int mode) {
|
|||
return false;
|
||||
}
|
||||
} else if (n == 1) {
|
||||
return cs.have_refs() && t[0].deserialize(cs.fetch_ref(), mode);
|
||||
return cs.have_refs() && t[0].deserialize(cs.fetch_ref(), mode) && set(t_tuple, std::move(tuple));
|
||||
}
|
||||
return set(t_tuple, std::move(tuple));
|
||||
}
|
||||
|
|
|
@ -145,13 +145,13 @@ void DhtBucket::promote_node(size_t idx) {
|
|||
}
|
||||
}
|
||||
|
||||
void DhtBucket::check(td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> dht,
|
||||
void DhtBucket::check(bool client_only, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> dht,
|
||||
adnl::AdnlNodeIdShort src) {
|
||||
size_t have_space = 0;
|
||||
for (size_t i = 0; i < active_nodes_.size(); i++) {
|
||||
auto &node = active_nodes_[i];
|
||||
if (node && td::Time::now_cached() - node->last_ping_at() > ping_timeout_) {
|
||||
node->send_ping(adnl, dht, src);
|
||||
node->send_ping(client_only, adnl, dht, src);
|
||||
if (node->ready_from() == 0) {
|
||||
demote_node(i);
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ void DhtBucket::check(td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<Dh
|
|||
for (size_t i = 0; i < backup_nodes_.size(); i++) {
|
||||
auto &node = backup_nodes_[i];
|
||||
if (node && td::Time::now_cached() - node->last_ping_at() > ping_timeout_) {
|
||||
node->send_ping(adnl, dht, src);
|
||||
node->send_ping(client_only, adnl, dht, src);
|
||||
}
|
||||
if (node && have_space > 0 && node->is_ready()) {
|
||||
promote_node(i);
|
||||
|
|
|
@ -39,8 +39,8 @@ class DhtBucket {
|
|||
|
||||
//std::map<td::UInt256, std::unique_ptr<DhtRemoteNode>> pending_nodes_;
|
||||
td::uint32 k_;
|
||||
bool check_one(td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node, adnl::AdnlNodeIdShort src,
|
||||
const DhtMember::PrintId &print_id);
|
||||
//bool check_one(td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node, adnl::AdnlNodeIdShort src,
|
||||
// const DhtMember::PrintId &print_id);
|
||||
void demote_node(size_t idx);
|
||||
void promote_node(size_t idx);
|
||||
|
||||
|
@ -52,7 +52,8 @@ class DhtBucket {
|
|||
td::uint32 active_cnt();
|
||||
td::Status add_full_node(DhtKeyId id, DhtNode node, td::actor::ActorId<adnl::Adnl> adnl,
|
||||
adnl::AdnlNodeIdShort self_id);
|
||||
void check(td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node, adnl::AdnlNodeIdShort src);
|
||||
void check(bool client_only, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node,
|
||||
adnl::AdnlNodeIdShort src);
|
||||
void receive_ping(DhtKeyId id, DhtNode result, td::actor::ActorId<adnl::Adnl> adnl, adnl::AdnlNodeIdShort self_id);
|
||||
void get_nearest_nodes(DhtKeyId id, td::uint32 bit, DhtNodesList &vec, td::uint32 k);
|
||||
void dump(td::StringBuilder &sb) const;
|
||||
|
|
|
@ -94,6 +94,8 @@ class DhtMemberImpl : public DhtMember {
|
|||
td::actor::ActorId<keyring::Keyring> keyring_;
|
||||
td::actor::ActorId<adnl::Adnl> adnl_;
|
||||
|
||||
bool client_only_{false};
|
||||
|
||||
td::uint64 ping_queries_{0};
|
||||
td::uint64 find_node_queries_{0};
|
||||
td::uint64 find_value_queries_{0};
|
||||
|
@ -123,8 +125,8 @@ class DhtMemberImpl : public DhtMember {
|
|||
|
||||
public:
|
||||
DhtMemberImpl(adnl::AdnlNodeIdShort id, std::string db_root, td::actor::ActorId<keyring::Keyring> keyring,
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::uint32 k, td::uint32 a = 3)
|
||||
: id_(id), key_{id_}, k_(k), a_(a), db_root_(db_root), keyring_(keyring), adnl_(adnl) {
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::uint32 k, td::uint32 a = 3, bool client_only = false)
|
||||
: id_(id), key_{id_}, k_(k), a_(a), db_root_(db_root), keyring_(keyring), adnl_(adnl), client_only_(client_only) {
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
buckets_.emplace_back(k_);
|
||||
}
|
||||
|
|
|
@ -96,7 +96,12 @@ void DhtQuery::add_nodes(DhtNodesList list) {
|
|||
|
||||
void DhtQueryFindNodes::send_one_query(adnl::AdnlNodeIdShort id) {
|
||||
auto P = create_serialize_tl_object<ton_api::dht_findNode>(get_key().tl(), get_k());
|
||||
auto B = create_serialize_tl_object_suffix<ton_api::dht_query>(P.as_slice(), self_.tl());
|
||||
td::BufferSlice B;
|
||||
if (client_only_) {
|
||||
B = std::move(P);
|
||||
} else {
|
||||
B = create_serialize_tl_object_suffix<ton_api::dht_query>(P.as_slice(), self_.tl());
|
||||
}
|
||||
|
||||
auto Pr = td::PromiseCreator::lambda([SelfId = actor_id(this), dst = id](td::Result<td::BufferSlice> R) {
|
||||
td::actor::send_closure(SelfId, &DhtQueryFindNodes::on_result, std::move(R), dst);
|
||||
|
@ -129,7 +134,12 @@ void DhtQueryFindNodes::finish(DhtNodesList list) {
|
|||
|
||||
void DhtQueryFindValue::send_one_query(adnl::AdnlNodeIdShort id) {
|
||||
auto P = create_serialize_tl_object<ton_api::dht_findValue>(get_key().tl(), get_k());
|
||||
auto B = create_serialize_tl_object_suffix<ton_api::dht_query>(P.as_slice(), self_.tl());
|
||||
td::BufferSlice B;
|
||||
if (client_only_) {
|
||||
B = std::move(P);
|
||||
} else {
|
||||
B = create_serialize_tl_object_suffix<ton_api::dht_query>(P.as_slice(), self_.tl());
|
||||
}
|
||||
|
||||
auto Pr = td::PromiseCreator::lambda([SelfId = actor_id(this), dst = id](td::Result<td::BufferSlice> R) {
|
||||
td::actor::send_closure(SelfId, &DhtQueryFindValue::on_result, std::move(R), dst);
|
||||
|
@ -186,7 +196,7 @@ void DhtQueryFindValue::finish(DhtNodesList list) {
|
|||
}
|
||||
|
||||
DhtQueryStore::DhtQueryStore(DhtValue key_value, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src,
|
||||
DhtNodesList list, td::uint32 k, td::uint32 a, DhtNode self,
|
||||
DhtNodesList list, td::uint32 k, td::uint32 a, DhtNode self, bool client_only,
|
||||
td::actor::ActorId<DhtMember> node, td::actor::ActorId<adnl::Adnl> adnl,
|
||||
td::Promise<td::Unit> promise)
|
||||
: print_id_(print_id)
|
||||
|
@ -195,7 +205,8 @@ DhtQueryStore::DhtQueryStore(DhtValue key_value, DhtMember::PrintId print_id, ad
|
|||
, promise_(std::move(promise))
|
||||
, value_(std::move(key_value))
|
||||
, list_(std::move(list))
|
||||
, self_(std::move(self)) {
|
||||
, self_(std::move(self))
|
||||
, client_only_(client_only) {
|
||||
node_ = node;
|
||||
adnl_ = adnl;
|
||||
src_ = src;
|
||||
|
@ -208,7 +219,7 @@ void DhtQueryStore::start_up() {
|
|||
|
||||
auto key = value_.key_id();
|
||||
auto A = td::actor::create_actor<DhtQueryFindNodes>("FindNodesQuery", key, print_id_, src_, std::move(list_), k_, a_,
|
||||
self_.clone(), node_, adnl_, std::move(P));
|
||||
self_.clone(), client_only_, node_, adnl_, std::move(P));
|
||||
A.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -41,11 +41,21 @@ class DhtQuery : public td::actor::Actor {
|
|||
protected:
|
||||
DhtKeyId key_;
|
||||
DhtNode self_;
|
||||
bool client_only_;
|
||||
|
||||
public:
|
||||
DhtQuery(DhtKeyId key, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list, td::uint32 k,
|
||||
td::uint32 a, DhtNode self, td::actor::ActorId<DhtMember> node, td::actor::ActorId<adnl::Adnl> adnl)
|
||||
: key_(key), self_(std::move(self)), print_id_(print_id), src_(src), k_(k), a_(a), node_(node), adnl_(adnl) {
|
||||
td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId<DhtMember> node,
|
||||
td::actor::ActorId<adnl::Adnl> adnl)
|
||||
: key_(key)
|
||||
, self_(std::move(self))
|
||||
, client_only_(client_only)
|
||||
, print_id_(print_id)
|
||||
, src_(src)
|
||||
, k_(k)
|
||||
, a_(a)
|
||||
, node_(node)
|
||||
, adnl_(adnl) {
|
||||
add_nodes(std::move(list));
|
||||
}
|
||||
DhtMember::PrintId print_id() const {
|
||||
|
@ -94,9 +104,10 @@ class DhtQueryFindNodes : public DhtQuery {
|
|||
|
||||
public:
|
||||
DhtQueryFindNodes(DhtKeyId key, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list,
|
||||
td::uint32 k, td::uint32 a, DhtNode self, td::actor::ActorId<DhtMember> node,
|
||||
td::uint32 k, td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId<DhtMember> node,
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::Promise<DhtNodesList> promise)
|
||||
: DhtQuery(key, print_id, src, std::move(list), k, a, std::move(self), node, adnl), promise_(std::move(promise)) {
|
||||
: DhtQuery(key, print_id, src, std::move(list), k, a, std::move(self), client_only, node, adnl)
|
||||
, promise_(std::move(promise)) {
|
||||
}
|
||||
void send_one_query(adnl::AdnlNodeIdShort id) override;
|
||||
void on_result(td::Result<td::BufferSlice> R, adnl::AdnlNodeIdShort dst);
|
||||
|
@ -112,9 +123,10 @@ class DhtQueryFindValue : public DhtQuery {
|
|||
|
||||
public:
|
||||
DhtQueryFindValue(DhtKeyId key, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list,
|
||||
td::uint32 k, td::uint32 a, DhtNode self, td::actor::ActorId<DhtMember> node,
|
||||
td::uint32 k, td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId<DhtMember> node,
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::Promise<DhtValue> promise)
|
||||
: DhtQuery(key, print_id, src, std::move(list), k, a, std::move(self), node, adnl), promise_(std::move(promise)) {
|
||||
: DhtQuery(key, print_id, src, std::move(list), k, a, std::move(self), client_only, node, adnl)
|
||||
, promise_(std::move(promise)) {
|
||||
}
|
||||
void send_one_query(adnl::AdnlNodeIdShort id) override;
|
||||
void on_result(td::Result<td::BufferSlice> R, adnl::AdnlNodeIdShort dst);
|
||||
|
@ -139,10 +151,11 @@ class DhtQueryStore : public td::actor::Actor {
|
|||
td::uint32 remaining_;
|
||||
DhtNodesList list_;
|
||||
DhtNode self_;
|
||||
bool client_only_;
|
||||
|
||||
public:
|
||||
DhtQueryStore(DhtValue key_value, DhtMember::PrintId print_id, adnl::AdnlNodeIdShort src, DhtNodesList list,
|
||||
td::uint32 k, td::uint32 a, DhtNode self, td::actor::ActorId<DhtMember> node,
|
||||
td::uint32 k, td::uint32 a, DhtNode self, bool client_only, td::actor::ActorId<DhtMember> node,
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::Promise<td::Unit> promise);
|
||||
void send_stores(td::Result<DhtNodesList> res);
|
||||
void store_ready(td::Result<td::BufferSlice> res);
|
||||
|
|
|
@ -63,7 +63,7 @@ td::Status DhtRemoteNode::update_value(DhtNode node, td::actor::ActorId<adnl::Ad
|
|||
return td::Status::OK();
|
||||
}
|
||||
|
||||
void DhtRemoteNode::send_ping(td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node,
|
||||
void DhtRemoteNode::send_ping(bool client_only, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node,
|
||||
adnl::AdnlNodeIdShort src) {
|
||||
missed_pings_++;
|
||||
if (missed_pings_ > max_missed_pings_ && ready_from_ > 0) {
|
||||
|
@ -75,8 +75,8 @@ void DhtRemoteNode::send_ping(td::actor::ActorId<adnl::Adnl> adnl, td::actor::Ac
|
|||
|
||||
td::actor::send_closure(adnl, &adnl::Adnl::add_peer, src, node_.adnl_id(), node_.addr_list());
|
||||
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[key = id_, id = node_.adnl_id().compute_short_id(), node, src, adnl](td::Result<DhtNode> R) mutable {
|
||||
auto P = td::PromiseCreator::lambda([key = id_, id = node_.adnl_id().compute_short_id(), client_only, node, src,
|
||||
adnl](td::Result<DhtNode> R) mutable {
|
||||
if (R.is_error()) {
|
||||
LOG(ERROR) << "[dht]: failed to get self node";
|
||||
return;
|
||||
|
@ -102,7 +102,12 @@ void DhtRemoteNode::send_ping(td::actor::ActorId<adnl::Adnl> adnl, td::actor::Ac
|
|||
}
|
||||
});
|
||||
auto Q = create_serialize_tl_object<ton_api::dht_getSignedAddressList>();
|
||||
auto B = create_serialize_tl_object_suffix<ton_api::dht_query>(Q.as_slice(), R.move_as_ok().tl());
|
||||
td::BufferSlice B;
|
||||
if (client_only) {
|
||||
B = std::move(Q);
|
||||
} else {
|
||||
B = create_serialize_tl_object_suffix<ton_api::dht_query>(Q.as_slice(), R.move_as_ok().tl());
|
||||
}
|
||||
td::actor::send_closure(adnl, &adnl::Adnl::send_query, src, id, "dht ping", std::move(P),
|
||||
td::Timestamp::in(10.0 + td::Random::fast(0, 100) * 0.1), std::move(B));
|
||||
});
|
||||
|
|
|
@ -76,7 +76,8 @@ class DhtRemoteNode {
|
|||
double last_ping_at() const {
|
||||
return last_ping_at_;
|
||||
}
|
||||
void send_ping(td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node, adnl::AdnlNodeIdShort src);
|
||||
void send_ping(bool client_only, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> node,
|
||||
adnl::AdnlNodeIdShort src);
|
||||
td::Status receive_ping(DhtNode node, td::actor::ActorId<adnl::Adnl> adnl, adnl::AdnlNodeIdShort self_id);
|
||||
td::Status update_value(DhtNode node, td::actor::ActorId<adnl::Adnl> adnl, adnl::AdnlNodeIdShort self_id);
|
||||
};
|
||||
|
|
61
dht/dht.cpp
61
dht/dht.cpp
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "dht.hpp"
|
||||
|
||||
|
@ -44,9 +44,10 @@ namespace dht {
|
|||
|
||||
td::actor::ActorOwn<DhtMember> DhtMember::create(adnl::AdnlNodeIdShort id, std::string db_root,
|
||||
td::actor::ActorId<keyring::Keyring> keyring,
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::uint32 k, td::uint32 a) {
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::uint32 k, td::uint32 a,
|
||||
bool client_only) {
|
||||
return td::actor::ActorOwn<DhtMember>(
|
||||
td::actor::create_actor<DhtMemberImpl>("dht", id, db_root, keyring, adnl, k, a));
|
||||
td::actor::create_actor<DhtMemberImpl>("dht", id, db_root, keyring, adnl, k, a, client_only));
|
||||
}
|
||||
|
||||
td::Result<td::actor::ActorOwn<Dht>> Dht::create(adnl::AdnlNodeIdShort id, std::string db_root,
|
||||
|
@ -66,9 +67,24 @@ td::Result<td::actor::ActorOwn<Dht>> Dht::create(adnl::AdnlNodeIdShort id, std::
|
|||
return std::move(D);
|
||||
}
|
||||
|
||||
td::Result<td::actor::ActorOwn<Dht>> Dht::create_client(adnl::AdnlNodeIdShort id, std::string db_root,
|
||||
std::shared_ptr<DhtGlobalConfig> conf,
|
||||
td::actor::ActorId<keyring::Keyring> keyring,
|
||||
td::actor::ActorId<adnl::Adnl> adnl) {
|
||||
CHECK(conf->get_k() > 0);
|
||||
CHECK(conf->get_a() > 0);
|
||||
|
||||
auto D = DhtMember::create(id, db_root, keyring, adnl, conf->get_k(), conf->get_a(), true);
|
||||
auto &nodes = conf->nodes();
|
||||
|
||||
for (auto &node : nodes.list()) {
|
||||
auto key = node.get_key();
|
||||
td::actor::send_closure(D, &DhtMember::add_full_node, key, node.clone());
|
||||
}
|
||||
return std::move(D);
|
||||
}
|
||||
|
||||
void DhtMemberImpl::start_up() {
|
||||
std::shared_ptr<td::KeyValue> kv = std::make_shared<td::RocksDb>(
|
||||
td::RocksDb::open(PSTRING() << db_root_ << "/dht-" << td::base64url_encode(id_.as_slice())).move_as_ok());
|
||||
std::vector<td::int32> methods = {ton_api::dht_getSignedAddressList::ID,
|
||||
ton_api::dht_findNode::ID,
|
||||
ton_api::dht_findValue::ID,
|
||||
|
@ -82,6 +98,10 @@ void DhtMemberImpl::start_up() {
|
|||
std::make_unique<Callback>(actor_id(this), id_));
|
||||
}
|
||||
alarm_timestamp() = td::Timestamp::in(1.0);
|
||||
|
||||
if (!db_root_.empty()) {
|
||||
std::shared_ptr<td::KeyValue> kv = std::make_shared<td::RocksDb>(
|
||||
td::RocksDb::open(PSTRING() << db_root_ << "/dht-" << td::base64url_encode(id_.as_slice())).move_as_ok());
|
||||
for (td::uint32 bit = 0; bit < 256; bit++) {
|
||||
auto key = create_hash_tl_object<ton_api::dht_db_key_bucket>(bit);
|
||||
std::string value;
|
||||
|
@ -103,6 +123,7 @@ void DhtMemberImpl::start_up() {
|
|||
}
|
||||
db_ = DbType{std::move(kv)};
|
||||
}
|
||||
}
|
||||
|
||||
void DhtMemberImpl::tear_down() {
|
||||
std::vector<td::int32> methods = {ton_api::dht_getSignedAddressList::ID,
|
||||
|
@ -119,6 +140,9 @@ void DhtMemberImpl::tear_down() {
|
|||
}
|
||||
|
||||
void DhtMemberImpl::save_to_db() {
|
||||
if (db_root_.empty()) {
|
||||
return;
|
||||
}
|
||||
next_save_to_db_at_ = td::Timestamp::in(10.0);
|
||||
alarm_timestamp().relax(next_save_to_db_at_);
|
||||
|
||||
|
@ -277,6 +301,9 @@ void DhtMemberImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::dht_getSig
|
|||
|
||||
void DhtMemberImpl::receive_query(adnl::AdnlNodeIdShort src, td::BufferSlice data,
|
||||
td::Promise<td::BufferSlice> promise) {
|
||||
if (client_only_) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto R = fetch_tl_prefix<ton_api::dht_query>(data, true);
|
||||
if (R.is_ok()) {
|
||||
|
@ -358,11 +385,11 @@ void DhtMemberImpl::set_value(DhtValue value, td::Promise<td::Unit> promise) {
|
|||
|
||||
void DhtMemberImpl::get_value_in(DhtKeyId key, td::Promise<DhtValue> result) {
|
||||
auto P = td::PromiseCreator::lambda([key, promise = std::move(result), SelfId = actor_id(this), print_id = print_id(),
|
||||
adnl = adnl_, list = get_nearest_nodes(key, k_), k = k_, a = a_,
|
||||
id = id_](td::Result<DhtNode> R) mutable {
|
||||
adnl = adnl_, list = get_nearest_nodes(key, k_), k = k_, a = a_, id = id_,
|
||||
client_only = client_only_](td::Result<DhtNode> R) mutable {
|
||||
R.ensure();
|
||||
td::actor::create_actor<DhtQueryFindValue>("FindValueQuery", key, print_id, id, std::move(list), k, a,
|
||||
R.move_as_ok(), SelfId, adnl, std::move(promise))
|
||||
R.move_as_ok(), client_only, SelfId, adnl, std::move(promise))
|
||||
.release();
|
||||
});
|
||||
|
||||
|
@ -374,7 +401,7 @@ void DhtMemberImpl::check() {
|
|||
<< " fvalue=" << find_value_queries_ << " store=" << store_queries_
|
||||
<< " addrlist=" << get_addr_list_queries_;
|
||||
for (auto &bucket : buckets_) {
|
||||
bucket.check(adnl_, actor_id(this), id_);
|
||||
bucket.check(client_only_, adnl_, actor_id(this), id_);
|
||||
}
|
||||
if (next_save_to_db_at_.is_in_past()) {
|
||||
save_to_db();
|
||||
|
@ -469,10 +496,10 @@ void DhtMemberImpl::check() {
|
|||
DhtKeyId key{x};
|
||||
auto P = td::PromiseCreator::lambda([key, promise = std::move(promise), SelfId = actor_id(this),
|
||||
print_id = print_id(), adnl = adnl_, list = get_nearest_nodes(key, k_), k = k_,
|
||||
a = a_, id = id_](td::Result<DhtNode> R) mutable {
|
||||
a = a_, id = id_, client_only = client_only_](td::Result<DhtNode> R) mutable {
|
||||
R.ensure();
|
||||
td::actor::create_actor<DhtQueryFindNodes>("FindNodesQuery", key, print_id, id, std::move(list), k, a,
|
||||
R.move_as_ok(), SelfId, adnl, std::move(promise))
|
||||
R.move_as_ok(), client_only, SelfId, adnl, std::move(promise))
|
||||
.release();
|
||||
});
|
||||
|
||||
|
@ -492,12 +519,13 @@ void DhtMemberImpl::send_store(DhtValue value, td::Promise<td::Unit> promise) {
|
|||
value.check().ensure();
|
||||
auto key_id = value.key_id();
|
||||
|
||||
auto P = td::PromiseCreator::lambda([value = std::move(value), print_id = print_id(), id = id_,
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([value = std::move(value), print_id = print_id(), id = id_, client_only = client_only_,
|
||||
list = get_nearest_nodes(key_id, k_), k = k_, a = a_, SelfId = actor_id(this),
|
||||
adnl = adnl_, promise = std::move(promise)](td::Result<DhtNode> R) mutable {
|
||||
R.ensure();
|
||||
td::actor::create_actor<DhtQueryStore>("StoreQuery", std::move(value), print_id, id, std::move(list), k, a,
|
||||
R.move_as_ok(), SelfId, adnl, std::move(promise))
|
||||
R.move_as_ok(), client_only, SelfId, adnl, std::move(promise))
|
||||
.release();
|
||||
});
|
||||
|
||||
|
@ -505,14 +533,17 @@ void DhtMemberImpl::send_store(DhtValue value, td::Promise<td::Unit> promise) {
|
|||
}
|
||||
|
||||
void DhtMemberImpl::get_self_node(td::Promise<DhtNode> promise) {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise), print_id = print_id(), id = id_,
|
||||
keyring = keyring_](td::Result<adnl::AdnlNode> R) mutable {
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([promise = std::move(promise), print_id = print_id(), id = id_, keyring = keyring_,
|
||||
client_only = client_only_](td::Result<adnl::AdnlNode> R) mutable {
|
||||
R.ensure();
|
||||
auto node = R.move_as_ok();
|
||||
auto version = static_cast<td::int32>(td::Clocks::system());
|
||||
auto B = create_serialize_tl_object<ton_api::dht_node>(node.pub_id().tl(), node.addr_list().tl(), version,
|
||||
td::BufferSlice());
|
||||
if (!client_only) {
|
||||
CHECK(node.addr_list().size() > 0);
|
||||
}
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise), node = std::move(node), version](td::Result<td::BufferSlice> R) mutable {
|
||||
R.ensure();
|
||||
|
|
|
@ -42,6 +42,10 @@ class Dht : public td::actor::Actor {
|
|||
std::shared_ptr<DhtGlobalConfig> conf,
|
||||
td::actor::ActorId<keyring::Keyring> keyring,
|
||||
td::actor::ActorId<adnl::Adnl> adnl);
|
||||
static td::Result<td::actor::ActorOwn<Dht>> create_client(adnl::AdnlNodeIdShort id, std::string db_root,
|
||||
std::shared_ptr<DhtGlobalConfig> conf,
|
||||
td::actor::ActorId<keyring::Keyring> keyring,
|
||||
td::actor::ActorId<adnl::Adnl> adnl);
|
||||
static td::Result<std::shared_ptr<DhtGlobalConfig>> create_global_config(
|
||||
tl_object_ptr<ton_api::dht_config_global> conf);
|
||||
|
||||
|
|
|
@ -85,8 +85,8 @@ class DhtMember : public Dht {
|
|||
|
||||
static td::actor::ActorOwn<DhtMember> create(adnl::AdnlNodeIdShort id, std::string db_root,
|
||||
td::actor::ActorId<keyring::Keyring> keyring,
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::uint32 k = 10,
|
||||
td::uint32 a = 3);
|
||||
td::actor::ActorId<adnl::Adnl> adnl, td::uint32 k = 10, td::uint32 a = 3,
|
||||
bool client_only = false);
|
||||
|
||||
//virtual void update_addr_list(tl_object_ptr<ton_api::adnl_addressList> addr_list) = 0;
|
||||
//virtual void add_node(adnl::AdnlNodeIdShort id) = 0;
|
||||
|
|
|
@ -2140,6 +2140,10 @@ These primitives are completely similar to their non-prefix code counterparts {\
|
|||
\item {\tt F4AA} --- {\tt PFXDICTGETJMP} ($s$ $D$ $n$ -- $s'$ $s''$ or $s$), similar to {\tt PFXDICTGETQ}, but on success {\tt BLESS}es the value $x$ into a {\em Continuation\/} and transfers control to it as if by a {\tt JMPX}. On failure, returns $s$ unchanged and continues execution.
|
||||
\item {\tt F4AB} --- {\tt PFXDICTGETEXEC} ($s$ $D$ $n$ -- $s'$ $s''$), similar to {\tt PFXDICTGETJMP}, but {\tt EXEC}utes the continuation found instead of jumping to it. On failure, throws a cell deserialization exception.
|
||||
\item {\tt F4AE\_$n$} --- {\tt PFXDICTCONSTGETJMP $n$} or {\tt PFXDICTSWITCH $n$} ($s$ -- $s'$ $s''$ or $s$), combines {\tt DICTPUSHCONST $n$} for $0\leq n\leq 1023$ with {\tt PFXDICTGETJMP}.
|
||||
\item {\tt F4BC} --- {\tt DICTIGETJMPZ} ($i$ $D$ $n$ -- $i$ or nothing), a variant of {\tt DICTIGETJMP} that returns index $i$ on failure.
|
||||
\item {\tt F4BD} --- {\tt DICTUGETJMPZ} ($i$ $D$ $n$ -- $i$ or nothing), a variant of {\tt DICTUGETJMP} that returns index $i$ on failure.
|
||||
\item {\tt F4BE} --- {\tt DICTIGETEXECZ} ($i$ $D$ $n$ -- $i$ or nothing), a variant of {\tt DICTIGETEXEC} that returns index $i$ on failure.
|
||||
\item {\tt F4BF} --- {\tt DICTUGETEXECZ} ($i$ $D$ $n$ -- $i$ or nothing), a variant of {\tt DICTUGETEXEC} that returns index $i$ on failure.
|
||||
\end{itemize}
|
||||
|
||||
\nxsubpoint\label{sp:prim.dict.get}\emb{{\sc SubDict} dictionary operations}
|
||||
|
@ -2150,6 +2154,7 @@ These primitives are completely similar to their non-prefix code counterparts {\
|
|||
\item {\tt F4B5} --- {\tt SUBDICTRPGET} ($k$ $l$ $D$ $n$ -- $D'$), similar to {\tt SUBDICTGET}, but removes the common prefix $k$ from all keys of the new dictionary $D'$, which becomes of type $\HashmapE(n-l,X)$.
|
||||
\item {\tt F4B6} --- {\tt SUBDICTIRPGET} ($x$ $l$ $D$ $n$ -- $D'$), variant of {\tt SUBDICTRPGET} with the prefix represented by a signed big-endian $l$-bit {\em Integer\/}~$x$, where necessarily $l\leq257$.
|
||||
\item {\tt F4B7} --- {\tt SUBDICTURPGET} ($x$ $l$ $D$ $n$ -- $D'$), variant of {\tt SUBDICTRPGET} with the prefix represented by an unsigned big-endian $l$-bit {\em Integer\/}~$x$, where necessarily $l\leq256$.
|
||||
\item {\tt F4BC}--{\tt F4BF} --- used by {\tt DICT\dots Z} primitives in \ptref{sp:prim.dict.get.spec}.
|
||||
\end{itemize}
|
||||
|
||||
\mysubsection{Application-specific primitives}\label{p:prim.app}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "keyring.hpp"
|
||||
#include "common/errorcode.h"
|
||||
|
@ -28,8 +28,10 @@ namespace ton {
|
|||
namespace keyring {
|
||||
|
||||
void KeyringImpl::start_up() {
|
||||
if (db_root_.size() > 0) {
|
||||
td::mkdir(db_root_).ensure();
|
||||
}
|
||||
}
|
||||
|
||||
td::Result<KeyringImpl::PrivateKeyDescr *> KeyringImpl::load_key(PublicKeyHash key_hash) {
|
||||
auto it = map_.find(key_hash);
|
||||
|
@ -37,6 +39,10 @@ td::Result<KeyringImpl::PrivateKeyDescr *> KeyringImpl::load_key(PublicKeyHash k
|
|||
return it->second.get();
|
||||
}
|
||||
|
||||
if (db_root_.size() == 0) {
|
||||
return td::Status::Error(ErrorCode::notready, "key not in db");
|
||||
}
|
||||
|
||||
auto name = db_root_ + "/" + key_hash.bits256_value().to_hex();
|
||||
|
||||
auto R = td::read_file(td::CSlice{name});
|
||||
|
@ -67,6 +73,9 @@ void KeyringImpl::add_key(PrivateKey key, bool is_temp, td::Promise<td::Unit> pr
|
|||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
if (db_root_.size() == 0) {
|
||||
CHECK(is_temp);
|
||||
}
|
||||
auto D = key.create_decryptor_async();
|
||||
D.ensure();
|
||||
|
||||
|
@ -103,6 +112,9 @@ void KeyringImpl::add_key_short(PublicKeyHash key_hash, td::Promise<PublicKey> p
|
|||
|
||||
void KeyringImpl::del_key(PublicKeyHash key_hash, td::Promise<td::Unit> promise) {
|
||||
map_.erase(key_hash);
|
||||
if (db_root_.size() == 0) {
|
||||
return promise.set_value(td::Unit());
|
||||
}
|
||||
auto name = db_root_ + "/" + key_hash.bits256_value().to_hex();
|
||||
td::BufferSlice d{256};
|
||||
td::Random::secure_bytes(d.as_slice());
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "lite-client.h"
|
||||
|
||||
|
@ -800,7 +800,7 @@ bool TestNode::show_help(std::string command) {
|
|||
"saveaccount[code|data] <filename> <addr> [<block-id-ext>]\tSaves into specified file the most recent state "
|
||||
"(StateInit) or just the code or data of specified account; <addr> is in "
|
||||
"[<workchain>:]<hex-or-base64-addr> format\n"
|
||||
"runmethod <addr> [<block-id-ext>] <method-id> <params>...\tRuns GET method <method-id> of account <addr> "
|
||||
"runmethod[x] <addr> [<block-id-ext>] <method-id> <params>...\tRuns GET method <method-id> of account <addr> "
|
||||
"with specified parameters\n"
|
||||
"allshards [<block-id-ext>]\tShows shard configuration from the most recent masterchain "
|
||||
"state or from masterchain state corresponding to <block-id-ext>\n"
|
||||
|
@ -871,11 +871,11 @@ bool TestNode::do_parse_line() {
|
|||
(seekeoln()
|
||||
? get_account_state(workchain, addr, mc_last_id_, filename, mode)
|
||||
: parse_block_id_ext(blkid) && seekeoln() && get_account_state(workchain, addr, blkid, filename, mode));
|
||||
} else if (word == "runmethod") {
|
||||
} else if (word == "runmethod" || word == "runmethodx") {
|
||||
std::string method;
|
||||
return parse_account_addr(workchain, addr) && get_word_to(method) &&
|
||||
(parse_block_id_ext(method, blkid) ? get_word_to(method) : (blkid = mc_last_id_).is_valid()) &&
|
||||
parse_run_method(workchain, addr, blkid, method);
|
||||
parse_run_method(workchain, addr, blkid, method, word.size() > 9);
|
||||
} else if (word == "allshards") {
|
||||
return eoln() ? get_all_shards() : (parse_block_id_ext(blkid) && seekeoln() && get_all_shards(false, blkid));
|
||||
} else if (word == "saveconfig") {
|
||||
|
@ -1015,8 +1015,16 @@ bool TestNode::get_account_state(ton::WorkchainId workchain, ton::StdSmcAddress
|
|||
});
|
||||
}
|
||||
|
||||
td::int64 TestNode::compute_method_id(std::string method) {
|
||||
td::int64 method_id;
|
||||
if (!convert_int64(method, method_id)) {
|
||||
method_id = (td::crc16(td::Slice{method}) & 0xffff) | 0x10000;
|
||||
}
|
||||
return method_id;
|
||||
}
|
||||
|
||||
bool TestNode::parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid,
|
||||
std::string method_name) {
|
||||
std::string method_name, bool ext_mode) {
|
||||
auto R = vm::parse_stack_entries(td::Slice(parse_ptr_, parse_end_));
|
||||
if (R.is_error()) {
|
||||
return set_error(R.move_as_error().to_string());
|
||||
|
@ -1030,6 +1038,8 @@ bool TestNode::parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a
|
|||
return set_error("server connection not ready");
|
||||
}
|
||||
auto a = ton::create_tl_object<ton::lite_api::liteServer_accountId>(workchain, addr);
|
||||
int mode = (ext_mode ? 0x1f : 0);
|
||||
if (!mode) {
|
||||
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getAccountState>(
|
||||
ton::create_tl_lite_block_id(ref_blkid), std::move(a)),
|
||||
true);
|
||||
|
@ -1046,12 +1056,51 @@ bool TestNode::parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress a
|
|||
LOG(ERROR) << "cannot parse answer to liteServer.getAccountState";
|
||||
} else {
|
||||
auto f = F.move_as_ok();
|
||||
td::actor::send_closure_later(Self, &TestNode::run_smc_method, ref_blkid, ton::create_block_id(f->id_),
|
||||
td::actor::send_closure_later(Self, &TestNode::run_smc_method, 0, ref_blkid, ton::create_block_id(f->id_),
|
||||
ton::create_block_id(f->shardblk_), std::move(f->shard_proof_),
|
||||
std::move(f->proof_), std::move(f->state_), workchain, addr, method_name,
|
||||
std::move(params));
|
||||
std::move(params), td::BufferSlice(), td::BufferSlice(), td::BufferSlice(),
|
||||
-0x10000);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
td::int64 method_id = compute_method_id(method_name);
|
||||
// serialize parameters
|
||||
vm::CellBuilder cb;
|
||||
Ref<vm::Cell> cell;
|
||||
if (!(vm::Stack{params}.serialize(cb) && cb.finalize_to(cell))) {
|
||||
return set_error("cannot serialize stack with get-method parameters");
|
||||
}
|
||||
auto stk = vm::std_boc_serialize(std::move(cell));
|
||||
if (stk.is_error()) {
|
||||
return set_error("cannot serialize stack with get-method parameters : "s + stk.move_as_error().to_string());
|
||||
}
|
||||
auto b = ton::serialize_tl_object(
|
||||
ton::create_tl_object<ton::lite_api::liteServer_runSmcMethod>(mode, ton::create_tl_lite_block_id(ref_blkid),
|
||||
std::move(a), method_id, stk.move_as_ok()),
|
||||
true);
|
||||
LOG(INFO) << "requesting remote get-method execution for " << workchain << ":" << addr.to_hex()
|
||||
<< " with respect to " << ref_blkid.to_str() << " to run method " << method_name << " with "
|
||||
<< params.size() << " parameters";
|
||||
return envelope_send_query(std::move(b), [
|
||||
Self = actor_id(this), workchain, addr, ref_blkid, method_name, mode, params = std::move(params)
|
||||
](td::Result<td::BufferSlice> R) mutable {
|
||||
if (R.is_error()) {
|
||||
return;
|
||||
}
|
||||
auto F = ton::fetch_tl_object<ton::lite_api::liteServer_runMethodResult>(R.move_as_ok(), true);
|
||||
if (F.is_error()) {
|
||||
LOG(ERROR) << "cannot parse answer to liteServer.runSmcMethod";
|
||||
} else {
|
||||
auto f = F.move_as_ok();
|
||||
td::actor::send_closure_later(Self, &TestNode::run_smc_method, mode, ref_blkid, ton::create_block_id(f->id_),
|
||||
ton::create_block_id(f->shardblk_), std::move(f->shard_proof_),
|
||||
std::move(f->proof_), std::move(f->state_proof_), workchain, addr, method_name,
|
||||
std::move(params), std::move(f->init_c7_), std::move(f->lib_extras_),
|
||||
std::move(f->result_), f->exit_code_);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool TestNode::get_one_transaction(ton::BlockIdExt blkid, ton::WorkchainId workchain, ton::StdSmcAddress addr,
|
||||
|
@ -1212,18 +1261,25 @@ void TestNode::got_account_state(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, t
|
|||
}
|
||||
}
|
||||
|
||||
void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk,
|
||||
void TestNode::run_smc_method(int mode, ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk,
|
||||
td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state,
|
||||
ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string method,
|
||||
std::vector<vm::StackEntry> params) {
|
||||
LOG(INFO) << "got account state for " << workchain << ":" << addr.to_hex() << " with respect to blocks "
|
||||
<< blk.to_str() << (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str());
|
||||
std::vector<vm::StackEntry> params, td::BufferSlice remote_c7,
|
||||
td::BufferSlice remote_libs, td::BufferSlice remote_result, int remote_exit_code) {
|
||||
LOG(INFO) << "got (partial) account state with mode=" << mode << " for " << workchain << ":" << addr.to_hex()
|
||||
<< " with respect to blocks " << blk.to_str()
|
||||
<< (shard_blk == blk ? "" : std::string{" and "} + shard_blk.to_str());
|
||||
auto out = td::TerminalIO::out();
|
||||
try {
|
||||
block::AccountState account_state;
|
||||
account_state.blk = blk;
|
||||
account_state.shard_blk = shard_blk;
|
||||
account_state.shard_proof = std::move(shard_proof);
|
||||
account_state.proof = std::move(proof);
|
||||
LOG(DEBUG) << "serialized state is " << state.size() << " bytes";
|
||||
LOG(DEBUG) << "serialized remote c7 is " << remote_c7.size() << " bytes";
|
||||
account_state.state = std::move(state);
|
||||
account_state.is_virtualized = (mode > 0);
|
||||
auto r_info = account_state.validate(ref_blk, block::StdAddress(workchain, addr));
|
||||
if (r_info.is_error()) {
|
||||
LOG(ERROR) << r_info.error().message();
|
||||
|
@ -1232,10 +1288,29 @@ void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton:
|
|||
auto out = td::TerminalIO::out();
|
||||
auto info = r_info.move_as_ok();
|
||||
if (info.root.is_null()) {
|
||||
LOG(ERROR) << "account state of " << workchain << ":" << addr.to_hex() << " is empty (cannot run method `" << method
|
||||
<< "`)";
|
||||
LOG(ERROR) << "account state of " << workchain << ":" << addr.to_hex() << " is empty (cannot run method `"
|
||||
<< method << "`)";
|
||||
return;
|
||||
}
|
||||
if (false) {
|
||||
// DEBUG (dump state)
|
||||
std::ostringstream os;
|
||||
vm::CellSlice{vm::NoVm(), info.true_root}.print_rec(os);
|
||||
out << "dump of account state (proof): " << os.str() << std::endl;
|
||||
}
|
||||
if (false && remote_c7.size()) {
|
||||
// DEBUG (dump remote_c7)
|
||||
auto r_c7 = vm::std_boc_deserialize(remote_c7).move_as_ok();
|
||||
std::ostringstream os;
|
||||
vm::StackEntry val;
|
||||
bool ok = val.deserialize(r_c7);
|
||||
val.dump(os);
|
||||
// os << std::endl;
|
||||
// block::gen::t_VmStackValue.print_ref(os, r_c7);
|
||||
// os << std::endl;
|
||||
// vm::CellSlice{vm::NoVmOrd(), r_c7}.print_rec(os);
|
||||
out << "remote_c7 (deserialized=" << ok << "): " << os.str() << std::endl;
|
||||
}
|
||||
block::gen::Account::Record_account acc;
|
||||
block::gen::AccountStorage::Record store;
|
||||
block::CurrencyCollection balance;
|
||||
|
@ -1247,7 +1322,8 @@ void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton:
|
|||
int tag = block::gen::t_AccountState.get_tag(*store.state);
|
||||
switch (tag) {
|
||||
case block::gen::AccountState::account_uninit:
|
||||
LOG(ERROR) << "account " << workchain << ":" << addr.to_hex() << " not initialized yet (cannot run any methods)";
|
||||
LOG(ERROR) << "account " << workchain << ":" << addr.to_hex()
|
||||
<< " not initialized yet (cannot run any methods)";
|
||||
return;
|
||||
case block::gen::AccountState::account_frozen:
|
||||
LOG(ERROR) << "account " << workchain << ":" << addr.to_hex() << " frozen (cannot run any methods)";
|
||||
|
@ -1259,10 +1335,7 @@ void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton:
|
|||
auto code = state_init.code->prefetch_ref();
|
||||
auto data = state_init.data->prefetch_ref();
|
||||
auto stack = td::make_ref<vm::Stack>(std::move(params));
|
||||
td::int64 method_id;
|
||||
if (!convert_int64(method, method_id)) {
|
||||
method_id = (td::crc16(td::Slice{method}) & 0xffff) | 0x10000;
|
||||
}
|
||||
td::int64 method_id = compute_method_id(method);
|
||||
stack.write().push_smallint(method_id);
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
@ -1276,12 +1349,16 @@ void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton:
|
|||
vm::GasLimits gas{gas_limit};
|
||||
LOG(DEBUG) << "creating VM";
|
||||
vm::VmState vm{code, std::move(stack), gas, 1, data, vm::VmLog()};
|
||||
vm.set_c7(liteclient::prepare_vm_c7(info.gen_utime, info.gen_lt, acc.addr, balance)); // tuple with SmartContractInfo
|
||||
vm.set_c7(liteclient::prepare_vm_c7(info.gen_utime, info.gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()),
|
||||
balance)); // tuple with SmartContractInfo
|
||||
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||
LOG(INFO) << "starting VM to run method `" << method << "` (" << method_id << ") of smart contract " << workchain
|
||||
<< ":" << addr.to_hex();
|
||||
int exit_code = ~vm.run();
|
||||
LOG(DEBUG) << "VM terminated with exit code " << exit_code;
|
||||
if (mode > 0) {
|
||||
LOG(DEBUG) << "remote VM exit code is " << remote_exit_code;
|
||||
}
|
||||
if (exit_code != 0) {
|
||||
LOG(ERROR) << "VM terminated with error code " << exit_code;
|
||||
out << "result: error " << exit_code << std::endl;
|
||||
|
@ -1294,6 +1371,38 @@ void TestNode::run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton:
|
|||
stack->dump(os, 3);
|
||||
out << os.str();
|
||||
}
|
||||
if (mode & 4) {
|
||||
if (remote_result.empty()) {
|
||||
out << "remote result: <none>, exit code " << remote_exit_code;
|
||||
} else {
|
||||
auto res = vm::std_boc_deserialize(std::move(remote_result));
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << "cannot deserialize remote VM result boc: " << res.move_as_error();
|
||||
return;
|
||||
}
|
||||
auto cs = vm::load_cell_slice(res.move_as_ok());
|
||||
Ref<vm::Stack> remote_stack;
|
||||
if (!(vm::Stack::deserialize_to(cs, remote_stack, 0) && cs.empty_ext())) {
|
||||
LOG(ERROR) << "remote VM result boc cannot be deserialized as a VmStack";
|
||||
return;
|
||||
}
|
||||
std::ostringstream os;
|
||||
os << "remote result (not to be trusted): ";
|
||||
remote_stack->dump(os, 3);
|
||||
out << os.str();
|
||||
}
|
||||
}
|
||||
if (0) { // DEBUG
|
||||
std::ostringstream os;
|
||||
LOG(DEBUG) << "dumping constructed proof";
|
||||
//vm::CellSlice{vm::NoVm(), pb.extract_proof()}.print_rec(os);
|
||||
out << "constructed state proof: " << os.str();
|
||||
}
|
||||
} catch (vm::VmVirtError& err) {
|
||||
out << "virtualization error while parsing runSmcMethod result: " << err.get_msg();
|
||||
} catch (vm::VmError& err) {
|
||||
out << "error while parsing runSmcMethod result: " << err.get_msg();
|
||||
}
|
||||
}
|
||||
|
||||
void TestNode::got_one_transaction(ton::BlockIdExt req_blkid, ton::BlockIdExt blkid, td::BufferSlice proof,
|
||||
|
@ -2062,7 +2171,7 @@ void TestNode::got_block_header(ton::BlockIdExt blkid, td::BufferSlice data, int
|
|||
}
|
||||
auto root = res.move_as_ok();
|
||||
std::ostringstream outp;
|
||||
vm::CellSlice cs{vm::NoVm{}, root};
|
||||
vm::CellSlice cs{vm::NoVm(), root};
|
||||
cs.print_rec(outp);
|
||||
td::TerminalIO::out() << outp.str();
|
||||
try {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
exception statement from your version. If you delete this exception statement
|
||||
from all source files in the program, then also delete it here.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "adnl/adnl-ext-client.h"
|
||||
|
@ -117,11 +117,12 @@ class TestNode : public td::actor::Actor {
|
|||
td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state,
|
||||
ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string filename, int mode);
|
||||
bool parse_run_method(ton::WorkchainId workchain, ton::StdSmcAddress addr, ton::BlockIdExt ref_blkid,
|
||||
std::string method_name);
|
||||
void run_smc_method(ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk,
|
||||
std::string method_name, bool ext_mode);
|
||||
void run_smc_method(int mode, ton::BlockIdExt ref_blk, ton::BlockIdExt blk, ton::BlockIdExt shard_blk,
|
||||
td::BufferSlice shard_proof, td::BufferSlice proof, td::BufferSlice state,
|
||||
ton::WorkchainId workchain, ton::StdSmcAddress addr, std::string method,
|
||||
std::vector<vm::StackEntry> params);
|
||||
std::vector<vm::StackEntry> params, td::BufferSlice remote_c7, td::BufferSlice remote_libs,
|
||||
td::BufferSlice remote_result, int remote_exit_code);
|
||||
bool get_all_shards(bool use_last = true, ton::BlockIdExt blkid = {});
|
||||
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 = "");
|
||||
|
@ -181,6 +182,7 @@ class TestNode : public td::actor::Actor {
|
|||
static bool convert_uint32(td::Slice word, td::uint32& val);
|
||||
static bool convert_int32(td::Slice word, td::int32& val);
|
||||
static bool convert_shard_id(td::Slice str, ton::ShardIdFull& shard);
|
||||
static td::int64 compute_method_id(std::string method);
|
||||
bool parse_hash(ton::Bits256& hash);
|
||||
bool parse_lt(ton::LogicalTime& lt);
|
||||
bool parse_uint32(td::uint32& val);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -84,6 +84,12 @@ class BufferedFd : public BufferedFdBase<FdT> {
|
|||
~BufferedFd();
|
||||
|
||||
void close();
|
||||
size_t left_unread() {
|
||||
return input_reader_.size();
|
||||
}
|
||||
size_t left_unwritten() {
|
||||
return output_reader_.size();
|
||||
}
|
||||
|
||||
Result<size_t> flush_read(size_t max_read = std::numeric_limits<size_t>::max()) TD_WARN_UNUSED_RESULT;
|
||||
Result<size_t> flush_write() TD_WARN_UNUSED_RESULT;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "td/utils/FileLog.h"
|
||||
|
||||
|
@ -128,4 +128,10 @@ void FileLog::do_rotate() {
|
|||
SET_VERBOSITY_LEVEL(current_verbosity_level);
|
||||
}
|
||||
|
||||
Result<td::unique_ptr<LogInterface>> FileLog::create(string path, int64 rotate_threshold, bool redirect_stderr) {
|
||||
auto l = make_unique<FileLog>();
|
||||
TRY_STATUS(l->init(std::move(path), rotate_threshold, redirect_stderr));
|
||||
return std::move(l);
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -30,6 +30,8 @@ class FileLog : public LogInterface {
|
|||
static constexpr int64 DEFAULT_ROTATE_THRESHOLD = 10 * (1 << 20);
|
||||
|
||||
public:
|
||||
static Result<td::unique_ptr<LogInterface>> create(string path, int64 rotate_threshold = DEFAULT_ROTATE_THRESHOLD,
|
||||
bool redirect_stderr = true);
|
||||
Status init(string path, int64 rotate_threshold = DEFAULT_ROTATE_THRESHOLD, bool redirect_stderr = true);
|
||||
|
||||
Slice get_path() const;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -44,12 +44,12 @@ std::pair<T, T> split(T s, char delimiter = ' ') {
|
|||
}
|
||||
|
||||
template <class T>
|
||||
vector<T> full_split(T s, char delimiter = ' ') {
|
||||
vector<T> full_split(T s, char delimiter = ' ', size_t max_parts = std::numeric_limits<size_t>::max()) {
|
||||
vector<T> result;
|
||||
if (s.empty()) {
|
||||
return result;
|
||||
}
|
||||
while (true) {
|
||||
while (result.size() + 1 < max_parts) {
|
||||
auto delimiter_pos = s.find(delimiter);
|
||||
if (delimiter_pos == string::npos) {
|
||||
result.push_back(std::move(s));
|
||||
|
@ -59,6 +59,8 @@ vector<T> full_split(T s, char delimiter = ' ') {
|
|||
s = s.substr(delimiter_pos + 1);
|
||||
}
|
||||
}
|
||||
result.push_back(std::move(s));
|
||||
return result;
|
||||
}
|
||||
|
||||
string implode(const vector<string> &v, char delimiter = ' ');
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "td/utils/port/detail/Epoll.h"
|
||||
|
||||
|
@ -109,6 +109,7 @@ void Epoll::run(int timeout_ms) {
|
|||
#ifdef EPOLLRDHUP
|
||||
if (event->events & EPOLLRDHUP) {
|
||||
event->events &= ~EPOLLRDHUP;
|
||||
flags = flags | PollFlags::Close();
|
||||
// flags |= Fd::Close;
|
||||
// TODO
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "td/utils/as.h"
|
||||
#include "td/utils/base64.h"
|
||||
|
@ -570,6 +570,10 @@ static void test_full_split(Slice str, vector<Slice> expected) {
|
|||
ASSERT_EQ(expected, td::full_split(str));
|
||||
}
|
||||
|
||||
static void test_full_split(Slice str, char c, size_t max_parts, vector<Slice> expected) {
|
||||
ASSERT_EQ(expected, td::full_split(str, c, max_parts));
|
||||
}
|
||||
|
||||
TEST(Misc, full_split) {
|
||||
test_full_split("", {});
|
||||
test_full_split(" ", {"", ""});
|
||||
|
@ -585,6 +589,7 @@ TEST(Misc, full_split) {
|
|||
test_full_split(" abcdef ", {"", "abcdef", ""});
|
||||
test_full_split(" ab cd ef ", {"", "ab", "cd", "ef", ""});
|
||||
test_full_split(" ab cd ef ", {"", "", "ab", "", "cd", "", "ef", "", ""});
|
||||
test_full_split("ab cd ef gh", ' ', 3, {"ab", "cd", "ef gh"});
|
||||
}
|
||||
|
||||
TEST(Misc, StringBuilder) {
|
||||
|
|
|
@ -23,7 +23,7 @@ Test_Fift_testvm6_default dd6353c8f3f21cf62a4769ee1f3daaec46f43fd633ffb84c5d6535
|
|||
Test_Fift_testvm7_default 77f54b6c8c9a728d262e912efcc347de7014a37d08793c3adeac8b96fe063342
|
||||
Test_Fift_testvm8_default 17c9e2205ccecfd8549328b4a501d07dde0336899a7a496e747e1032ad5efff9
|
||||
Test_Fift_testvm_default ee4cbfec76c050b6de7877cfc39817d594cd1e175b6265b76fb642e30b940437
|
||||
Test_Fift_testvmprog_default 3aeebf868c0492f2bafe339505751449e9d258bf25ea5d956efe70c6fce408ed
|
||||
Test_Fift_testvmprog_default a6d40d8a7bf0dd3b719c8b1023fef59e01ef094f732951cec4577556c6c68e64
|
||||
Test_RefInt_main_default 768493e0aef8e09a401a6d369edd1ef503a9215fb09dc460f52b27a8bde767cb
|
||||
Test_VM_assert_code_not_null_default 05bc07e129181c972b976442f200de9487dee8bfb5ac53dd36ff61c5d4d4291d
|
||||
Test_VM_assert_extract_minmax_key_default c352309c61bdf62ba7a0ba7280d303c88b0696fe7efa550c05feb2c662275297
|
||||
|
|
|
@ -35,7 +35,7 @@ liteServer.blockState id:tonNode.blockIdExt root_hash:int256 file_hash:int256 da
|
|||
liteServer.blockHeader id:tonNode.blockIdExt mode:# header_proof:bytes = liteServer.BlockHeader;
|
||||
liteServer.sendMsgStatus status:int = liteServer.SendMsgStatus;
|
||||
liteServer.accountState id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:bytes proof:bytes state:bytes = liteServer.AccountState;
|
||||
liteServer.runMethodResult mode:# id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:bytes proof:bytes state_proof:bytes init_c7:bytes lib_extras:bytes exit_code:int result:bytes = liteServer.RunMethodResult;
|
||||
liteServer.runMethodResult mode:# id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:mode.0?bytes proof:mode.0?bytes state_proof:mode.1?bytes init_c7:mode.3?bytes lib_extras:mode.4?bytes exit_code:int result:mode.2?bytes = liteServer.RunMethodResult;
|
||||
liteServer.shardInfo id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:bytes shard_descr:bytes = liteServer.ShardInfo;
|
||||
liteServer.allShardsInfo id:tonNode.blockIdExt proof:bytes data:bytes = liteServer.AllShardsInfo;
|
||||
liteServer.transactionInfo id:tonNode.blockIdExt proof:bytes transaction:bytes = liteServer.TransactionInfo;
|
||||
|
@ -64,7 +64,7 @@ liteServer.getState id:tonNode.blockIdExt = liteServer.BlockState;
|
|||
liteServer.getBlockHeader id:tonNode.blockIdExt mode:# = liteServer.BlockHeader;
|
||||
liteServer.sendMessage body:bytes = liteServer.SendMsgStatus;
|
||||
liteServer.getAccountState id:tonNode.blockIdExt account:liteServer.accountId = liteServer.AccountState;
|
||||
liteServer.runSmcMethod mode:# id:tonNode.blockIdExt account:liteServer.accountId method_id:int params:bytes = liteServer.RunMethodResult;
|
||||
liteServer.runSmcMethod mode:# id:tonNode.blockIdExt account:liteServer.accountId method_id:long params:bytes = liteServer.RunMethodResult;
|
||||
liteServer.getShardInfo id:tonNode.blockIdExt workchain:int shard:long exact:Bool = liteServer.ShardInfo;
|
||||
liteServer.getAllShardsInfo id:tonNode.blockIdExt = liteServer.AllShardsInfo;
|
||||
liteServer.getOneTransaction id:tonNode.blockIdExt account:liteServer.accountId lt:long = liteServer.TransactionInfo;
|
||||
|
|
Binary file not shown.
|
@ -614,3 +614,25 @@ engine.validator.createElectionBid election_date:int election_addr:string wallet
|
|||
engine.validator.checkDhtServers id:int256 = engine.validator.DhtServersStatus;
|
||||
|
||||
engine.validator.controlQuery data:bytes = Object;
|
||||
|
||||
|
||||
---types---
|
||||
|
||||
http.header name:string value:string = http.Header;
|
||||
http.payloadPart data:bytes trailer:(vector http.header) last:Bool = http.PayloadPart;
|
||||
http.response http_version:string status_code:int reason:string headers:(vector http.header) = http.Response;
|
||||
|
||||
---functions---
|
||||
|
||||
http.request id:int256 method:string url:string http_version:string headers:(vector http.header) = http.Response;
|
||||
http.getNextPayloadPart id:int256 seqno:int max_chunk_size:int = http.PayloadPart;
|
||||
|
||||
---types---
|
||||
|
||||
|
||||
http.server.dnsEntry domain:string addr:adnl.id.short = http.server.DnsEntry;
|
||||
http.server.host domains:(vector string) ip:int port:int adnl_id:adnl.id.short = http.server.Host;
|
||||
|
||||
http.server.config dhs:(vector http.server.dnsEntry) local_hosts:(vector http.server.host) = http.server.Config;
|
||||
|
||||
---functions---
|
||||
|
|
Binary file not shown.
|
@ -504,6 +504,13 @@ void ArchiveManager::load_package(PackageId id) {
|
|||
return;
|
||||
}
|
||||
|
||||
std::string prefix = PSTRING() << db_root_ << id.path() << id.name();
|
||||
auto f = td::FileFd::open(prefix + ".pack", td::FileFd::Read);
|
||||
if (f.is_error()) {
|
||||
x->deleted_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
FileDescription desc{id, false};
|
||||
if (!id.temp) {
|
||||
for (auto &e : x->firstblocks_) {
|
||||
|
@ -512,7 +519,6 @@ void ArchiveManager::load_package(PackageId id) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string prefix = PSTRING() << db_root_ << id.path() << id.name();
|
||||
desc.file = td::actor::create_actor<ArchiveSlice>("slice", id.key, id.temp, prefix);
|
||||
|
||||
get_file_map(id).emplace(id, std::move(desc));
|
||||
|
|
|
@ -28,6 +28,7 @@ class PackageReader : public td::actor::Actor {
|
|||
}
|
||||
void start_up() {
|
||||
promise_.set_result(package_->read(offset_));
|
||||
stop();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -46,8 +46,14 @@ td::uint64 Package::append(std::string filename, td::Slice data, bool sync) {
|
|||
size += 8;
|
||||
CHECK(fd_.pwrite(filename, size).move_as_ok() == filename.size());
|
||||
size += filename.size();
|
||||
CHECK(fd_.pwrite(data, size).move_as_ok() == data.size());
|
||||
size += data.size();
|
||||
while (data.size() != 0) {
|
||||
auto R = fd_.pwrite(data, size);
|
||||
R.ensure();
|
||||
auto x = R.move_as_ok();
|
||||
CHECK(x > 0);
|
||||
size += x;
|
||||
data.remove_prefix(x);
|
||||
}
|
||||
if (sync) {
|
||||
fd_.sync().ensure();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#include "liteserver.hpp"
|
||||
#include "td/utils/Slice.h"
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include "adnl/utils.hpp"
|
||||
#include "ton/lite-tl.hpp"
|
||||
#include "tl-utils/lite-utils.hpp"
|
||||
#include "td/utils/Random.h"
|
||||
#include "vm/boc.h"
|
||||
#include "tl/tlblib.hpp"
|
||||
#include "block/block.h"
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "block/block-auto.h"
|
||||
#include "vm/dict.h"
|
||||
#include "vm/cells/MerkleProof.h"
|
||||
#include "vm/continuation.h"
|
||||
#include "shard.hpp"
|
||||
#include "validator-set.hpp"
|
||||
#include "signature-set.hpp"
|
||||
|
@ -665,14 +667,14 @@ void LiteQuery::continue_getAccountState_0(Ref<ton::validator::MasterchainState>
|
|||
}
|
||||
|
||||
void LiteQuery::perform_runSmcMethod(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, int mode,
|
||||
int method_id, td::BufferSlice params) {
|
||||
td::int64 method_id, td::BufferSlice params) {
|
||||
LOG(INFO) << "started a runSmcMethod(" << blkid.to_str() << ", " << workchain << ", " << addr.to_hex() << ", "
|
||||
<< method_id << ", " << mode << ") liteserver query with " << params.size() << " parameter bytes";
|
||||
if (params.size() >= 65536) {
|
||||
fatal_error("more than 64k parameter bytes passed");
|
||||
return;
|
||||
}
|
||||
if (mode & ~0xf) {
|
||||
if (mode & ~0x1f) {
|
||||
fatal_error("unsupported mode in runSmcMethod");
|
||||
return;
|
||||
}
|
||||
|
@ -984,7 +986,8 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) {
|
|||
return;
|
||||
}
|
||||
if (mode_ & 0x10000) {
|
||||
finish_runSmcMethod(std::move(shard_proof), proof.move_as_ok(), std::move(acc_root));
|
||||
finish_runSmcMethod(std::move(shard_proof), proof.move_as_ok(), std::move(acc_root), sstate.gen_utime,
|
||||
sstate.gen_lt);
|
||||
return;
|
||||
}
|
||||
td::BufferSlice data;
|
||||
|
@ -1003,12 +1006,113 @@ void LiteQuery::finish_getAccountState(td::BufferSlice shard_proof) {
|
|||
finish_query(std::move(b));
|
||||
}
|
||||
|
||||
void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice state_proof, Ref<vm::Cell> acc_root) {
|
||||
// same as in lite-client/lite-client-common.cpp
|
||||
static td::Ref<vm::Tuple> prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt, td::Ref<vm::CellSlice> my_addr,
|
||||
const block::CurrencyCollection& balance) {
|
||||
td::BitArray<256> rand_seed;
|
||||
td::RefInt256 rand_seed_int{true};
|
||||
td::Random::secure_bytes(rand_seed.as_slice());
|
||||
if (!rand_seed_int.unique_write().import_bits(rand_seed.cbits(), 256, false)) {
|
||||
return {};
|
||||
}
|
||||
auto tuple = vm::make_tuple_ref(td::make_refint(0x076ef1ea), // [ magic:0x076ef1ea
|
||||
td::make_refint(0), // actions:Integer
|
||||
td::make_refint(0), // msgs_sent:Integer
|
||||
td::make_refint(now), // unixtime:Integer
|
||||
td::make_refint(lt), // block_lt:Integer
|
||||
td::make_refint(lt), // trans_lt:Integer
|
||||
std::move(rand_seed_int), // rand_seed:Integer
|
||||
balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
||||
my_addr, // myself:MsgAddressInt
|
||||
vm::StackEntry()); // global_config:(Maybe Cell) ] = SmartContractInfo;
|
||||
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string();
|
||||
return vm::make_tuple_ref(std::move(tuple));
|
||||
}
|
||||
|
||||
void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice state_proof, Ref<vm::Cell> acc_root,
|
||||
UnixTime gen_utime, LogicalTime gen_lt) {
|
||||
LOG(INFO) << "completing runSmcMethod() query";
|
||||
// ... TODO ...
|
||||
fatal_error("runSmcMethod not implemented");
|
||||
int mode = mode_ & 0xffff;
|
||||
if (acc_root.is_null()) {
|
||||
// no such account
|
||||
LOG(INFO) << "runSmcMethod(" << acc_workchain_ << ":" << acc_addr_.to_hex()
|
||||
<< ") query completed: account state is empty";
|
||||
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_runMethodResult>(
|
||||
mode, ton::create_tl_lite_block_id(base_blk_id_), ton::create_tl_lite_block_id(blk_id_), std::move(shard_proof),
|
||||
std::move(state_proof), td::BufferSlice(), td::BufferSlice(), td::BufferSlice(), -0x100, td::BufferSlice());
|
||||
finish_query(std::move(b));
|
||||
return;
|
||||
}
|
||||
vm::MerkleProofBuilder pb{std::move(acc_root)};
|
||||
block::gen::Account::Record_account acc;
|
||||
block::gen::AccountStorage::Record store;
|
||||
block::CurrencyCollection balance;
|
||||
block::gen::StateInit::Record state_init;
|
||||
if (!(tlb::unpack_cell(pb.root(), acc) && tlb::csr_unpack(std::move(acc.storage), store) &&
|
||||
balance.validate_unpack(store.balance) && store.state->prefetch_ulong(1) == 1 &&
|
||||
store.state.write().advance(1) && tlb::csr_unpack(std::move(store.state), state_init))) {
|
||||
LOG(INFO) << "error unpacking account state, or account is frozen or uninitialized";
|
||||
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_runMethodResult>(
|
||||
mode, ton::create_tl_lite_block_id(base_blk_id_), ton::create_tl_lite_block_id(blk_id_), std::move(shard_proof),
|
||||
std::move(state_proof), mode & 2 ? pb.extract_proof_boc().move_as_ok() : td::BufferSlice(), td::BufferSlice(),
|
||||
td::BufferSlice(), -0x100, td::BufferSlice());
|
||||
finish_query(std::move(b));
|
||||
return;
|
||||
}
|
||||
auto code = state_init.code->prefetch_ref();
|
||||
auto data = state_init.data->prefetch_ref();
|
||||
long long gas_limit = client_method_gas_limit;
|
||||
LOG(DEBUG) << "creating VM with gas limit " << gas_limit;
|
||||
// **** INIT VM ****
|
||||
vm::GasLimits gas{gas_limit};
|
||||
vm::VmState vm{std::move(code), std::move(stack_), gas, 1, std::move(data), vm::VmLog::Null()};
|
||||
auto c7 = prepare_vm_c7(gen_utime, gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()), balance);
|
||||
vm.set_c7(c7); // tuple with SmartContractInfo
|
||||
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||
LOG(INFO) << "starting VM to run GET-method of smart contract " << acc_workchain_ << ":" << acc_addr_.to_hex();
|
||||
// **** RUN VM ****
|
||||
int exit_code = ~vm.run();
|
||||
LOG(DEBUG) << "VM terminated with exit code " << exit_code;
|
||||
stack_ = vm.get_stack_ref();
|
||||
LOG(INFO) << "runSmcMethod(" << acc_workchain_ << ":" << acc_addr_.to_hex() << ") query completed: exit code is "
|
||||
<< exit_code;
|
||||
Ref<vm::Cell> cell;
|
||||
td::BufferSlice c7_info, result;
|
||||
if (mode & 8) {
|
||||
// serialize c7
|
||||
vm::CellBuilder cb;
|
||||
if (!(vm::StackEntry{std::move(c7)}.serialize(cb) && cb.finalize_to(cell))) {
|
||||
fatal_error("cannot serialize c7");
|
||||
return;
|
||||
}
|
||||
auto res = vm::std_boc_serialize(std::move(cell));
|
||||
if (res.is_error()) {
|
||||
fatal_error("cannot serialize c7 : "s + res.move_as_error().to_string());
|
||||
return;
|
||||
}
|
||||
c7_info = res.move_as_ok();
|
||||
}
|
||||
// pre-serialize stack always (to visit all data cells referred from the result)
|
||||
vm::CellBuilder cb;
|
||||
if (!(stack_->serialize(cb) && cb.finalize_to(cell))) {
|
||||
fatal_error("cannot serialize resulting stack");
|
||||
return;
|
||||
}
|
||||
if (mode & 4) {
|
||||
// serialize stack if required
|
||||
auto res = vm::std_boc_serialize(std::move(cell));
|
||||
if (res.is_error()) {
|
||||
fatal_error("cannot serialize resulting stack : "s + res.move_as_error().to_string());
|
||||
return;
|
||||
}
|
||||
result = res.move_as_ok();
|
||||
}
|
||||
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_runMethodResult>(
|
||||
mode, ton::create_tl_lite_block_id(base_blk_id_), ton::create_tl_lite_block_id(blk_id_), std::move(shard_proof),
|
||||
std::move(state_proof), mode & 2 ? pb.extract_proof_boc().move_as_ok() : td::BufferSlice(), std::move(c7_info),
|
||||
td::BufferSlice(), exit_code, std::move(result));
|
||||
finish_query(std::move(b));
|
||||
}
|
||||
|
||||
void LiteQuery::continue_getOneTransaction() {
|
||||
LOG(INFO) << "completing getOneTransaction() query";
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "ton/ton-types.h"
|
||||
|
@ -61,12 +61,13 @@ class LiteQuery : public td::actor::Actor {
|
|||
public:
|
||||
enum {
|
||||
default_timeout_msec = 4500, // 4.5 seconds
|
||||
max_transaction_count = 16 // fetch at most 16 transactions in one query
|
||||
max_transaction_count = 16, // fetch at most 16 transactions in one query
|
||||
client_method_gas_limit = 100000 // gas limit for liteServer.runSmcMethod
|
||||
};
|
||||
enum {
|
||||
ls_version = 0x101,
|
||||
ls_capabilities = 3
|
||||
}; // version 1.1; +1 = build block proof chains, +2 = masterchainInfoExt
|
||||
ls_capabilities = 7
|
||||
}; // version 1.1; +1 = build block proof chains, +2 = masterchainInfoExt, +4 = runSmcMethod
|
||||
LiteQuery(td::BufferSlice data, td::actor::ActorId<ton::validator::ValidatorManager> manager,
|
||||
td::Promise<td::BufferSlice> promise);
|
||||
static void run_query(td::BufferSlice data, td::actor::ActorId<ton::validator::ValidatorManager> manager,
|
||||
|
@ -97,9 +98,10 @@ class LiteQuery : public td::actor::Actor {
|
|||
void continue_getAccountState_0(Ref<MasterchainState> mc_state, BlockIdExt blkid);
|
||||
void continue_getAccountState();
|
||||
void finish_getAccountState(td::BufferSlice shard_proof);
|
||||
void perform_runSmcMethod(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, int mode, int method_id,
|
||||
void perform_runSmcMethod(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, int mode, td::int64 method_id,
|
||||
td::BufferSlice params);
|
||||
void finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice state_proof, Ref<vm::Cell> acc_root);
|
||||
void finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice state_proof, Ref<vm::Cell> acc_root,
|
||||
UnixTime gen_utime, LogicalTime gen_lt);
|
||||
void perform_getOneTransaction(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, LogicalTime lt);
|
||||
void continue_getOneTransaction();
|
||||
void perform_getTransactions(WorkchainId workchain, StdSmcAddress addr, LogicalTime lt, Bits256 hash, unsigned count);
|
||||
|
|
Loading…
Reference in a new issue