mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-14 12:12:21 +00:00
updated vm
- updated func/fift - additional checks in block validator - docs - tunnel prototype in ADNL
This commit is contained in:
parent
ba76f1404e
commit
54c7a4dcc3
50 changed files with 972 additions and 300 deletions
|
@ -21,6 +21,7 @@
|
|||
#include "auto/tl/ton_api.hpp"
|
||||
#include "td/utils/overloaded.h"
|
||||
#include "td/net/UdpServer.h"
|
||||
#include "keys/encryptor.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -50,6 +51,59 @@ class AdnlNetworkConnectionUdp : public AdnlNetworkConnection {
|
|||
std::unique_ptr<AdnlNetworkConnection::Callback> callback_;
|
||||
};
|
||||
|
||||
class AdnlNetworkConnectionTunnel : public AdnlNetworkConnection {
|
||||
public:
|
||||
void send(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::uint32 priority, td::BufferSlice message) override {
|
||||
if (!encryptor_) {
|
||||
VLOG(ADNL_INFO) << "tunnel: message [" << src << "->" << dst << "to bad tunnel. dropping";
|
||||
return;
|
||||
}
|
||||
auto dataR = encryptor_->encrypt(message.as_slice());
|
||||
if (dataR.is_error()) {
|
||||
VLOG(ADNL_INFO) << "tunnel: message [" << src << "->" << dst << ": failed to encrypt: " << dataR.move_as_error();
|
||||
return;
|
||||
}
|
||||
auto data = dataR.move_as_ok();
|
||||
td::BufferSlice enc_message{data.size() + 32};
|
||||
auto S = enc_message.as_slice();
|
||||
S.copy_from(pub_key_hash_.as_slice());
|
||||
S.remove_prefix(32);
|
||||
S.copy_from(data.as_slice());
|
||||
td::actor::send_closure(adnl_, &Adnl::send_message_ex, src, adnl_id_, std::move(enc_message),
|
||||
Adnl::SendFlags::direct_only);
|
||||
}
|
||||
bool is_alive() const override {
|
||||
return ready_.load(std::memory_order_consume);
|
||||
}
|
||||
bool is_active() const override {
|
||||
return ready_.load(std::memory_order_consume);
|
||||
}
|
||||
void start_up() override {
|
||||
auto R = pub_key_.create_encryptor();
|
||||
if (R.is_error()) {
|
||||
VLOG(ADNL_INFO) << "tunnel: bad public key: " << R.move_as_error();
|
||||
return;
|
||||
}
|
||||
encryptor_ = R.move_as_ok();
|
||||
pub_key_hash_ = pub_key_.compute_short_id();
|
||||
//ready_.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
AdnlNetworkConnectionTunnel(td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
adnl::AdnlNodeIdShort adnl_id, PublicKey pubkey,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback);
|
||||
|
||||
private:
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager_;
|
||||
td::actor::ActorId<Adnl> adnl_;
|
||||
AdnlNodeIdShort adnl_id_;
|
||||
PublicKey pub_key_;
|
||||
PublicKeyHash pub_key_hash_;
|
||||
std::unique_ptr<Encryptor> encryptor_;
|
||||
std::atomic<bool> ready_{false};
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback_;
|
||||
};
|
||||
|
||||
void AdnlNetworkConnectionUdp::send(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::uint32 priority,
|
||||
td::BufferSlice message) {
|
||||
LOG_CHECK(message.size() <= AdnlNetworkManager::get_mtu()) << "dst=" << addr_ << " size=" << message.size();
|
||||
|
@ -71,12 +125,23 @@ AdnlNetworkConnectionUdp::AdnlNetworkConnectionUdp(td::actor::ActorId<AdnlNetwor
|
|||
addr_.init_host_port(td::IPAddress::ipv6_to_str(ip.as_slice()), port).ensure();
|
||||
}
|
||||
|
||||
AdnlNetworkConnectionTunnel::AdnlNetworkConnectionTunnel(td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<Adnl> adnl, adnl::AdnlNodeIdShort adnl_id,
|
||||
PublicKey pubkey,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback)
|
||||
: network_manager_(std::move(network_manager))
|
||||
, adnl_(std::move(adnl))
|
||||
, adnl_id_(adnl_id)
|
||||
, pub_key_(std::move(pubkey))
|
||||
, callback_(std::move(callback)) {
|
||||
}
|
||||
|
||||
AdnlAddressImpl::Hash AdnlAddressImpl::get_hash() const {
|
||||
return get_tl_object_sha_bits256(tl());
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> AdnlAddressUdp::create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const {
|
||||
return td::actor::create_actor<AdnlNetworkConnectionUdp>("udpconn", network_manager, ip_, port_, std::move(callback));
|
||||
}
|
||||
|
@ -87,7 +152,7 @@ AdnlAddressUdp::AdnlAddressUdp(const ton_api::adnl_address_udp &obj) {
|
|||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> AdnlAddressUdp6::create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const {
|
||||
return td::actor::create_actor<AdnlNetworkConnectionUdp>("udpconn", network_manager, ip_, port_, std::move(callback));
|
||||
}
|
||||
|
@ -97,16 +162,24 @@ AdnlAddressUdp6::AdnlAddressUdp6(const ton_api::adnl_address_udp6 &obj) {
|
|||
port_ = static_cast<td::uint16>(obj.port_);
|
||||
}
|
||||
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> AdnlAddressTunnel::create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const {
|
||||
return td::actor::create_actor<AdnlNetworkConnectionTunnel>("tunnelconn", network_manager, adnl, adnl_id_, pub_key_,
|
||||
std::move(callback));
|
||||
}
|
||||
AdnlAddressTunnel::AdnlAddressTunnel(const ton_api::adnl_address_tunnel &obj) {
|
||||
adnl_id_ = AdnlNodeIdShort{obj.to_};
|
||||
pub_key_ = ton::PublicKey{obj.pubkey_};
|
||||
}
|
||||
|
||||
td::Ref<AdnlAddressImpl> AdnlAddressImpl::create(const tl_object_ptr<ton_api::adnl_Address> &addr) {
|
||||
td::Ref<AdnlAddressImpl> res = td::Ref<AdnlAddressImpl>{};
|
||||
ton_api::downcast_call(*const_cast<ton_api::adnl_Address *>(addr.get()),
|
||||
td::overloaded(
|
||||
[&](const ton_api::adnl_address_udp &obj) {
|
||||
res = td::Ref<AdnlAddressUdp>{true, obj};
|
||||
},
|
||||
[&](const ton_api::adnl_address_udp6 &obj) {
|
||||
res = td::Ref<AdnlAddressUdp6>{true, obj};
|
||||
}));
|
||||
ton_api::downcast_call(
|
||||
*const_cast<ton_api::adnl_Address *>(addr.get()),
|
||||
td::overloaded([&](const ton_api::adnl_address_udp &obj) { res = td::make_ref<AdnlAddressUdp>(obj); },
|
||||
[&](const ton_api::adnl_address_udp6 &obj) { res = td::make_ref<AdnlAddressUdp6>(obj); },
|
||||
[&](const ton_api::adnl_address_tunnel &obj) { res = td::make_ref<AdnlAddressTunnel>(obj); }));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace ton {
|
|||
|
||||
namespace adnl {
|
||||
|
||||
class Adnl;
|
||||
|
||||
class AdnlAddressImpl : public td::CntObject {
|
||||
public:
|
||||
using Hash = td::Bits256;
|
||||
|
@ -35,7 +37,7 @@ class AdnlAddressImpl : public td::CntObject {
|
|||
virtual td::uint32 serialized_size() const = 0;
|
||||
virtual tl_object_ptr<ton_api::adnl_Address> tl() const = 0;
|
||||
virtual td::actor::ActorOwn<AdnlNetworkConnection> create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const = 0;
|
||||
|
||||
static td::Ref<AdnlAddressImpl> create(const tl_object_ptr<ton_api::adnl_Address> &addr);
|
||||
|
|
|
@ -51,7 +51,7 @@ class AdnlAddressUdp : public AdnlAddressImpl {
|
|||
return create_tl_object<ton_api::adnl_address_udp>(ip_, port_);
|
||||
}
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const override;
|
||||
};
|
||||
|
||||
|
@ -81,7 +81,38 @@ class AdnlAddressUdp6 : public AdnlAddressImpl {
|
|||
return create_tl_object<ton_api::adnl_address_udp6>(ip_, port_);
|
||||
}
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const override;
|
||||
};
|
||||
|
||||
class AdnlAddressTunnel : public AdnlAddressImpl {
|
||||
private:
|
||||
AdnlNodeIdShort adnl_id_;
|
||||
PublicKey pub_key_;
|
||||
|
||||
public:
|
||||
explicit AdnlAddressTunnel(const ton_api::adnl_address_tunnel &obj);
|
||||
|
||||
AdnlAddressTunnel(AdnlNodeIdShort adnl_id, PublicKey pub_key)
|
||||
: adnl_id_(std::move(adnl_id)), pub_key_(std::move(pub_key)) {
|
||||
}
|
||||
|
||||
AdnlAddressTunnel *make_copy() const override {
|
||||
return new AdnlAddressTunnel{*this};
|
||||
}
|
||||
|
||||
bool is_public() const override {
|
||||
return false;
|
||||
}
|
||||
td::uint32 serialized_size() const override {
|
||||
return 4 + 32 + pub_key_.serialized_size();
|
||||
}
|
||||
|
||||
tl_object_ptr<ton_api::adnl_Address> tl() const override {
|
||||
return create_tl_object<ton_api::adnl_address_tunnel>(adnl_id_.bits256_value(), pub_key_.tl());
|
||||
}
|
||||
td::actor::ActorOwn<AdnlNetworkConnection> create_connection(
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl,
|
||||
std::unique_ptr<AdnlNetworkConnection::Callback> callback) const override;
|
||||
};
|
||||
|
||||
|
|
|
@ -249,6 +249,40 @@ class AdnlMessage {
|
|||
}
|
||||
};
|
||||
|
||||
class OutboundAdnlMessage {
|
||||
public:
|
||||
template <class T>
|
||||
OutboundAdnlMessage(T m, td::uint32 flags) : message_{std::move(m)}, flags_(flags) {
|
||||
}
|
||||
td::uint32 flags() const {
|
||||
return flags_;
|
||||
}
|
||||
void set_flags(td::uint32 f) {
|
||||
flags_ = f;
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> tl() const {
|
||||
return message_.tl();
|
||||
}
|
||||
td::uint32 size() const {
|
||||
return message_.size();
|
||||
}
|
||||
template <class F>
|
||||
void visit(F &&f) {
|
||||
message_.visit(std::move(f));
|
||||
}
|
||||
template <class F>
|
||||
void visit(F &&f) const {
|
||||
message_.visit(std::move(f));
|
||||
}
|
||||
AdnlMessage release() {
|
||||
return std::move(message_);
|
||||
}
|
||||
|
||||
private:
|
||||
AdnlMessage message_;
|
||||
td::uint32 flags_;
|
||||
};
|
||||
|
||||
class AdnlMessageList {
|
||||
public:
|
||||
AdnlMessageList() {
|
||||
|
@ -291,6 +325,48 @@ class AdnlMessageList {
|
|||
std::vector<AdnlMessage> messages_;
|
||||
};
|
||||
|
||||
class OutboundAdnlMessageList {
|
||||
public:
|
||||
OutboundAdnlMessageList() {
|
||||
}
|
||||
OutboundAdnlMessageList(tl_object_ptr<ton_api::adnl_Message> message, td::uint32 flags) {
|
||||
auto msg = OutboundAdnlMessage{std::move(message), flags};
|
||||
messages_.emplace_back(std::move(msg));
|
||||
}
|
||||
OutboundAdnlMessageList(std::vector<tl_object_ptr<ton_api::adnl_Message>> messages, td::uint32 flags) {
|
||||
for (auto &message : messages) {
|
||||
messages_.push_back(OutboundAdnlMessage{std::move(message), flags});
|
||||
}
|
||||
}
|
||||
void push_back(OutboundAdnlMessage message) {
|
||||
messages_.push_back(std::move(message));
|
||||
}
|
||||
|
||||
td::uint32 size() const {
|
||||
return static_cast<td::uint32>(messages_.size());
|
||||
}
|
||||
tl_object_ptr<ton_api::adnl_Message> one_message() const {
|
||||
CHECK(size() == 1);
|
||||
return messages_[0].tl();
|
||||
}
|
||||
std::vector<tl_object_ptr<ton_api::adnl_Message>> mult_messages() const {
|
||||
std::vector<tl_object_ptr<ton_api::adnl_Message>> vec;
|
||||
for (auto &m : messages_) {
|
||||
vec.emplace_back(m.tl());
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
static std::vector<tl_object_ptr<ton_api::adnl_Message>> empty_vector() {
|
||||
return std::vector<tl_object_ptr<ton_api::adnl_Message>>{};
|
||||
}
|
||||
auto &vector() {
|
||||
return messages_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<OutboundAdnlMessage> messages_;
|
||||
};
|
||||
|
||||
} // namespace adnl
|
||||
|
||||
} // namespace ton
|
||||
|
|
|
@ -138,7 +138,8 @@ void AdnlPeerTableImpl::add_static_nodes_from_config(AdnlNodesList nodes) {
|
|||
}
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message) {
|
||||
void AdnlPeerTableImpl::send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message,
|
||||
td::uint32 flags) {
|
||||
auto it = peers_.find(dst);
|
||||
|
||||
if (it == peers_.end()) {
|
||||
|
@ -152,7 +153,7 @@ void AdnlPeerTableImpl::send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst
|
|||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeer::send_one_message, src, it2->second.second, it2->second.first.get(),
|
||||
std::move(message));
|
||||
OutboundAdnlMessage{std::move(message), flags});
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id,
|
||||
|
@ -162,7 +163,7 @@ void AdnlPeerTableImpl::answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, A
|
|||
<< "]: message too big: size=" << data.size();
|
||||
return;
|
||||
}
|
||||
send_message_in(src, dst, adnlmessage::AdnlMessageAnswer{query_id, std::move(data)});
|
||||
send_message_in(src, dst, adnlmessage::AdnlMessageAnswer{query_id, std::move(data)}, 0);
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name,
|
||||
|
@ -185,7 +186,7 @@ void AdnlPeerTableImpl::send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std
|
|||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeer::send_query, src, it2->second.second, it2->second.first.get(), name,
|
||||
std::move(promise), timeout, std::move(data));
|
||||
std::move(promise), timeout, std::move(data), 0);
|
||||
}
|
||||
|
||||
void AdnlPeerTableImpl::add_id_ex(AdnlNodeIdFull id, AdnlAddressList addr_list, td::uint32 mode) {
|
||||
|
|
|
@ -91,7 +91,7 @@ class AdnlPeerTable : public Adnl {
|
|||
|
||||
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;
|
||||
virtual void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) = 0;
|
||||
|
||||
virtual void register_channel(AdnlChannelIdShort id, td::actor::ActorId<AdnlChannel> channel) = 0;
|
||||
virtual void unregister_channel(AdnlChannelIdShort id) = 0;
|
||||
|
|
|
@ -45,14 +45,17 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
|
|||
|
||||
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_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) override;
|
||||
void send_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override {
|
||||
send_message_ex(src, dst, std::move(data), 0);
|
||||
}
|
||||
void send_message_ex(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data, td::uint32 flags) override {
|
||||
if (data.size() > huge_packet_max_size()) {
|
||||
VLOG(ADNL_WARNING) << "dropping too big packet [" << src << "->" << dst << "]: size=" << data.size();
|
||||
VLOG(ADNL_WARNING) << "DUMP: " << td::buffer_to_hex(data.as_slice().truncate(128));
|
||||
return;
|
||||
}
|
||||
send_message_in(src, dst, AdnlMessage{adnlmessage::AdnlMessageCustom{std::move(data)}});
|
||||
send_message_in(src, dst, AdnlMessage{adnlmessage::AdnlMessageCustom{std::move(data)}}, flags);
|
||||
}
|
||||
void answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id, td::BufferSlice data) override;
|
||||
void send_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, std::string name, td::Promise<td::BufferSlice> promise,
|
||||
|
|
|
@ -142,7 +142,7 @@ void AdnlPeerPairImpl::receive_packet_checked(AdnlPacket packet) {
|
|||
update_addr_list(packet.priority_addr_list());
|
||||
}
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping IN message old our reinit date " << packet.reinit_date() << " date=" << d;
|
||||
auto M = AdnlMessage{adnlmessage::AdnlMessageNop{}};
|
||||
auto M = OutboundAdnlMessage{adnlmessage::AdnlMessageNop{}, 0};
|
||||
send_message(std::move(M));
|
||||
return;
|
||||
}
|
||||
|
@ -231,113 +231,131 @@ void AdnlPeerPairImpl::deliver_message(AdnlMessage message) {
|
|||
message.visit([&](const auto &obj) { this->process_message(obj); });
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::send_messages_in(std::vector<AdnlMessage> messages, bool allow_postpone) {
|
||||
auto connR = get_conn();
|
||||
if (connR.is_error()) {
|
||||
if (!allow_postpone) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping OUT messages: cannot get conn: " << connR.move_as_error();
|
||||
void AdnlPeerPairImpl::send_messages_in(std::vector<OutboundAdnlMessage> messages, bool allow_postpone) {
|
||||
for (td::int32 idx = 0; idx < 2; idx++) {
|
||||
std::vector<OutboundAdnlMessage> not_sent;
|
||||
|
||||
auto connR = get_conn(idx == 1);
|
||||
if (connR.is_error()) {
|
||||
if (!allow_postpone) {
|
||||
VLOG(ADNL_NOTICE) << this << ": dropping OUT messages: cannot get conn: " << connR.move_as_error();
|
||||
return;
|
||||
}
|
||||
VLOG(ADNL_INFO) << this << ": delaying OUT messages: cannot get conn: " << connR.move_as_error();
|
||||
if (!retry_send_at_) {
|
||||
retry_send_at_.relax(td::Timestamp::in(10.0));
|
||||
alarm_timestamp().relax(retry_send_at_);
|
||||
}
|
||||
for (auto &m : messages) {
|
||||
pending_messages_.push_back(std::move(m));
|
||||
}
|
||||
return;
|
||||
}
|
||||
VLOG(ADNL_INFO) << this << ": delaying OUT messages: cannot get conn: " << connR.move_as_error();
|
||||
if (!retry_send_at_) {
|
||||
retry_send_at_.relax(td::Timestamp::in(10.0));
|
||||
alarm_timestamp().relax(retry_send_at_);
|
||||
auto C = connR.move_as_ok();
|
||||
bool is_direct = C.second;
|
||||
auto conn = std::move(C.first);
|
||||
if (idx == 1) {
|
||||
CHECK(is_direct);
|
||||
}
|
||||
for (auto &m : messages) {
|
||||
pending_messages_.push_back(std::move(m));
|
||||
|
||||
size_t ptr = 0;
|
||||
bool first = true;
|
||||
do {
|
||||
size_t s = (channel_ready_ ? channel_packet_header_max_size() : packet_header_max_size());
|
||||
if (first) {
|
||||
s += 2 * addr_list_max_size();
|
||||
}
|
||||
|
||||
AdnlPacket packet;
|
||||
packet.set_seqno(++out_seqno_);
|
||||
packet.set_confirm_seqno(in_seqno_);
|
||||
|
||||
if (first) {
|
||||
if (!channel_inited_) {
|
||||
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
} else if (!channel_ready_) {
|
||||
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
}
|
||||
|
||||
if (!addr_list_.empty()) {
|
||||
packet.set_received_addr_list_version(addr_list_.version());
|
||||
}
|
||||
if (!priority_addr_list_.empty()) {
|
||||
packet.set_received_priority_addr_list_version(priority_addr_list_.version());
|
||||
}
|
||||
|
||||
while (ptr < messages.size()) {
|
||||
auto &M = messages[ptr];
|
||||
if (!is_direct && (M.flags() & Adnl::SendFlags::direct_only)) {
|
||||
not_sent.push_back(std::move(M));
|
||||
continue;
|
||||
}
|
||||
CHECK(M.size() <= get_mtu());
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(M.release());
|
||||
ptr++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel_ready_) {
|
||||
packet.set_reinit_date(Adnl::adnl_start_time(), reinit_date_);
|
||||
packet.set_source(local_id_);
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
if (!channel_inited_) {
|
||||
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
} else if (!channel_ready_) {
|
||||
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
packet.run_basic_checks().ensure();
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), conn, id = print_id(),
|
||||
via_channel = channel_ready_](td::Result<AdnlPacket> res) {
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << id << ": dropping OUT message: error while creating packet: " << res.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_packet_continue, res.move_as_ok(), conn, via_channel);
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(local_actor_, &AdnlLocalId::update_packet, std::move(packet),
|
||||
!channel_ready_ && ack_seqno_ == 0 && in_seqno_ == 0, !channel_ready_,
|
||||
(first || s + addr_list_max_size() <= AdnlNetworkManager::get_mtu())
|
||||
? peer_recv_addr_list_version_
|
||||
: 0x7fffffff,
|
||||
(first || s + 2 * addr_list_max_size() <= AdnlNetworkManager::get_mtu())
|
||||
? peer_recv_priority_addr_list_version_
|
||||
: 0x7fffffff,
|
||||
std::move(P));
|
||||
first = false;
|
||||
} while (ptr < messages.size());
|
||||
messages = std::move(not_sent);
|
||||
if (!messages.size()) {
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto conn = connR.move_as_ok();
|
||||
|
||||
size_t ptr = 0;
|
||||
bool first = true;
|
||||
do {
|
||||
size_t s = (channel_ready_ ? channel_packet_header_max_size() : packet_header_max_size());
|
||||
if (first) {
|
||||
s += 2 * addr_list_max_size();
|
||||
}
|
||||
|
||||
AdnlPacket packet;
|
||||
packet.set_seqno(++out_seqno_);
|
||||
packet.set_confirm_seqno(in_seqno_);
|
||||
|
||||
if (first) {
|
||||
if (!channel_inited_) {
|
||||
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
} else if (!channel_ready_) {
|
||||
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
}
|
||||
|
||||
if (!addr_list_.empty()) {
|
||||
packet.set_received_addr_list_version(addr_list_.version());
|
||||
}
|
||||
if (!priority_addr_list_.empty()) {
|
||||
packet.set_received_priority_addr_list_version(priority_addr_list_.version());
|
||||
}
|
||||
|
||||
while (ptr < messages.size()) {
|
||||
auto &M = messages[ptr];
|
||||
CHECK(M.size() <= get_mtu());
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
ptr++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel_ready_) {
|
||||
packet.set_reinit_date(Adnl::adnl_start_time(), reinit_date_);
|
||||
packet.set_source(local_id_);
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
if (!channel_inited_) {
|
||||
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
} else if (!channel_ready_) {
|
||||
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
|
||||
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
|
||||
s += M.size();
|
||||
packet.add_message(std::move(M));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
packet.run_basic_checks().ensure();
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), conn, id = print_id(),
|
||||
via_channel = channel_ready_](td::Result<AdnlPacket> res) {
|
||||
if (res.is_error()) {
|
||||
LOG(ERROR) << id << ": dropping OUT message: error while creating packet: " << res.move_as_error();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_packet_continue, res.move_as_ok(), conn, via_channel);
|
||||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(
|
||||
local_actor_, &AdnlLocalId::update_packet, std::move(packet),
|
||||
!channel_ready_ && ack_seqno_ == 0 && in_seqno_ == 0, !channel_ready_,
|
||||
(first || s + addr_list_max_size() <= AdnlNetworkManager::get_mtu()) ? peer_recv_addr_list_version_
|
||||
: 0x7fffffff,
|
||||
(first || s + 2 * addr_list_max_size() <= AdnlNetworkManager::get_mtu()) ? peer_recv_priority_addr_list_version_
|
||||
: 0x7fffffff,
|
||||
std::move(P));
|
||||
first = false;
|
||||
} while (ptr < messages.size());
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::send_messages(std::vector<AdnlMessage> messages) {
|
||||
std::vector<AdnlMessage> new_vec;
|
||||
void AdnlPeerPairImpl::send_messages(std::vector<OutboundAdnlMessage> messages) {
|
||||
std::vector<OutboundAdnlMessage> new_vec;
|
||||
for (auto &M : messages) {
|
||||
if (M.size() <= get_mtu()) {
|
||||
new_vec.push_back(std::move(M));
|
||||
|
@ -357,7 +375,8 @@ void AdnlPeerPairImpl::send_messages(std::vector<AdnlMessage> messages) {
|
|||
}
|
||||
B.confirm_read(data.size());
|
||||
|
||||
new_vec.push_back(AdnlMessage{adnlmessage::AdnlMessagePart{hash, size, offset, std::move(data)}});
|
||||
new_vec.push_back(
|
||||
OutboundAdnlMessage{adnlmessage::AdnlMessagePart{hash, size, offset, std::move(data)}, M.flags()});
|
||||
offset += part_size;
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +421,7 @@ void AdnlPeerPairImpl::send_packet_continue(AdnlPacket packet, td::actor::ActorI
|
|||
}
|
||||
|
||||
void AdnlPeerPairImpl::send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) {
|
||||
td::BufferSlice data, td::uint32 flags) {
|
||||
AdnlQueryId id = AdnlQuery::random_query_id();
|
||||
CHECK(out_queries_.count(id) == 0);
|
||||
|
||||
|
@ -412,7 +431,7 @@ void AdnlPeerPairImpl::send_query(std::string name, td::Promise<td::BufferSlice>
|
|||
|
||||
out_queries_[id] = AdnlQuery::create(std::move(promise), std::move(P), name, timeout, id);
|
||||
|
||||
send_message(adnlmessage::AdnlMessageQuery{id, std::move(data)});
|
||||
send_message(OutboundAdnlMessage{adnlmessage::AdnlMessageQuery{id, std::move(data)}, flags});
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::alarm_query(AdnlQueryId id) {
|
||||
|
@ -499,20 +518,20 @@ void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageReinit &mes
|
|||
}
|
||||
|
||||
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageQuery &message) {
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), query_id = message.query_id()](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(WARNING) << "failed to answer query: " << R.move_as_error();
|
||||
} else {
|
||||
auto data = R.move_as_ok();
|
||||
if (data.size() > Adnl::huge_packet_max_size()) {
|
||||
LOG(WARNING) << "dropping too big answer query: size=" << data.size();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_message,
|
||||
AdnlMessage{adnlmessage::AdnlMessageAnswer{query_id, std::move(data)}});
|
||||
}
|
||||
}
|
||||
});
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), query_id = message.query_id(),
|
||||
flags = static_cast<td::uint32>(0)](td::Result<td::BufferSlice> R) {
|
||||
if (R.is_error()) {
|
||||
LOG(WARNING) << "failed to answer query: " << R.move_as_error();
|
||||
} else {
|
||||
auto data = R.move_as_ok();
|
||||
if (data.size() > Adnl::huge_packet_max_size()) {
|
||||
LOG(WARNING) << "dropping too big answer query: size=" << data.size();
|
||||
} else {
|
||||
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_message,
|
||||
OutboundAdnlMessage{adnlmessage::AdnlMessageAnswer{query_id, std::move(data)}, flags});
|
||||
}
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(local_actor_, &AdnlLocalId::deliver_query, peer_id_short_, message.data(), std::move(P));
|
||||
}
|
||||
|
||||
|
@ -625,7 +644,7 @@ void AdnlPeerPairImpl::reinit(td::int32 date) {
|
|||
}
|
||||
}
|
||||
|
||||
td::Result<td::actor::ActorId<AdnlNetworkConnection>> AdnlPeerPairImpl::get_conn() {
|
||||
td::Result<std::pair<td::actor::ActorId<AdnlNetworkConnection>, bool>> AdnlPeerPairImpl::get_conn(bool direct_only) {
|
||||
if (!priority_addr_list_.empty() && priority_addr_list_.expire_at() < td::Clocks::system()) {
|
||||
priority_addr_list_ = AdnlAddressList{};
|
||||
priority_conns_.clear();
|
||||
|
@ -639,13 +658,13 @@ td::Result<td::actor::ActorId<AdnlNetworkConnection>> AdnlPeerPairImpl::get_conn
|
|||
}
|
||||
|
||||
for (auto &conn : priority_conns_) {
|
||||
if (conn.ready()) {
|
||||
return conn.conn.get();
|
||||
if (conn.ready() && (!direct_only || conn.is_direct())) {
|
||||
return std::make_pair(conn.conn.get(), conn.is_direct());
|
||||
}
|
||||
}
|
||||
for (auto &conn : conns_) {
|
||||
if (conn.ready()) {
|
||||
return conn.conn.get();
|
||||
if (conn.ready() && (!direct_only || conn.is_direct())) {
|
||||
return std::make_pair(conn.conn.get(), conn.is_direct());
|
||||
}
|
||||
}
|
||||
return td::Status::Error(ErrorCode::notready, "no active connections");
|
||||
|
@ -695,7 +714,7 @@ void AdnlPeerPairImpl::update_addr_list(AdnlAddressList addr_list) {
|
|||
if (idx < old_conns.size() && old_conns[idx].addr->get_hash() == hash) {
|
||||
conns.push_back(std::move(old_conns[idx]));
|
||||
} else {
|
||||
conns.push_back(Conn{addr, actor_id(this), network_manager_});
|
||||
conns.push_back(Conn{addr, actor_id(this), network_manager_, peer_table_});
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
@ -718,10 +737,11 @@ void AdnlPeerImpl::update_id(AdnlNodeIdFull id) {
|
|||
}
|
||||
|
||||
void AdnlPeerPairImpl::Conn::create_conn(td::actor::ActorId<AdnlPeerPairImpl> peer,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager) {
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<Adnl> adnl) {
|
||||
auto id = addr->get_hash();
|
||||
|
||||
conn = addr->create_connection(network_manager, std::make_unique<ConnCallback>(peer, id));
|
||||
conn = addr->create_connection(network_manager, adnl, std::make_unique<ConnCallback>(peer, id));
|
||||
}
|
||||
|
||||
void AdnlPeerPairImpl::conn_change_state(AdnlConnectionIdShort id, bool ready) {
|
||||
|
@ -771,7 +791,7 @@ void AdnlPeerImpl::receive_packet(AdnlNodeIdShort dst, td::uint32 dst_mode, td::
|
|||
}
|
||||
|
||||
void AdnlPeerImpl::send_messages(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::vector<AdnlMessage> messages) {
|
||||
std::vector<OutboundAdnlMessage> messages) {
|
||||
auto it = peer_pairs_.find(src);
|
||||
if (it == peer_pairs_.end()) {
|
||||
auto X = AdnlPeerPair::create(network_manager_, peer_table_, src_mode, src_actor, actor_id(this), dht_node_, src,
|
||||
|
@ -790,7 +810,7 @@ void AdnlPeerImpl::send_messages(AdnlNodeIdShort src, td::uint32 src_mode, td::a
|
|||
|
||||
void AdnlPeerImpl::send_query(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) {
|
||||
td::BufferSlice data, td::uint32 flags) {
|
||||
auto it = peer_pairs_.find(src);
|
||||
if (it == peer_pairs_.end()) {
|
||||
auto X = AdnlPeerPair::create(network_manager_, peer_table_, src_mode, src_actor, actor_id(this), dht_node_, src,
|
||||
|
@ -804,7 +824,8 @@ void AdnlPeerImpl::send_query(AdnlNodeIdShort src, td::uint32 src_mode, td::acto
|
|||
}
|
||||
}
|
||||
|
||||
td::actor::send_closure(it->second, &AdnlPeerPair::send_query, name, std::move(promise), timeout, std::move(data));
|
||||
td::actor::send_closure(it->second, &AdnlPeerPair::send_query, name, std::move(promise), timeout, std::move(data),
|
||||
flags);
|
||||
}
|
||||
|
||||
void AdnlPeerImpl::del_local_id(AdnlNodeIdShort local_id) {
|
||||
|
|
|
@ -43,9 +43,9 @@ class AdnlPeerPair : public td::actor::Actor {
|
|||
virtual void receive_packet_checked(AdnlPacket packet) = 0;
|
||||
virtual void receive_packet(AdnlPacket packet) = 0;
|
||||
|
||||
virtual void send_messages(std::vector<AdnlMessage> message) = 0;
|
||||
inline void send_message(AdnlMessage message) {
|
||||
std::vector<AdnlMessage> vec;
|
||||
virtual void send_messages(std::vector<OutboundAdnlMessage> message) = 0;
|
||||
inline void send_message(OutboundAdnlMessage message) {
|
||||
std::vector<OutboundAdnlMessage> vec;
|
||||
vec.push_back(std::move(message));
|
||||
send_messages(std::move(vec));
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class AdnlPeerPair : public td::actor::Actor {
|
|||
return Adnl::get_mtu() + 128;
|
||||
}
|
||||
virtual void send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) = 0;
|
||||
td::BufferSlice data, td::uint32 flags) = 0;
|
||||
virtual void alarm_query(AdnlQueryId query_id) = 0;
|
||||
virtual void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) = 0;
|
||||
virtual void update_peer_id(AdnlNodeIdFull id) = 0;
|
||||
|
@ -72,20 +72,20 @@ class AdnlPeer : public td::actor::Actor {
|
|||
virtual void receive_packet(AdnlNodeIdShort dst, td::uint32 dst_mode, td::actor::ActorId<AdnlLocalId> dst_actor,
|
||||
AdnlPacket message) = 0;
|
||||
virtual void send_messages(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::vector<AdnlMessage> messages) = 0;
|
||||
std::vector<OutboundAdnlMessage> messages) = 0;
|
||||
virtual void send_query(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) = 0;
|
||||
td::BufferSlice data, td::uint32 flags) = 0;
|
||||
void send_one_message(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
AdnlMessage message) {
|
||||
std::vector<AdnlMessage> vec;
|
||||
OutboundAdnlMessage message) {
|
||||
std::vector<OutboundAdnlMessage> vec;
|
||||
vec.push_back(std::move(message));
|
||||
send_messages(src, src_mode, src_actor, std::move(vec));
|
||||
}
|
||||
|
||||
void send_message(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
td::BufferSlice data) {
|
||||
auto M = AdnlMessage{adnlmessage::AdnlMessageCustom{std::move(data)}};
|
||||
td::BufferSlice data, td::uint32 flags) {
|
||||
auto M = OutboundAdnlMessage{adnlmessage::AdnlMessageCustom{std::move(data)}, flags};
|
||||
send_one_message(src, src_mode, src_actor, std::move(M));
|
||||
}
|
||||
|
||||
|
|
|
@ -71,11 +71,11 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
|
|||
void receive_packet(AdnlPacket packet) override;
|
||||
void deliver_message(AdnlMessage message);
|
||||
|
||||
void send_messages_in(std::vector<AdnlMessage> messages, bool allow_postpone);
|
||||
void send_messages(std::vector<AdnlMessage> messages) override;
|
||||
void send_messages_in(std::vector<OutboundAdnlMessage> messages, bool allow_postpone);
|
||||
void send_messages(std::vector<OutboundAdnlMessage> messages) override;
|
||||
void send_packet_continue(AdnlPacket packet, td::actor::ActorId<AdnlNetworkConnection> conn, bool via_channel);
|
||||
void send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout,
|
||||
td::BufferSlice data) override;
|
||||
void send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data,
|
||||
td::uint32 flags) override;
|
||||
|
||||
void alarm_query(AdnlQueryId id) override;
|
||||
|
||||
|
@ -121,7 +121,7 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
|
|||
|
||||
private:
|
||||
void reinit(td::int32 date);
|
||||
td::Result<td::actor::ActorId<AdnlNetworkConnection>> get_conn();
|
||||
td::Result<std::pair<td::actor::ActorId<AdnlNetworkConnection>, bool>> get_conn(bool direct_only);
|
||||
void create_channel(pubkeys::Ed25519 pub, td::uint32 date);
|
||||
|
||||
bool received_packet(td::uint64 seqno) const {
|
||||
|
@ -170,9 +170,9 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
|
|||
td::actor::ActorOwn<AdnlNetworkConnection> conn;
|
||||
|
||||
Conn(AdnlAddress addr, td::actor::ActorId<AdnlPeerPairImpl> peer,
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager)
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<Adnl> adnl)
|
||||
: addr(std::move(addr)) {
|
||||
create_conn(peer, network_manager);
|
||||
create_conn(peer, network_manager, adnl);
|
||||
}
|
||||
Conn() {
|
||||
}
|
||||
|
@ -181,10 +181,15 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
|
|||
return !conn.empty() && conn.get_actor_unsafe().is_active();
|
||||
}
|
||||
|
||||
void create_conn(td::actor::ActorId<AdnlPeerPairImpl> peer, td::actor::ActorId<AdnlNetworkManager> network_manager);
|
||||
bool is_direct() {
|
||||
return addr->is_public();
|
||||
}
|
||||
|
||||
void create_conn(td::actor::ActorId<AdnlPeerPairImpl> peer, td::actor::ActorId<AdnlNetworkManager> network_manager,
|
||||
td::actor::ActorId<Adnl> adnl);
|
||||
};
|
||||
|
||||
std::vector<AdnlMessage> pending_messages_;
|
||||
std::vector<OutboundAdnlMessage> pending_messages_;
|
||||
|
||||
td::actor::ActorId<AdnlNetworkManager> network_manager_;
|
||||
td::actor::ActorId<AdnlPeerTable> peer_table_;
|
||||
|
@ -250,9 +255,10 @@ class AdnlPeerImpl : public AdnlPeer {
|
|||
void receive_packet(AdnlNodeIdShort dst, td::uint32 dst_mode, td::actor::ActorId<AdnlLocalId> dst_actor,
|
||||
AdnlPacket packet) override;
|
||||
void send_messages(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
|
||||
std::vector<AdnlMessage> messages) override;
|
||||
std::vector<OutboundAdnlMessage> messages) override;
|
||||
void send_query(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor, std::string name,
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data) override;
|
||||
td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data,
|
||||
td::uint32 flags) override;
|
||||
|
||||
void del_local_id(AdnlNodeIdShort local_id) override;
|
||||
void update_id(AdnlNodeIdFull id) override;
|
||||
|
|
|
@ -75,6 +75,11 @@ class Adnl : public AdnlSenderInterface {
|
|||
return 1024 * 8;
|
||||
}
|
||||
|
||||
struct SendFlags {
|
||||
enum Flags : td::uint32 { direct_only = 1 };
|
||||
};
|
||||
virtual void send_message_ex(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data, td::uint32 flags) = 0;
|
||||
|
||||
// adds node to peer table
|
||||
// used mostly from DHT to avoid loops
|
||||
virtual void add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) = 0;
|
||||
|
|
|
@ -48,6 +48,7 @@ set(TON_CRYPTO_SOURCE
|
|||
common/refint.h
|
||||
common/bigexp.h
|
||||
common/util.h
|
||||
common/linalloc.hpp
|
||||
|
||||
ellcurve/Ed25519.h
|
||||
ellcurve/Fp25519.h
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "block/block.h"
|
||||
#include "block/block-auto.h"
|
||||
#include "block/block-parse.h"
|
||||
#include "block/mc-config.h"
|
||||
#include "ton/ton-shard.h"
|
||||
#include "common/bigexp.h"
|
||||
#include "common/util.h"
|
||||
|
@ -1602,33 +1603,46 @@ bool check_one_config_param(Ref<vm::CellSlice> cs_ref, td::ConstBitPtr key, td::
|
|||
|
||||
const int mandatory_config_params[] = {18, 20, 21, 22, 23, 24, 25, 28, 34};
|
||||
|
||||
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors, bool relax_par0) {
|
||||
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors, bool relax_par0,
|
||||
Ref<vm::Cell> old_mparams) {
|
||||
using namespace std::placeholders;
|
||||
if (cell.is_null()) {
|
||||
return false;
|
||||
}
|
||||
if (!catch_errors) {
|
||||
vm::Dictionary dict{std::move(cell), 32};
|
||||
for (int x : mandatory_config_params) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
|
||||
return false;
|
||||
}
|
||||
if (catch_errors) {
|
||||
try {
|
||||
return valid_config_data(std::move(cell), addr, false, relax_par0, std::move(old_mparams));
|
||||
} catch (vm::VmError&) {
|
||||
return false;
|
||||
}
|
||||
return dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0));
|
||||
}
|
||||
try {
|
||||
vm::Dictionary dict{std::move(cell), 32};
|
||||
for (int x : mandatory_config_params) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0));
|
||||
} catch (vm::VmError&) {
|
||||
vm::Dictionary dict{std::move(cell), 32};
|
||||
if (!dict.check_for_each(std::bind(check_one_config_param, _1, _2, addr.cbits(), relax_par0))) {
|
||||
return false;
|
||||
}
|
||||
for (int x : mandatory_config_params) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "mandatory configuration parameter #" << x << " is missing";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return config_params_present(dict, dict.lookup_ref(td::BitArray<32>{9})) &&
|
||||
config_params_present(dict, std::move(old_mparams));
|
||||
}
|
||||
|
||||
bool config_params_present(vm::Dictionary& dict, Ref<vm::Cell> param_dict_root) {
|
||||
auto res = block::Config::unpack_param_dict(std::move(param_dict_root));
|
||||
if (res.is_error()) {
|
||||
return false;
|
||||
}
|
||||
for (int x : res.move_as_ok()) {
|
||||
if (!dict.int_key_exists(x)) {
|
||||
LOG(ERROR) << "configuration parameter #" << x
|
||||
<< " (declared as mandatory in configuration parameter #9) is missing";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool add_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res) {
|
||||
|
|
|
@ -606,7 +606,8 @@ bool unpack_CurrencyCollection(Ref<vm::CellSlice> csr, td::RefInt256& value, Ref
|
|||
bool valid_library_collection(Ref<vm::Cell> cell, bool catch_errors = true);
|
||||
|
||||
bool valid_config_data(Ref<vm::Cell> cell, const td::BitArray<256>& addr, bool catch_errors = true,
|
||||
bool relax_par0 = false);
|
||||
bool relax_par0 = false, Ref<vm::Cell> old_mparams = {});
|
||||
bool config_params_present(vm::Dictionary& dict, Ref<vm::Cell> param_dict_root);
|
||||
|
||||
bool add_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res);
|
||||
bool sub_extra_currency(Ref<vm::Cell> extra1, Ref<vm::Cell> extra2, Ref<vm::Cell>& res);
|
||||
|
|
|
@ -572,6 +572,7 @@ _ to_mint:ExtraCurrencyCollection = ConfigParam 7;
|
|||
capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion;
|
||||
_ GlobalVersion = ConfigParam 8; // all zero if absent
|
||||
_ mandatory_params:(Hashmap 32 True) = ConfigParam 9;
|
||||
_ critical_params:(Hashmap 32 True) = ConfigParam 10;
|
||||
|
||||
wfmt_basic#1 vm_version:int32 vm_mode:uint64 = WorkchainFormat 1;
|
||||
wfmt_ext#0 min_addr_len:(## 12) max_addr_len:(## 12) addr_len_step:(## 12)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
namespace block {
|
||||
using namespace std::literals::string_literals;
|
||||
using td::Ref;
|
||||
|
||||
Config::Config(Ref<vm::Cell> config_root, const td::Bits256& config_addr, int _mode)
|
||||
|
@ -335,6 +336,59 @@ std::unique_ptr<vm::Dictionary> ShardConfig::extract_shard_hashes_dict(Ref<vm::C
|
|||
}
|
||||
}
|
||||
|
||||
td::Result<std::vector<int>> Config::unpack_param_dict(vm::Dictionary& dict) {
|
||||
try {
|
||||
std::vector<int> vect;
|
||||
if (dict.check_for_each(
|
||||
[&vect](Ref<vm::CellSlice> value, td::ConstBitPtr key, int key_len) {
|
||||
bool ok = (key_len == 32 && value->empty_ext());
|
||||
if (ok) {
|
||||
vect.push_back((int)key.get_int(32));
|
||||
}
|
||||
return ok;
|
||||
},
|
||||
true)) {
|
||||
return std::move(vect);
|
||||
} else {
|
||||
return td::Status::Error("invalid parameter list dictionary");
|
||||
}
|
||||
} catch (vm::VmError& vme) {
|
||||
return td::Status::Error("error unpacking parameter list dictionary: "s + vme.get_msg());
|
||||
}
|
||||
}
|
||||
|
||||
td::Result<std::vector<int>> Config::unpack_param_dict(Ref<vm::Cell> dict_root) {
|
||||
vm::Dictionary dict{std::move(dict_root), 32};
|
||||
return unpack_param_dict(dict);
|
||||
}
|
||||
|
||||
std::unique_ptr<vm::Dictionary> Config::get_param_dict(int idx) const {
|
||||
return std::make_unique<vm::Dictionary>(get_config_param(idx), 32);
|
||||
}
|
||||
|
||||
td::Result<std::vector<int>> Config::unpack_param_list(int idx) const {
|
||||
return unpack_param_dict(*get_param_dict(idx));
|
||||
}
|
||||
|
||||
bool Config::all_mandatory_params_defined(int* bad_idx_ptr) const {
|
||||
auto res = get_mandatory_param_list();
|
||||
if (res.is_error()) {
|
||||
if (bad_idx_ptr) {
|
||||
*bad_idx_ptr = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (int x : res.move_as_ok()) {
|
||||
if (get_config_param(x).is_null()) {
|
||||
if (bad_idx_ptr) {
|
||||
*bad_idx_ptr = x;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<vm::AugmentedDictionary> ConfigInfo::create_accounts_dict() const {
|
||||
if (mode & needAccountsRoot) {
|
||||
return std::make_unique<vm::AugmentedDictionary>(accounts_root, 256, block::tlb::aug_ShardAccounts);
|
||||
|
|
|
@ -534,6 +534,21 @@ class Config {
|
|||
bool create_stats_enabled() const {
|
||||
return has_capability(ton::capCreateStatsEnabled);
|
||||
}
|
||||
std::unique_ptr<vm::Dictionary> get_param_dict(int idx) const;
|
||||
td::Result<std::vector<int>> unpack_param_list(int idx) const;
|
||||
std::unique_ptr<vm::Dictionary> get_mandatory_param_dict() const {
|
||||
return get_param_dict(9);
|
||||
}
|
||||
std::unique_ptr<vm::Dictionary> get_critical_param_dict() const {
|
||||
return get_param_dict(10);
|
||||
}
|
||||
td::Result<std::vector<int>> get_mandatory_param_list() const {
|
||||
return unpack_param_list(9);
|
||||
}
|
||||
td::Result<std::vector<int>> get_critical_param_list() const {
|
||||
return unpack_param_list(10);
|
||||
}
|
||||
bool all_mandatory_params_defined(int* bad_idx_ptr = nullptr) const;
|
||||
td::Result<ton::StdSmcAddress> get_dns_root_addr() const;
|
||||
bool set_block_id_ext(const ton::BlockIdExt& block_id_ext);
|
||||
td::Result<std::vector<ton::StdSmcAddress>> get_special_smartcontracts(bool without_config = false) const;
|
||||
|
@ -580,6 +595,8 @@ class Config {
|
|||
static td::Result<std::unique_ptr<Config>> extract_from_state(Ref<vm::Cell> mc_state_root, int mode = 0);
|
||||
static td::Result<std::unique_ptr<Config>> extract_from_key_block(Ref<vm::Cell> key_block_root, int mode = 0);
|
||||
static td::Result<std::pair<ton::UnixTime, ton::UnixTime>> unpack_validator_set_start_stop(Ref<vm::Cell> root);
|
||||
static td::Result<std::vector<int>> unpack_param_dict(vm::Dictionary& dict);
|
||||
static td::Result<std::vector<int>> unpack_param_dict(Ref<vm::Cell> dict_root);
|
||||
|
||||
protected:
|
||||
Config(int _mode) : mode(_mode) {
|
||||
|
|
50
crypto/common/linalloc.hpp
Normal file
50
crypto/common/linalloc.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2020 Telegram Systems LLP
|
||||
*/
|
||||
namespace td {
|
||||
|
||||
class LinearAllocator {
|
||||
std::size_t size;
|
||||
char *ptr, *cur, *end;
|
||||
|
||||
public:
|
||||
LinearAllocator(std::size_t _size) : size(_size) {
|
||||
cur = ptr = (char*)malloc(size);
|
||||
if (!ptr) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
end = ptr + size;
|
||||
}
|
||||
~LinearAllocator() {
|
||||
free(ptr);
|
||||
}
|
||||
void* allocate(std::size_t count) {
|
||||
char* t = cur;
|
||||
cur += (count + 7) & -8;
|
||||
if (cur > end) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return (void*)t;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
||||
inline void* operator new(std::size_t count, td::LinearAllocator& alloc) {
|
||||
return alloc.allocate(count);
|
||||
}
|
|
@ -1288,7 +1288,9 @@ void parse_func_def(Lexer& lex) {
|
|||
sym::close_scope(lex);
|
||||
}
|
||||
|
||||
bool parse_source(std::istream* is, const src::FileDescr* fdescr) {
|
||||
std::vector<const src::FileDescr*> source_fdescr;
|
||||
|
||||
bool parse_source(std::istream* is, src::FileDescr* fdescr) {
|
||||
src::SourceReader reader{is, fdescr};
|
||||
Lexer lex{reader, true, ";,()[] ~."};
|
||||
while (lex.tp() != _Eof) {
|
||||
|
@ -1306,6 +1308,7 @@ bool parse_source_file(const char* filename) {
|
|||
throw src::Fatal{"source file name is an empty string"};
|
||||
}
|
||||
src::FileDescr* cur_source = new src::FileDescr{filename};
|
||||
source_fdescr.push_back(cur_source);
|
||||
std::ifstream ifs{filename};
|
||||
if (ifs.fail()) {
|
||||
throw src::Fatal{std::string{"cannot open source file `"} + filename + "`"};
|
||||
|
@ -1314,7 +1317,9 @@ bool parse_source_file(const char* filename) {
|
|||
}
|
||||
|
||||
bool parse_source_stdin() {
|
||||
return parse_source(&std::cin, new src::FileDescr{"stdin", true});
|
||||
src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
|
||||
source_fdescr.push_back(cur_source);
|
||||
return parse_source(&std::cin, cur_source);
|
||||
}
|
||||
|
||||
} // namespace funC
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
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 "srcread.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace src {
|
||||
|
||||
|
@ -34,9 +35,47 @@ std::ostream& operator<<(std::ostream& os, const Fatal& fatal) {
|
|||
return os << fatal.get_msg();
|
||||
}
|
||||
|
||||
const char* FileDescr::convert_offset(long offset, long* line_no, long* line_pos, long* line_size) const {
|
||||
long lno = 0, lpos = -1, lsize = 0;
|
||||
const char* lstart = nullptr;
|
||||
if (offset >= 0 && offset < (long)text.size()) {
|
||||
auto it = std::upper_bound(line_offs.begin(), line_offs.end(), offset);
|
||||
lno = it - line_offs.begin();
|
||||
if (lno && it != line_offs.end()) {
|
||||
lsize = it[0] - it[-1];
|
||||
lpos = offset - it[-1];
|
||||
lstart = text.data() + it[-1];
|
||||
}
|
||||
} else {
|
||||
lno = (long)line_offs.size();
|
||||
}
|
||||
if (line_no) {
|
||||
*line_no = lno;
|
||||
}
|
||||
if (line_pos) {
|
||||
*line_pos = lpos;
|
||||
}
|
||||
if (line_size) {
|
||||
*line_size = lsize;
|
||||
}
|
||||
return lstart;
|
||||
}
|
||||
|
||||
const char* FileDescr::push_line(std::string new_line) {
|
||||
if (line_offs.empty()) {
|
||||
line_offs.push_back(0);
|
||||
}
|
||||
std::size_t cur_size = text.size();
|
||||
text += new_line;
|
||||
text += '\0';
|
||||
line_offs.push_back((long)text.size());
|
||||
return text.data() + cur_size;
|
||||
}
|
||||
|
||||
void SrcLocation::show(std::ostream& os) const {
|
||||
os << fdescr;
|
||||
if (line_no > 0) {
|
||||
long line_no, line_pos;
|
||||
if (fdescr && convert_pos(&line_no, &line_pos)) {
|
||||
os << ':' << line_no;
|
||||
if (line_pos >= 0) {
|
||||
os << ':' << (line_pos + 1);
|
||||
|
@ -45,13 +84,15 @@ void SrcLocation::show(std::ostream& os) const {
|
|||
}
|
||||
|
||||
bool SrcLocation::show_context(std::ostream& os) const {
|
||||
if (text.empty() || line_pos < 0 || (unsigned)line_pos > text.size()) {
|
||||
long line_no, line_pos, line_size;
|
||||
if (!fdescr || !convert_pos(&line_no, &line_pos, &line_size)) {
|
||||
return false;
|
||||
}
|
||||
bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < text.size());
|
||||
const char* start = skip_left ? text.c_str() + line_pos - 100 : text.c_str();
|
||||
const char* end = skip_right ? text.c_str() + line_pos + 100 : text.c_str() + text.size();
|
||||
const char* here = text.c_str() + line_pos;
|
||||
bool skip_left = (line_pos > 200), skip_right = (line_pos + 200u < line_size);
|
||||
const char* here = fdescr->text.data() + char_offs;
|
||||
const char* base = here - line_pos;
|
||||
const char* start = skip_left ? here - 100 : base;
|
||||
const char* end = skip_right ? here + 100 : base + line_size;
|
||||
os << " ";
|
||||
if (skip_left) {
|
||||
os << "... ";
|
||||
|
@ -99,8 +140,8 @@ void ParseError::show(std::ostream& os) const {
|
|||
where.show_context(os);
|
||||
}
|
||||
|
||||
SourceReader::SourceReader(std::istream* _is, const FileDescr* _fdescr)
|
||||
: ifs(_is), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) {
|
||||
SourceReader::SourceReader(std::istream* _is, FileDescr* _fdescr)
|
||||
: ifs(_is), fdescr(_fdescr), loc(_fdescr), eof(false), cur_line_len(0), start(0), cur(0), end(0) {
|
||||
load_line();
|
||||
}
|
||||
|
||||
|
@ -139,7 +180,7 @@ const char* SourceReader::set_ptr(const char* ptr) {
|
|||
if (ptr < cur || ptr > end) {
|
||||
error("parsing position went outside of line");
|
||||
}
|
||||
loc.line_pos = (int)(ptr - start);
|
||||
loc.char_offs += ptr - cur;
|
||||
cur = ptr;
|
||||
}
|
||||
return ptr;
|
||||
|
@ -149,12 +190,11 @@ bool SourceReader::load_line() {
|
|||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
loc.set_eof();
|
||||
if (ifs->eof()) {
|
||||
set_eof();
|
||||
return false;
|
||||
}
|
||||
++loc.line_no;
|
||||
loc.line_pos = -1;
|
||||
std::getline(*ifs, cur_line);
|
||||
if (ifs->fail()) {
|
||||
set_eof();
|
||||
|
@ -174,11 +214,16 @@ bool SourceReader::load_line() {
|
|||
cur_line.pop_back();
|
||||
--len;
|
||||
}
|
||||
loc.text = cur_line;
|
||||
cur_line_len = (int)len;
|
||||
loc.line_pos = 0;
|
||||
cur = start = cur_line.c_str();
|
||||
end = start + cur_line_len;
|
||||
if (fdescr) {
|
||||
cur = start = fdescr->push_line(std::move(cur_line));
|
||||
end = start + len;
|
||||
loc.char_offs = (std::size_t)(cur - fdescr->text.data());
|
||||
cur_line.clear();
|
||||
} else {
|
||||
cur = start = cur_line.c_str();
|
||||
end = start + cur_line_len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace src {
|
||||
|
@ -31,9 +32,13 @@ namespace src {
|
|||
|
||||
struct FileDescr {
|
||||
std::string filename;
|
||||
std::string text;
|
||||
std::vector<long> line_offs;
|
||||
bool is_stdin;
|
||||
FileDescr(std::string _fname, bool _stdin = false) : filename(std::move(_fname)), is_stdin(_stdin) {
|
||||
}
|
||||
const char* push_line(std::string new_line);
|
||||
const char* convert_offset(long offset, long* line_no, long* line_pos, long* line_size = nullptr) const;
|
||||
};
|
||||
|
||||
struct Fatal {
|
||||
|
@ -49,16 +54,23 @@ std::ostream& operator<<(std::ostream& os, const Fatal& fatal);
|
|||
|
||||
struct SrcLocation {
|
||||
const FileDescr* fdescr;
|
||||
int line_no;
|
||||
int line_pos;
|
||||
std::string text;
|
||||
SrcLocation() : fdescr(nullptr), line_no(0), line_pos(-1) {
|
||||
long char_offs;
|
||||
SrcLocation() : fdescr(nullptr), char_offs(-1) {
|
||||
}
|
||||
SrcLocation(const FileDescr* _fdescr, int line = 0, int pos = -1) : fdescr(_fdescr), line_no(line), line_pos(pos) {
|
||||
SrcLocation(const FileDescr* _fdescr, long offs = -1) : fdescr(_fdescr), char_offs(-1) {
|
||||
}
|
||||
bool defined() const {
|
||||
return fdescr;
|
||||
}
|
||||
bool eof() const {
|
||||
return char_offs == -1;
|
||||
}
|
||||
void set_eof() {
|
||||
char_offs = -1;
|
||||
}
|
||||
const char* convert_pos(long* line_no, long* line_pos, long* line_size = nullptr) const {
|
||||
return defined() ? fdescr->convert_offset(char_offs, line_no, line_pos, line_size) : nullptr;
|
||||
}
|
||||
void show(std::ostream& os) const;
|
||||
bool show_context(std::ostream& os) const;
|
||||
void show_gen_error(std::ostream& os, std::string message, std::string err_type = "") const;
|
||||
|
@ -98,6 +110,7 @@ struct ParseError : Error {
|
|||
|
||||
class SourceReader {
|
||||
std::istream* ifs;
|
||||
FileDescr* fdescr;
|
||||
SrcLocation loc;
|
||||
bool eof;
|
||||
std::string cur_line;
|
||||
|
@ -106,7 +119,7 @@ class SourceReader {
|
|||
const char *start, *cur, *end;
|
||||
|
||||
public:
|
||||
SourceReader(std::istream* _is, const FileDescr* _fdescr);
|
||||
SourceReader(std::istream* _is, FileDescr* _fdescr);
|
||||
bool load_line();
|
||||
bool is_eof() const {
|
||||
return eof;
|
||||
|
|
|
@ -52,43 +52,50 @@
|
|||
// elected-for elections-begin-before elections-end-before stakes-frozen
|
||||
{ 4 0 reverse <b { swap 32 u, } 4 times b> 15 config! } : config.election_params!
|
||||
|
||||
dictnew 0 2constant validator-dict
|
||||
{ @' validator-dict } : validator-dict@
|
||||
{ validator-dict@ nip } : validator#
|
||||
variable validator-dict
|
||||
dictnew 0 validator-dict 2!
|
||||
{ validator-dict @ second } : validator#
|
||||
// val-pubkey weight --
|
||||
{ dup 0<= abort"validator weight must be non-negative"
|
||||
dup 64 ufits not abort"validator weight must fit into 64 bits"
|
||||
over Blen 32 <> abort"validator public key must be 32 bytes long"
|
||||
<b x{538e81278a} s, rot B, swap 64 u, b> <s
|
||||
validator-dict@ dup 1+ 3 -roll swap
|
||||
validator-dict 2@ dup 1+ 3 -roll swap
|
||||
16 udict!+ 0= abort"cannot add validator"
|
||||
swap 2 'nop does : validator-dict
|
||||
swap validator-dict 2!
|
||||
} : add-validator
|
||||
// since-ut until-ut main-val-cnt-or-0 --
|
||||
{ ?dup 0= { validator# } if
|
||||
validator# 0= abort"no initial validators defined"
|
||||
rot <b x{11} s, swap 32 u, rot 32 u, validator# 16 u, swap 16 u,
|
||||
validator-dict@ drop <s s, b>
|
||||
validator-dict @ first <s s, b>
|
||||
34 config!
|
||||
} : config.validators!
|
||||
|
||||
dictnew constant workchain-dict
|
||||
variable workchain-dict
|
||||
// root-hash file-hash enable-utime actual-min-split min-split max-split workchain-id --
|
||||
{ <b x{a6} s, 5 roll 32 u, 4 roll 8 u, 3 roll 8 u, rot 8 u, x{e000} s,
|
||||
3 roll 256 u, rot 256 u, 0 32 u, x{1} s, -1 32 i, 0 64 u, b>
|
||||
dup isWorkchainDescr? not abort"invalid WorkchainDescr created"
|
||||
<s swap @' workchain-dict 32 idict!+ 0= abort"cannot add workchain"
|
||||
=: workchain-dict
|
||||
<s swap workchain-dict @ 32 idict!+ 0= abort"cannot add workchain"
|
||||
workchain-dict !
|
||||
} : add-std-workchain
|
||||
// --
|
||||
{ @' workchain-dict dict>s s>c 12 config! } : config.workchains!
|
||||
{ workchain-dict @ dict>s s>c 12 config! } : config.workchains!
|
||||
|
||||
dictnew constant special-dict
|
||||
variable special-dict
|
||||
// special-smc-addr --
|
||||
{ x{} swap @' special-dict 256 udict! not abort"cannot add a new special smart contract"
|
||||
=: special-dict
|
||||
{ x{} swap special-dict @ 256 udict! not abort"cannot add a new special smart contract"
|
||||
special-dict !
|
||||
} : make_special
|
||||
{ @' special-dict dict>s s>c 31 config! } : config.special!
|
||||
{ special-dict @ dict>s s>c 31 config! } : config.special!
|
||||
|
||||
// ( l -- D ) Converts a list of parameter indices into a dictionary
|
||||
{ dictnew { swap uncons -rot <b swap rot 32 b>idict! not abort"cannot add parameter index" over null?
|
||||
} until nip
|
||||
} : param-list-to-dict
|
||||
{ param-list-to-dict 9 config! } : config.mandatory_params!
|
||||
{ param-list-to-dict 10 config! } : config.critical_params!
|
||||
|
||||
// bit-pps cell-pps mc-bit-pps mc-cell-pps --
|
||||
{ <b x{cc} s, 0 32 u, 4 roll 64 u, 3 roll 64 u, rot 64 u, swap 64 u,
|
||||
|
|
|
@ -217,6 +217,7 @@ builder pack_proposal(cell voters, int sum_weight, int vset_id, slice body) inli
|
|||
int msg_seqno = cs~load_uint(32);
|
||||
var valid_until = cs~load_uint(32);
|
||||
throw_if(35, valid_until < now());
|
||||
throw_if(39, slice_depth(cs) > 64);
|
||||
var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
|
||||
throw_unless(33, msg_seqno == stored_seqno);
|
||||
ifnot ((action - 0x566f7465) & -2) {
|
||||
|
@ -228,6 +229,7 @@ builder pack_proposal(cell voters, int sum_weight, int vset_id, slice body) inli
|
|||
stored_seqno += 1;
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
commit();
|
||||
var (_, bits, refs) = cs.slice_compute_data_size(1024);
|
||||
(vote_dict, var accepted) = register_vote(vote_dict, action, cs, idx, weight, total_weight, config_param(34).cell_hash());
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
ifnot (accepted.null?()) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/create-state -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
"Lists.fif" include
|
||||
|
||||
def? $1 { @' $1 } { "" } cond constant suffix
|
||||
{ suffix $+ } : +suffix
|
||||
|
@ -199,6 +201,9 @@ smc1_addr config.minter_smc!
|
|||
|
||||
1000000000000 -17 of-cc 666666666666 239 of-cc cc+ config.to_mint!
|
||||
|
||||
( 9 10 18 20 21 22 23 24 25 28 34 ) config.mandatory_params!
|
||||
( -1000 -1001 9 10 32 34 36 ) config.critical_params!
|
||||
|
||||
"validator-keys" +suffix +".pub" file>B
|
||||
{ dup Blen } { 32 B| swap dup ."Validator public key = " Bx. cr
|
||||
17 add-validator } while drop
|
||||
|
|
|
@ -42,8 +42,10 @@ int string_hash(slice s) asm "SHA256U";
|
|||
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
|
||||
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
|
||||
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) asm "CDATASIZE";
|
||||
(int, int, int) slice_compute_data_size(slice s, int max_cells) asm "SDATASIZE";
|
||||
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
|
||||
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
|
||||
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
|
||||
(int, int, int, int) slice_compute_data_size?(cell c, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
|
||||
|
||||
;; () throw_if(int excno, int cond) impure asm "THROWARGIF";
|
||||
|
||||
|
|
|
@ -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 "GenericAccount.h"
|
||||
|
||||
|
@ -96,4 +96,19 @@ td::Ref<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& ad
|
|||
|
||||
return res;
|
||||
}
|
||||
td::Result<td::Ed25519::PublicKey> GenericAccount::get_public_key(const SmartContract& sc) {
|
||||
auto answer = sc.run_get_method("get_public_key");
|
||||
if (!answer.success) {
|
||||
return td::Status::Error("get_public_key failed");
|
||||
}
|
||||
auto do_get_public_key = [&]() -> td::Result<td::Ed25519::PublicKey> {
|
||||
auto key = answer.stack.write().pop_int_finite();
|
||||
td::SecureString bytes(32);
|
||||
if (!key->export_bytes(bytes.as_mutable_slice().ubegin(), bytes.size(), false)) {
|
||||
return td::Status::Error("get_public_key failed");
|
||||
}
|
||||
return td::Ed25519::PublicKey(std::move(bytes));
|
||||
};
|
||||
return TRY_VM(do_get_public_key());
|
||||
}
|
||||
} // namespace ton
|
||||
|
|
|
@ -14,11 +14,14 @@
|
|||
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 "vm/cells.h"
|
||||
#include "block/block.h"
|
||||
#include "Ed25519.h"
|
||||
#include "SmartContract.h"
|
||||
|
||||
namespace ton {
|
||||
class GenericAccount {
|
||||
public:
|
||||
|
@ -27,5 +30,7 @@ class GenericAccount {
|
|||
static td::Ref<vm::Cell> create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
|
||||
td::Ref<vm::Cell> body) noexcept;
|
||||
static void store_int_message(vm::CellBuilder& cb, const block::StdAddress& dest_address, td::int64 gramms);
|
||||
|
||||
static td::Result<td::Ed25519::PublicKey> get_public_key(const SmartContract& sc);
|
||||
};
|
||||
} // namespace ton
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class HighloadWallet : ton::SmartContract, public WalletInterface {
|
||||
class HighloadWallet : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit HighloadWallet(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class HighloadWalletV2 : ton::SmartContract, public WalletInterface {
|
||||
class HighloadWalletV2 : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit HighloadWalletV2(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class Wallet : ton::SmartContract, public WalletInterface {
|
||||
class Wallet : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit Wallet(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class WalletInterface {
|
|||
virtual td::Result<td::Ref<vm::Cell>> make_a_gift_message(const td::Ed25519::PrivateKey &private_key,
|
||||
td::uint32 valid_until, td::Span<Gift> gifts) const = 0;
|
||||
virtual td::Result<td::Ed25519::PublicKey> get_public_key() const {
|
||||
return td::Status::Error("TODO");
|
||||
return td::Status::Error("Unsupported");
|
||||
}
|
||||
|
||||
td::Result<td::Ref<vm::Cell>> get_init_message(const td::Ed25519::PrivateKey &private_key,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "vm/cells/CellString.h"
|
||||
|
||||
namespace ton {
|
||||
class WalletV3 : ton::SmartContract, public WalletInterface {
|
||||
class WalletV3 : public ton::SmartContract, public WalletInterface {
|
||||
public:
|
||||
explicit WalletV3(State state) : ton::SmartContract(std::move(state)) {
|
||||
}
|
||||
|
|
|
@ -306,6 +306,8 @@ TEST(Tonlib, WalletV3) {
|
|||
ASSERT_EQ(239u, wallet.get_wallet_id().ok());
|
||||
ASSERT_EQ(123u, wallet.get_seqno().ok());
|
||||
CHECK(priv_key.get_public_key().ok().as_octet_string() == wallet.get_public_key().ok().as_octet_string());
|
||||
CHECK(priv_key.get_public_key().ok().as_octet_string() ==
|
||||
ton::GenericAccount::get_public_key(wallet).ok().as_octet_string());
|
||||
|
||||
auto gift_message = ton::GenericAccount::create_ext_message(
|
||||
address, {}, wallet.make_a_gift_message(priv_key, 60, {gift}).move_as_ok());
|
||||
|
@ -337,6 +339,7 @@ TEST(Tonlib, HighloadWallet) {
|
|||
ASSERT_EQ(239u, wallet.get_wallet_id().ok());
|
||||
ASSERT_EQ(0u, wallet.get_seqno().ok());
|
||||
CHECK(pub_key.as_octet_string() == wallet.get_public_key().ok().as_octet_string());
|
||||
CHECK(pub_key.as_octet_string() == ton::GenericAccount::get_public_key(wallet).ok().as_octet_string());
|
||||
|
||||
CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32));
|
||||
|
||||
|
@ -417,6 +420,7 @@ TEST(Tonlib, HighloadWalletV2) {
|
|||
{ton::HighloadWalletV2::get_init_code(-1), ton::HighloadWalletV2::get_init_data(pub_key, 239)});
|
||||
ASSERT_EQ(239u, wallet.get_wallet_id().ok());
|
||||
CHECK(pub_key.as_octet_string() == wallet.get_public_key().ok().as_octet_string());
|
||||
CHECK(pub_key.as_octet_string() == ton::GenericAccount::get_public_key(wallet).ok().as_octet_string());
|
||||
|
||||
CHECK(address.addr.as_slice() == td::Slice(new_wallet_addr).substr(0, 32));
|
||||
|
||||
|
|
|
@ -161,6 +161,10 @@ TEST(VM, infinity_loop_2) {
|
|||
test_run_vm_raw("kpTt7ZLrig==");
|
||||
}
|
||||
|
||||
TEST(VM, oom_1) {
|
||||
test_run_vm_raw("bXflX/BvDw==");
|
||||
}
|
||||
|
||||
TEST(VM, bigint) {
|
||||
td::StringBuilder sb({}, true);
|
||||
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/linalloc.hpp"
|
||||
|
||||
namespace tlbc {
|
||||
|
||||
|
@ -26,6 +27,8 @@ using src::Lexem;
|
|||
using src::Lexer;
|
||||
using sym::sym_idx_t;
|
||||
|
||||
extern td::LinearAllocator AR;
|
||||
|
||||
struct Type;
|
||||
struct Constructor;
|
||||
|
||||
|
|
|
@ -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 <vector>
|
||||
#include <string>
|
||||
|
@ -219,6 +219,8 @@ inline bool is_uc_ident(sym_idx_t idx) {
|
|||
|
||||
namespace tlbc {
|
||||
|
||||
td::LinearAllocator AR(1 << 22);
|
||||
|
||||
/*
|
||||
*
|
||||
* AUXILIARY DATA TYPES
|
||||
|
@ -906,7 +908,7 @@ bool TypeExpr::no_tchk() const {
|
|||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_intconst(const src::SrcLocation& loc, unsigned int_const) {
|
||||
return new TypeExpr{loc, te_IntConst, (int)int_const};
|
||||
return new (AR) TypeExpr{loc, te_IntConst, (int)int_const};
|
||||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_intconst(const src::SrcLocation& loc, std::string int_const) {
|
||||
|
@ -951,16 +953,16 @@ TypeExpr* TypeExpr::mk_mulint(const src::SrcLocation& loc, TypeExpr* expr1, Type
|
|||
return expr2;
|
||||
}
|
||||
// delete expr2;
|
||||
return new TypeExpr{loc, te_MulConst, val, {expr1}, expr1->negated};
|
||||
return new (AR) TypeExpr{loc, te_MulConst, val, {expr1}, expr1->negated};
|
||||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_apply(const src::SrcLocation& loc, int tp, TypeExpr* expr1, TypeExpr* expr2) {
|
||||
TypeExpr* expr = new TypeExpr{loc, tp, 0, {expr1, expr2}};
|
||||
TypeExpr* expr = new (AR) TypeExpr{loc, tp, 0, {expr1, expr2}};
|
||||
return expr;
|
||||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_cellref(const src::SrcLocation& loc, TypeExpr* expr1) {
|
||||
TypeExpr* expr = new TypeExpr{loc, te_Ref, 0, {expr1}};
|
||||
TypeExpr* expr = new (AR) TypeExpr{loc, te_Ref, 0, {expr1}};
|
||||
return expr;
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1048,7 @@ bool TypeExpr::close(const src::SrcLocation& loc) {
|
|||
}
|
||||
|
||||
TypeExpr* TypeExpr::mk_apply_empty(const src::SrcLocation& loc, sym_idx_t name, Type* type_applied) {
|
||||
TypeExpr* expr = new TypeExpr{loc, te_Apply, name};
|
||||
TypeExpr* expr = new (AR) TypeExpr{loc, te_Apply, name};
|
||||
expr->type_applied = type_applied;
|
||||
expr->is_nat_subtype = (type_applied->produces_nat && !type_applied->arity);
|
||||
return expr;
|
||||
|
@ -1984,7 +1986,7 @@ void parse_field_list(Lexer& lex, Constructor& cs);
|
|||
|
||||
TypeExpr* parse_anonymous_constructor(Lexer& lex, Constructor& cs) {
|
||||
sym::open_scope(lex);
|
||||
Constructor* cs2 = new Constructor(lex.cur().loc); // anonymous constructor
|
||||
Constructor* cs2 = new (AR) Constructor(lex.cur().loc); // anonymous constructor
|
||||
parse_field_list(lex, *cs2);
|
||||
if (lex.tp() != ']') {
|
||||
lex.expect(']');
|
||||
|
@ -2089,7 +2091,7 @@ TypeExpr* parse_term(Lexer& lex, Constructor& cs, int mode) {
|
|||
}
|
||||
int i = sym_val->idx;
|
||||
assert(i >= 0 && i < cs.fields_num);
|
||||
auto res = new TypeExpr{lex.cur().loc, TypeExpr::te_Param, i};
|
||||
auto res = new (AR) TypeExpr{lex.cur().loc, TypeExpr::te_Param, i};
|
||||
auto field_type = cs.fields[i].type;
|
||||
assert(field_type);
|
||||
if ((mode & 4) && !cs.fields[i].known) {
|
||||
|
@ -2345,7 +2347,7 @@ void parse_constructor_def(Lexer& lex) {
|
|||
}
|
||||
//std::cerr << "parsing constructor `" << sym::symbols.get_name(constr_name) << "` with tag " << std::hex << tag
|
||||
// << std::dec << std::endl;
|
||||
auto cs_ref = new Constructor(where, constr_name, 0, tag);
|
||||
auto cs_ref = new (AR) Constructor(where, constr_name, 0, tag);
|
||||
Constructor& cs = *cs_ref;
|
||||
cs.is_special = is_special;
|
||||
parse_field_list(lex, cs);
|
||||
|
@ -2417,7 +2419,9 @@ void parse_constructor_def(Lexer& lex) {
|
|||
*
|
||||
*/
|
||||
|
||||
bool parse_source(std::istream* is, const src::FileDescr* fdescr) {
|
||||
std::vector<const src::FileDescr*> source_fdescr;
|
||||
|
||||
bool parse_source(std::istream* is, src::FileDescr* fdescr) {
|
||||
src::SourceReader reader{is, fdescr};
|
||||
src::Lexer lex{reader, true, "(){}:;? #$. ^~ #", "//", "/*", "*/"};
|
||||
while (lex.tp() != src::_Eof) {
|
||||
|
@ -2432,6 +2436,7 @@ bool parse_source_file(const char* filename) {
|
|||
throw src::Fatal{"source file name is an empty string"};
|
||||
}
|
||||
src::FileDescr* cur_source = new src::FileDescr{filename};
|
||||
source_fdescr.push_back(cur_source);
|
||||
std::ifstream ifs{filename};
|
||||
if (ifs.fail()) {
|
||||
throw src::Fatal{std::string{"cannot open source file `"} + filename + "`"};
|
||||
|
@ -2440,7 +2445,9 @@ bool parse_source_file(const char* filename) {
|
|||
}
|
||||
|
||||
bool parse_source_stdin() {
|
||||
return parse_source(&std::cin, new src::FileDescr{"stdin", true});
|
||||
src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
|
||||
source_fdescr.push_back(cur_source);
|
||||
return parse_source(&std::cin, cur_source);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2466,7 +2473,7 @@ Type* define_builtin_type(std::string name_str, std::string args, bool produces_
|
|||
}
|
||||
auto sym_def = sym::define_global_symbol(name, true);
|
||||
assert(sym_def);
|
||||
sym_def->value = new SymValType{type};
|
||||
sym_def->value = new (AR) SymValType{type};
|
||||
if (size < 0) {
|
||||
type->size = MinMaxSize::Any;
|
||||
} else if (min_size >= 0 && min_size != size) {
|
||||
|
|
|
@ -610,30 +610,4 @@ Ref<OrdCont> OrdCont::deserialize(CellSlice& cs, int mode) {
|
|||
: Ref<OrdCont>{};
|
||||
}
|
||||
|
||||
void VmState::init_cregs(bool same_c3, bool push_0) {
|
||||
cr.set_c0(quit0);
|
||||
cr.set_c1(quit1);
|
||||
cr.set_c2(Ref<ExcQuitCont>{true});
|
||||
if (same_c3) {
|
||||
cr.set_c3(Ref<OrdCont>{true, code, cp});
|
||||
if (push_0) {
|
||||
VM_LOG(this) << "implicit PUSH 0 at start\n";
|
||||
get_stack().push_smallint(0);
|
||||
}
|
||||
} else {
|
||||
cr.set_c3(Ref<QuitCont>{true, 11});
|
||||
}
|
||||
if (cr.d[0].is_null() || cr.d[1].is_null()) {
|
||||
auto empty_cell = CellBuilder{}.finalize();
|
||||
for (int i = 0; i < ControlRegs::dreg_num; i++) {
|
||||
if (cr.d[i].is_null()) {
|
||||
cr.d[i] = empty_cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cr.c7.is_null()) {
|
||||
cr.set_c7(Ref<Tuple>{true});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
|
|
@ -72,6 +72,32 @@ VmState::VmState(Ref<CellSlice> _code, Ref<Stack> _stack, const GasLimits& gas,
|
|||
init_cregs(flags & 1, flags & 2);
|
||||
}
|
||||
|
||||
void VmState::init_cregs(bool same_c3, bool push_0) {
|
||||
cr.set_c0(quit0);
|
||||
cr.set_c1(quit1);
|
||||
cr.set_c2(Ref<ExcQuitCont>{true});
|
||||
if (same_c3) {
|
||||
cr.set_c3(Ref<OrdCont>{true, code, cp});
|
||||
if (push_0) {
|
||||
VM_LOG(this) << "implicit PUSH 0 at start\n";
|
||||
get_stack().push_smallint(0);
|
||||
}
|
||||
} else {
|
||||
cr.set_c3(Ref<QuitCont>{true, 11});
|
||||
}
|
||||
if (cr.d[0].is_null() || cr.d[1].is_null()) {
|
||||
auto empty_cell = CellBuilder{}.finalize();
|
||||
for (int i = 0; i < ControlRegs::dreg_num; i++) {
|
||||
if (cr.d[i].is_null()) {
|
||||
cr.d[i] = empty_cell;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cr.c7.is_null()) {
|
||||
cr.set_c7(Ref<Tuple>{true});
|
||||
}
|
||||
}
|
||||
|
||||
Ref<CellSlice> VmState::convert_code_cell(Ref<Cell> code_cell) {
|
||||
if (code_cell.is_null()) {
|
||||
return {};
|
||||
|
@ -388,7 +414,7 @@ void VmState::change_gas_limit(long long new_limit) {
|
|||
}
|
||||
|
||||
int VmState::step() {
|
||||
assert(!code.is_null());
|
||||
CHECK(code.not_null() && stack.not_null());
|
||||
//VM_LOG(st) << "stack:"; stack->dump(VM_LOG(st));
|
||||
//VM_LOG(st) << "; cr0.refcnt = " << get_c0()->get_refcnt() - 1 << std::endl;
|
||||
if (stack_trace) {
|
||||
|
@ -410,8 +436,9 @@ int VmState::step() {
|
|||
}
|
||||
|
||||
int VmState::run() {
|
||||
if (code.is_null()) {
|
||||
throw VmError{Excno::fatal, "cannot run an uninitialized VM"};
|
||||
if (code.is_null() || stack.is_null()) {
|
||||
// throw VmError{Excno::fatal, "cannot run an uninitialized VM"};
|
||||
return (int)Excno::fatal; // no ~ for unhandled exceptions
|
||||
}
|
||||
int res;
|
||||
Guard guard(this);
|
||||
|
|
173
doc/DNS-HOWTO
Normal file
173
doc/DNS-HOWTO
Normal file
|
@ -0,0 +1,173 @@
|
|||
The aim of this document is to provide a very brief introduction to TON DNS, a service for translating human-readable domain names (such as `test.ton` or `mysite.temp.ton`) into TON smart contract addresses, ADNL addresses employed by services running in the TON Network (such as TON Sites), and so on.
|
||||
|
||||
1. Domain names
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
TON DNS employs familiarly-looking domain names, consisting of a UTF-8 encoded string up to 126 bytes, with different sections of the domain name separated by dots (`.`). Null characters (i.e. zero bytes) and, more generally, bytes in range 0..32 are not allowed in domain names. For instance, `test.ton` and `mysite.temp.ton` are valid TON DNS domains. A major difference from usual domain names is that TON DNS domains are case-sensitive; one could convert all domains to lowercase before performing a TON DNS lookup in order to obtain case-insensitivity if desired.
|
||||
|
||||
Currently, only domains ending in `.ton` are recognized as valid TON DNS domains. This could change in the future. Notice, however, that it is a bad idea to define first-level domains coinciding with first-level domains already existing in the Internet, such as `.com` or `.to`, because one could then register a TON domain `google.com`, deploy a TON site there, create a hidden link to a page at this TON site from his other innocently-looking TON site, and steal `google.com` cookies from unsuspecting visitors.
|
||||
|
||||
Internally, TON DNS transforms domain names as follows. First, a domain name is split into its components delimited by dot characters `.`. Then null characters are appended to each component, and all components are concatenated in reverse order. For example, `google.com` becomes `com\0google\0`.
|
||||
|
||||
2. Resolving TON DNS domains
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A TON DNS domain is resolved as follows. First, the *root DNS smart contract* is located by inspecting the value of configuration parameter #4 in a recent masterchain state. This parameter contains the 256-bit address of the root DNS smart contract inside the masterchain.
|
||||
|
||||
Then a special get-method `dnsresolve` (method id 123660) is invoked for the root DNS smart contract, with two parameters. The first parameter is a CellSlice with *8n* data bits containing the internal representation of the domain being resolved, where *n* is the length of the internal representation in bytes (at most 127). The second parameter is a signed 16-bit Integer containing the required *category*. If the category is zero, then all categories are requested.
|
||||
|
||||
If this get-method fails, then the TON DNS lookup is unsuccessful. Otherwise the get-method returns two values. The first is *8m*, the length (in bits) of the prefix of the internal representation of the domain that has been resolved, 0 < m <= n. The second is a Cell with the TON DNS record for the required domain in the required category, or the root a Dictionary with 16-bit signed integer keys (categories) and values equal to the serializations of corresponding TON DNS records. If the domain cannot be resolved by the root DNS smart contract, i.e. if no non-empty prefix is a valid domain known to the smart contract, then (0, null) is returned. In other words, m = 0 means that the TON DNS lookup has found no data for the required domain. In that case, the TON DNS lookup is also unsuccessful.
|
||||
|
||||
If m = n, then the second component of the result is either a Cell with a valid TON DNS record for the required domain and category, or a Null if there is no TON DNS record for this domain with this category. In either case, the resolution process stops, and the TON DNS record thus obtained is deserialized and the required information (such as the type of the record and its parameters, such as a smart contract address or a ADNL address).
|
||||
|
||||
Finally, if m < n, then the lookup is successful so far, but only a partial result is available for the m-byte prefix of the original internal representation of the domain. The longest of all such prefixes known to the DNS smart contract is returned. For instance, an attempt to look up `mysite.test.ton` (i.e. `ton\0test\0mysite\0` in the internal representation) in the root DNS smart contract might return 8m=72, corresponding to prefix `ton\0test\0`, i.e. to subdomain "test.ton" in the usual domain representation. In that case, dnsresolve() returns the value for category -1 for this prefix regardless of the category originally requested by the client. By convention, category -1 usually contains a TON DNS Record of type *dns_next_resolver*, containing the address of next resolver smart contract (which can reside in any other workchain, such as the basechain). If that is indeed the case, the resolution process continues by running get-method `dnsresolve` for the next resolver, with the internal representation of the domain name containing only its part unresolved so far (if we were looking up `ton\0test\0mysite\0`, and prefix `ton\0test\0` was found by the root DNS smart contract, then the next `dnsresolve` will be invoked with `mysite\0` as its first argument). Then either the next resolver smart contract reports an error or the absence of any records for the required domain or any of its prefixes, or the final result is obtained, or another prefix and next resolver smart contract is returned. In the latter case, the process continues in the same fashion until all of the original domain is resolved.
|
||||
|
||||
3. Using LiteClient and TonLib to resolve TON DNS domains
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The above process can be invoked automatically using the TON LiteClient or TONLib. For instance, one can invoke the command `dnsresolve test.ton 1` in the LiteClient to resolve "test.ton" with category 1 and obtain the following result:
|
||||
|
||||
================================================
|
||||
> dnsresolve test.ton
|
||||
...
|
||||
Result for domain 'test.ton' category 1
|
||||
raw data: x{AD011B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB00}
|
||||
|
||||
category #1 : (dns_adnl_address adnl_addr:x1B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB flags:0)
|
||||
adnl address 1B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB = UNTZO7EAT2H77XZFUGXRFGFY3ZBL5TXOMVETZKE6FWR45LEHVDKXAUY
|
||||
================================================
|
||||
|
||||
In this case, the TON DNS record for "test.ton" is a `dns_adnl_address` record containing ADNL address UNTZO7EAT2H77XZFUGXRFGFY3ZBL5TXOMVETZKE6FWR45LEHVDKXAUY
|
||||
|
||||
Alternatively, one can invoke `tonlib-cli` and enter the following command:
|
||||
================================================
|
||||
> dns resolve root test.ton 1
|
||||
Redirect resolver
|
||||
...
|
||||
Done
|
||||
test.ton 1 ADNL:untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy
|
||||
================================================
|
||||
|
||||
This is a more compact representation of the same result.
|
||||
|
||||
Finally, if one uses RLDP-HTTP Proxy in the client mode to access TON Sites from a browser as explained in `TONSites-HOWTO.txt`, the TONLib resolver is automatically invoked to resolve all domains entered by the end user, so that a HTTP query to `http://test.ton/testnet/last` is automatically forwarded to ADNL address `untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy` via RLDP.
|
||||
|
||||
4. Registering new domains
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Suppose that you have a new TON Site with a newly-generated ADNL address, such as `vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3`. Of course, the end user might type `http://vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3.adnl/` to visit your TON Site from a browser using a RLDP-HTTP Proxy in client mode, but this is not very convenient. Instead, you could register a new domain, say, `mysite.temp.ton` with a `dns_adnl_address` record in category 1 containing the ADNL address vcq...25f3 of your TON Site. Then the user would access your TON Site by simply typing `mysite.temp.ton` in a browser.
|
||||
|
||||
In general, you would need to contact the owner of the higher-level domain and ask him to add a record for your subdomain in his DNS resolver smart contract. However, the TestNet of the TON Blockchain has a special resolver smart contract for `temp.ton` that allows anyone to automatically register any subdomains of `temp.ton` not registered yet, provided a small fee (in test Grams) is paid to that smart contract. In our case, we first need to find out the address of this smart contract, for example by using the Lite Client:
|
||||
|
||||
================================================
|
||||
> dnsresolve temp.ton -1
|
||||
...
|
||||
category #-1 : (dns_next_resolver
|
||||
resolver:(addr_std
|
||||
anycast:nothing workchain_id:0 address:x190BD756F6C0E7948DC26CB47968323177FB20344F8F9A50918CAF87ECB34B79))
|
||||
next resolver 0:190BD756F6C0E7948DC26CB47968323177FB20344F8F9A50918CAF87ECB34B79 = EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN
|
||||
================================================
|
||||
|
||||
We see that the address of this automatic DNS smart contract is EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN. We can run several get methods to compute the required price for registering a subdomain, and to learn the period for which the subdomain will be registered:
|
||||
|
||||
================================================
|
||||
> runmethod EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN getstdperiod
|
||||
...
|
||||
arguments: [ 67418 ]
|
||||
result: [ 700000 ]
|
||||
remote result (not to be trusted): [ 700000 ]
|
||||
> runmethod EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN getppr
|
||||
...
|
||||
arguments: [ 109522 ]
|
||||
result: [ 100000000 ]
|
||||
remote result (not to be trusted): [ 100000000 ]
|
||||
================================================
|
||||
|
||||
We see that subdomains are registered for 700000 seconds (about eight days), and that the registration price is 100000000ng = 0.1 test Grams per domain, plus a price for each bit and cell of stored data, which can be learned by running get-methods `getppb` and `getppc`.
|
||||
|
||||
Now we want this smart contract to register our subdomain. In order to do this, we have to create a special message from our wallet to the automatic DNS smart contract. Let us assume that we have a wallet `my_new_wallet` with address kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI. Then we run the following Fift script (from the subdirectory `crypto/smartcont` of the source tree):
|
||||
|
||||
fift -s auto-dns.fif <auto-dns-smc-addr> add <my-subdomain> <expire-time> owner <my-wallet-addr> cat 1 adnl <my-site-adnl-address>
|
||||
|
||||
For example:
|
||||
|
||||
===============================================
|
||||
$ fift -s auto-dns.fif EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN add 'mysite' 700000 owner kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI cat 1 adnl vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3
|
||||
Automatic DNS smart contract address = 0:190bd756f6c0e7948dc26cb47968323177fb20344f8f9a50918caf87ecb34b79
|
||||
kQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLef5H
|
||||
Action: add mysite 1583865040
|
||||
Operation code: 0x72656764
|
||||
Value: x{2_}
|
||||
x{BC000C_}
|
||||
x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
|
||||
x{BFFFF4_}
|
||||
x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}
|
||||
|
||||
Internal message body is: x{726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
|
||||
x{2_}
|
||||
x{BC000C_}
|
||||
x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
|
||||
x{BFFFF4_}
|
||||
x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}
|
||||
|
||||
B5EE9C7241010601007800012F726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A10102012002030105BC000C040105BFFFF4050046AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD0000499FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01070E6337D
|
||||
Query_id is 6799642071046147647 = 0x5E5D2E700481CE3F
|
||||
(Saved to file dns-msg-body.boc)
|
||||
================================================
|
||||
|
||||
We see that the internal message body for this query has been created and saved into file `dns-msg-body.boc`. Now you have to send a payment from your wallet kQAB..ZgI to the automatic DNS smart contract EQA..UXN, along with message body from file `dns-msg-body.boc`, so that the automatic DNS smart contract knows what you want it to do. If your wallet has been created by means of `new-wallet.fif`, you can simply use `-B` command-line argument to `wallet.fif` while performing this transfer:
|
||||
|
||||
================================================
|
||||
$ fift -s wallet.fif my_new_wallet EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN 1 1.7 -B dns-msg-body.boc
|
||||
Source wallet address = 0:01cec94030a395c244a49167de952d696120ce4b24dc827d3263f96842fca8fd
|
||||
kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI
|
||||
Loading private key from file my_new_wallet.pk
|
||||
Transferring GR$1.7 to account kQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLef5H = 0:190bd756f6c0e7948dc26cb47968323177fb20344f8f9a50918caf87ecb34b79 seqno=0x1 bounce=-1
|
||||
Body of transfer message is x{726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
|
||||
x{2_}
|
||||
x{BC000C_}
|
||||
x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
|
||||
x{BFFFF4_}
|
||||
x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}
|
||||
|
||||
signing message: x{0000000103}
|
||||
x{62000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
|
||||
x{2_}
|
||||
x{BC000C_}
|
||||
x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
|
||||
x{BFFFF4_}
|
||||
x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}
|
||||
|
||||
resulting external message: x{8800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA050E3817FC01F564AECE810B8077D72E3EE15C81392E8B4AE9CDD0D6575821481C996AE8FFBABA0513F131E10E27C006C6544E99D71E0A6AACF7D02C677342B040000000081C_}
|
||||
x{62000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_}
|
||||
x{2_}
|
||||
x{BC000C_}
|
||||
x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00}
|
||||
x{BFFFF4_}
|
||||
x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_}
|
||||
|
||||
B5EE9C72410207010001170001CF8800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA050E3817FC01F564AECE810B8077D72E3EE15C81392E8B4AE9CDD0D6575821481C996AE8FFBABA0513F131E10E27C006C6544E99D71E0A6AACF7D02C677342B040000000081C01019762000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A10202012003040105BC000C050105BFFFF4060046AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD0000499FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01031E3A74C
|
||||
(Saved to file wallet-query.boc)
|
||||
=====================================================
|
||||
|
||||
(You have to replace 1 with the correct sequence number for your wallet.) Once you obtain a signed external message in `wallet-query.boc`, addressed to your wallet and instructing it to transfer 1.7 test Grams to the automatic DNS smart contract along with the description of your new domain to be registered, you can upload this message using the LiteClient by typing
|
||||
|
||||
=====================================================
|
||||
> sendfile wallet-query.boc
|
||||
[ 1][t 1][!testnode] sending query from file wallet-query.boc
|
||||
[ 3][t 1][!query] external message status is 1
|
||||
=====================================================
|
||||
|
||||
If all works correctly, you'll obtain some change from the automatic DNS smart contract in a confirmation message (it will charge only the storage fees for your subdomain and processing fees for running the smart contract and sending messages, and return the rest), and your new domain will be registered:
|
||||
|
||||
=====================================================
|
||||
> last
|
||||
...
|
||||
> dnsresolve mysite.temp.ton 1
|
||||
...
|
||||
Result for domain 'mysite.temp.ton' category 1
|
||||
category #1 : (dns_adnl_address adnl_addr:x45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD flags:0)
|
||||
adnl address 45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD = vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3
|
||||
=====================================================
|
||||
|
||||
You can modify or prolong this domain in essentially the same manner, by first creating a request in file `dns-msg-body.boc` by means of `auto-dns.fif`, using such actions as `update` or `prolong`, and then embedding this request into a message from your wallet to the automatic DNS smart contract using `wallet.fif` or a similar script with command-line argument `-B dns-msg-body.boc`.
|
|
@ -67,7 +67,7 @@ adnl.address.udp6 ip:int128 port:int = adnl.Address;
|
|||
//adnl.address.tcp ip:int port:int = adnl.Address;
|
||||
//adnl.address.tcp6 ip:int128 port:int = adnl.Address;
|
||||
|
||||
//adnl.address.tunnel to:adnl.Address tunid: = adnl.Address;
|
||||
adnl.address.tunnel to:int256 pubkey:PublicKey = adnl.Address;
|
||||
|
||||
adnl.addressList addrs:(vector adnl.Address) version:int reinit_date:int priority:int expire_at:int = adnl.AddressList;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -90,7 +90,7 @@ msg.dataEncryptedText text:bytes = msg.Data;
|
|||
|
||||
msg.dataArray elements:vector<msg.Data> = msg.DataArray;
|
||||
|
||||
msg.message destination:accountAddress amount:int64 data:msg.Data = msg.Message;
|
||||
msg.message destination:accountAddress public_key:string amount:int64 data:msg.Data = msg.Message;
|
||||
|
||||
//
|
||||
// DNS
|
||||
|
|
Binary file not shown.
|
@ -239,7 +239,7 @@ td::Result<QueryId> create_send_grams_query(Client& client, const Wallet& source
|
|||
data = tonlib_api::make_object<tonlib_api::msg_dataText>(std::move(message));
|
||||
}
|
||||
msgs.push_back(tonlib_api::make_object<tonlib_api::msg_message>(
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(destination), amount, std::move(data)));
|
||||
tonlib_api::make_object<tonlib_api::accountAddress>(destination), "", amount, std::move(data)));
|
||||
|
||||
auto r_id =
|
||||
sync_send(client, tonlib_api::make_object<tonlib_api::createQuery>(
|
||||
|
|
|
@ -1851,7 +1851,6 @@ struct ToRawTransactions {
|
|||
|
||||
if (r_body_message.is_ok()) {
|
||||
if (type == 0) {
|
||||
LOG(ERROR) << "OK " << r_body_message.ok();
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataText>(r_body_message.move_as_ok());
|
||||
} else {
|
||||
LOG(ERROR) << "TRY DECRYPT";
|
||||
|
@ -2177,6 +2176,8 @@ class GenericCreateSendGrams : public TonlibQueryActor {
|
|||
std::string message;
|
||||
|
||||
td::Ref<vm::Cell> body;
|
||||
|
||||
td::optional<td::Ed25519::PublicKey> o_public_key;
|
||||
};
|
||||
bool allow_send_to_uninited_{false};
|
||||
std::vector<Action> actions_;
|
||||
|
@ -2210,6 +2211,11 @@ class GenericCreateSendGrams : public TonlibQueryActor {
|
|||
return TonlibError::InvalidField("amount", "can't be negative");
|
||||
}
|
||||
res.amount = message.amount_;
|
||||
if (!message.public_key_.empty()) {
|
||||
TRY_RESULT(public_key, get_public_key(message.public_key_));
|
||||
auto key = td::Ed25519::PublicKey(td::SecureString(public_key.key));
|
||||
res.o_public_key = std::move(key);
|
||||
}
|
||||
auto status =
|
||||
downcast_call2<td::Status>(*message.data_, td::overloaded(
|
||||
[&](tonlib_api::msg_dataRaw& text) {
|
||||
|
@ -2243,7 +2249,7 @@ class GenericCreateSendGrams : public TonlibQueryActor {
|
|||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
TRY_STATUS(std::move(status));
|
||||
return res;
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
td::Result<ton::ManualDns::Action> to_dns_action(tonlib_api::dns_Action& action) {
|
||||
|
@ -2465,15 +2471,30 @@ class GenericCreateSendGrams : public TonlibQueryActor {
|
|||
if (!private_key_) {
|
||||
return TonlibError::EmptyField("private_key");
|
||||
}
|
||||
if (!destination->is_wallet()) {
|
||||
|
||||
auto o_public_key = std::move(action.o_public_key);
|
||||
if (!o_public_key && destination->is_wallet()) {
|
||||
auto wallet = destination->get_wallet();
|
||||
auto r_public_key = wallet->get_public_key();
|
||||
if (r_public_key.is_ok()) {
|
||||
o_public_key = r_public_key.move_as_ok();
|
||||
}
|
||||
}
|
||||
|
||||
if (!o_public_key) {
|
||||
auto smc = ton::SmartContract::create(destination->get_smc_state());
|
||||
auto r_public_key = ton::GenericAccount::get_public_key(destination->get_smc_state());
|
||||
if (r_public_key.is_ok()) {
|
||||
o_public_key = r_public_key.move_as_ok();
|
||||
}
|
||||
}
|
||||
|
||||
if (!o_public_key) {
|
||||
return TonlibError::MessageEncryption("Get public key (in destination)");
|
||||
}
|
||||
auto wallet = destination->get_wallet();
|
||||
TRY_RESULT_PREFIX(public_key, wallet->get_public_key(),
|
||||
TonlibError::AccountActionUnsupported(PSLICE() << "Get public key (in destination) : "
|
||||
<< destination->get_wallet_type()));
|
||||
|
||||
TRY_RESULT_PREFIX(encrypted_message,
|
||||
SimpleEncryptionV2::encrypt_data(action.message, public_key, private_key_.value()),
|
||||
SimpleEncryptionV2::encrypt_data(action.message, o_public_key.unwrap(), private_key_.value()),
|
||||
TonlibError::Internal());
|
||||
gift.message = encrypted_message.as_slice().str();
|
||||
gift.is_encrypted = true;
|
||||
|
|
|
@ -1476,8 +1476,8 @@ class TonlibCli : public td::actor::Actor {
|
|||
} else {
|
||||
data = tonlib_api::make_object<tonlib_api::msg_dataText>(message.str());
|
||||
}
|
||||
messages.push_back(
|
||||
tonlib_api::make_object<tonlib_api::msg_message>(std::move(address.address), amount.nano, std::move(data)));
|
||||
messages.push_back(tonlib_api::make_object<tonlib_api::msg_message>(std::move(address.address), "", amount.nano,
|
||||
std::move(data)));
|
||||
return td::Status::OK();
|
||||
};
|
||||
|
||||
|
|
|
@ -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 "interfaces/validator-manager.h"
|
||||
|
@ -124,6 +124,7 @@ class Collator final : public td::actor::Actor {
|
|||
Ref<vm::Cell> state_update; // Merkle update from prev_state_root to state_root
|
||||
std::shared_ptr<vm::CellUsageTree> state_usage_tree_; // used to construct Merkle update
|
||||
Ref<vm::CellSlice> new_config_params_;
|
||||
Ref<vm::Cell> old_mparams_;
|
||||
ton::LogicalTime prev_state_lt_;
|
||||
ton::LogicalTime shards_max_end_lt_{0};
|
||||
ton::UnixTime prev_state_utime_;
|
||||
|
|
|
@ -1457,6 +1457,7 @@ bool Collator::init_lt() {
|
|||
}
|
||||
|
||||
bool Collator::fetch_config_params() {
|
||||
old_mparams_ = config_->get_config_param(9);
|
||||
{
|
||||
auto res = config_->get_storage_prices();
|
||||
if (res.is_error()) {
|
||||
|
@ -2968,7 +2969,7 @@ bool Collator::create_mc_state_extra() {
|
|||
auto cfg_smc_config = cfg_res.move_as_ok();
|
||||
CHECK(cfg_smc_config.not_null());
|
||||
vm::Dictionary cfg_dict{cfg_smc_config, 32};
|
||||
if (!block::valid_config_data(cfg_smc_config, config_addr, true, true)) {
|
||||
if (!block::valid_config_data(cfg_smc_config, config_addr, true, true, old_mparams_)) {
|
||||
block::gen::t_Hashmap_32_Ref_Cell.print_ref(std::cerr, cfg_smc_config);
|
||||
return fatal_error("configuration smart contract "s + config_addr.to_hex() +
|
||||
" contains an invalid configuration in its data");
|
||||
|
@ -3241,7 +3242,7 @@ bool Collator::try_fetch_new_config(const ton::StdSmcAddress& cfg_addr, Ref<vm::
|
|||
return false;
|
||||
}
|
||||
auto cfg = cfg_res.move_as_ok();
|
||||
if (!block::valid_config_data(cfg, cfg_addr, true)) {
|
||||
if (!block::valid_config_data(cfg, cfg_addr, true, false, old_mparams_)) {
|
||||
LOG(ERROR) << "new configuration smart contract " << cfg_addr.to_hex()
|
||||
<< " contains a new configuration which is invalid, ignoring";
|
||||
return false;
|
||||
|
|
|
@ -728,6 +728,7 @@ bool ValidateQuery::try_unpack_mc_state() {
|
|||
|
||||
// almost the same as in Collator
|
||||
bool ValidateQuery::fetch_config_params() {
|
||||
old_mparams_ = config_->get_config_param(9);
|
||||
{
|
||||
auto res = config_->get_storage_prices();
|
||||
if (res.is_error()) {
|
||||
|
@ -4804,7 +4805,7 @@ bool ValidateQuery::check_config_update(Ref<vm::CellSlice> old_conf_params, Ref<
|
|||
Ref<vm::Cell> old_cfg_root, new_cfg_root;
|
||||
CHECK(block::gen::t_ConfigParams.unpack_cons1(old_conf_params.write(), old_cfg_addr, old_cfg_root) &&
|
||||
block::gen::t_ConfigParams.unpack_cons1(new_conf_params.write(), new_cfg_addr, new_cfg_root));
|
||||
if (!block::valid_config_data(new_cfg_root, new_cfg_addr, true)) {
|
||||
if (!block::valid_config_data(new_cfg_root, new_cfg_addr, true, false, old_mparams_)) {
|
||||
return reject_query(
|
||||
"new configuration parameters failed to pass per-parameter automated validity checks, or one of mandatory "
|
||||
"configuration parameters is missing");
|
||||
|
@ -4829,7 +4830,7 @@ bool ValidateQuery::check_config_update(Ref<vm::CellSlice> old_conf_params, Ref<
|
|||
"the new configuration is different from that stored in the persistent data of the (new) configuration smart contract "s +
|
||||
old_cfg_addr.to_hex());
|
||||
}
|
||||
if (!block::valid_config_data(ocfg_root, old_cfg_addr, true, true)) {
|
||||
if (!block::valid_config_data(ocfg_root, old_cfg_addr, true, true, old_mparams_)) {
|
||||
return reject_query("configuration extracted from (old) configuration smart contract "s + old_cfg_addr.to_hex() +
|
||||
" failed to pass per-parameted validity checks, or one of mandatory parameters is missing");
|
||||
}
|
||||
|
@ -4883,7 +4884,7 @@ bool ValidateQuery::check_config_update(Ref<vm::CellSlice> old_conf_params, Ref<
|
|||
return true;
|
||||
}
|
||||
auto wcfg_root = wcfg_res.move_as_ok();
|
||||
if (!block::valid_config_data(wcfg_root, want_cfg_addr, true)) {
|
||||
if (!block::valid_config_data(wcfg_root, want_cfg_addr, true, false, old_mparams_)) {
|
||||
LOG(WARNING)
|
||||
<< "switching of configuration smart contract did not happen because the configuration extracted from "
|
||||
"suggested new configuration smart contract "
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -169,6 +169,7 @@ class ValidateQuery : public td::actor::Actor {
|
|||
std::unique_ptr<block::ShardConfig> new_shard_conf_; // from shard_hashes_ in mc blocks
|
||||
Ref<block::WorkchainInfo> wc_info_;
|
||||
std::unique_ptr<vm::AugmentedDictionary> fees_import_dict_;
|
||||
Ref<vm::Cell> old_mparams_;
|
||||
bool accept_msgs_{true};
|
||||
|
||||
ton::BlockSeqno min_shard_ref_mc_seqno_{~0U};
|
||||
|
|
Loading…
Reference in a new issue