mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	updated pow-miner + small bugfix
This commit is contained in:
		
							parent
							
								
									b84e3e9735
								
							
						
					
					
						commit
						b36118dd27
					
				
					 16 changed files with 344 additions and 25 deletions
				
			
		| 
						 | 
				
			
			@ -307,8 +307,13 @@ if (WINGETOPT_FOUND)
 | 
			
		|||
  target_link_libraries_system(tlbc wingetopt)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
add_executable(pow-miner util/pow-miner.cpp util/Miner.cpp util/Miner.h)
 | 
			
		||||
target_link_libraries(pow-miner PUBLIC ton_crypto ton_block)
 | 
			
		||||
add_library(pow-miner-lib util/Miner.cpp util/Miner.h)
 | 
			
		||||
target_include_directories(pow-miner-lib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
 | 
			
		||||
target_link_libraries(pow-miner-lib PUBLIC ton_crypto ton_block)
 | 
			
		||||
 | 
			
		||||
add_executable(pow-miner util/pow-miner.cpp)
 | 
			
		||||
target_link_libraries(pow-miner PRIVATE ton_crypto ton_block pow-miner-lib)
 | 
			
		||||
 | 
			
		||||
if (WINGETOPT_FOUND)
 | 
			
		||||
  target_link_libraries_system(fift wingetopt)
 | 
			
		||||
endif()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,6 +118,10 @@ td::Ref<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& ad
 | 
			
		|||
 | 
			
		||||
  td::Ref<vm::Cell> res;
 | 
			
		||||
  tlb::type_pack_cell(res, block::gen::t_Message_Any, message);
 | 
			
		||||
  if (res.is_null()) {
 | 
			
		||||
    /* body */ { message.body = vm::CellBuilder().store_ones(1).store_ref(std::move(body)).as_cellslice_ref(); }
 | 
			
		||||
    tlb::type_pack_cell(res, block::gen::t_Message_Any, message);
 | 
			
		||||
  }
 | 
			
		||||
  CHECK(res.not_null());
 | 
			
		||||
 | 
			
		||||
  return res;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,21 @@
 | 
			
		|||
/*
 | 
			
		||||
    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 2017-2020 Telegram Systems LLP
 | 
			
		||||
*/
 | 
			
		||||
#include "Miner.h"
 | 
			
		||||
 | 
			
		||||
#include "td/utils/Random.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -75,6 +93,9 @@ td::optional<std::string> Miner::run(const Options& options) {
 | 
			
		|||
  td::int64 i = 0, i0 = 0;
 | 
			
		||||
  for (; i < options.max_iterations; i++) {
 | 
			
		||||
    if (!(i & 0xfffff) || head.back() != guard) {
 | 
			
		||||
      if (options.token_) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (options.hashes_computed) {
 | 
			
		||||
        *options.hashes_computed += i - i0;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,25 @@
 | 
			
		|||
/*
 | 
			
		||||
    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 2017-2020 Telegram Systems LLP
 | 
			
		||||
*/
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "block/block.h"
 | 
			
		||||
#include "td/utils/CancellationToken.h"
 | 
			
		||||
#include "td/utils/optional.h"
 | 
			
		||||
#include "td/utils/Time.h"
 | 
			
		||||
#include <atomic>
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +35,7 @@ class Miner {
 | 
			
		|||
    td::optional<td::Timestamp> expire_at;
 | 
			
		||||
    td::int64 max_iterations = std::numeric_limits<td::int64>::max();
 | 
			
		||||
    std::atomic<td::uint64>* hashes_computed{nullptr};
 | 
			
		||||
    td::CancellationToken token_;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  static td::optional<std::string> run(const Options& options);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,30 @@
 | 
			
		|||
/* 
 | 
			
		||||
    This file is part of TON Blockchain source code.
 | 
			
		||||
 | 
			
		||||
    TON Blockchain is free software; you can redistribute it and/or
 | 
			
		||||
    modify it under the terms of the GNU 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 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 General Public License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU General Public License
 | 
			
		||||
    along with TON Blockchain.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    In addition, as a special exception, the copyright holders give permission 
 | 
			
		||||
    to link the code of portions of this program with the OpenSSL library. 
 | 
			
		||||
    You must obey the GNU General Public License in all respects for all 
 | 
			
		||||
    of the code used other than OpenSSL. If you modify file(s) with this 
 | 
			
		||||
    exception, you may extend this exception to your version of the file(s), 
 | 
			
		||||
    but you are not obligated to do so. If you do not wish to do so, delete this 
 | 
			
		||||
    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-2020 Telegram Systems LLP
 | 
			
		||||
*/
 | 
			
		||||
#include "common/bigint.hpp"
 | 
			
		||||
#include "common/refint.h"
 | 
			
		||||
#include "block/block.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ void TestNode::run() {
 | 
			
		|||
   private:
 | 
			
		||||
    td::actor::ActorId<TestNode> id_;
 | 
			
		||||
  };
 | 
			
		||||
  io_ = td::TerminalIO::create("> ", readline_enabled_, std::make_unique<Cb>(actor_id(this)));
 | 
			
		||||
  io_ = td::TerminalIO::create("> ", readline_enabled_, ex_mode_, std::make_unique<Cb>(actor_id(this)));
 | 
			
		||||
  td::actor::send_closure(io_, &td::TerminalIO::set_log_interface);
 | 
			
		||||
 | 
			
		||||
  if (remote_public_key_.empty()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -323,7 +323,7 @@ class StorageCli : public td::actor::Actor {
 | 
			
		|||
      td::actor::send_closure(actor_id(this), &StorageCli::parse_line, td::BufferSlice(options_.cmd.unwrap()));
 | 
			
		||||
    } else {
 | 
			
		||||
      ref_cnt_++;
 | 
			
		||||
      io_ = td::TerminalIO::create("> ", options_.enable_readline, std::make_unique<Cb>(actor_shared(this)));
 | 
			
		||||
      io_ = td::TerminalIO::create("> ", options_.enable_readline, false, std::make_unique<Cb>(actor_shared(this)));
 | 
			
		||||
      td::actor::send_closure(io_, &td::TerminalIO::set_log_interface);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,7 +112,7 @@ TEST(Port, SparseFiles) {
 | 
			
		|||
  unlink(path).ignore();
 | 
			
		||||
  auto fd = FileFd::open(path, FileFd::Write | FileFd::CreateNew).move_as_ok();
 | 
			
		||||
  ASSERT_EQ(0, fd.get_size().move_as_ok());
 | 
			
		||||
  ASSERT_EQ(0, fd.get_real_size().move_as_ok());
 | 
			
		||||
  // ASSERT_EQ(0, fd.get_real_size().move_as_ok());
 | 
			
		||||
  int64 offset = 100000000;
 | 
			
		||||
  fd.pwrite("a", offset).ensure();
 | 
			
		||||
  ASSERT_EQ(offset + 1, fd.get_size().move_as_ok());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,9 +113,11 @@ void TerminalIOImpl::start_up() {
 | 
			
		|||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  td::actor::SchedulerContext::get()->get_poll().subscribe(stdin_.get_poll_info().extract_pollable_fd(this),
 | 
			
		||||
                                                           td::PollFlags::Read());
 | 
			
		||||
  loop();
 | 
			
		||||
  if (!no_input_) {
 | 
			
		||||
    td::actor::SchedulerContext::get()->get_poll().subscribe(stdin_.get_poll_info().extract_pollable_fd(this),
 | 
			
		||||
                                                             td::PollFlags::Read());
 | 
			
		||||
    loop();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TerminalIOImpl::tear_down() {
 | 
			
		||||
| 
						 | 
				
			
			@ -329,10 +331,10 @@ TerminalIOOutputter::~TerminalIOOutputter() {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
td::actor::ActorOwn<TerminalIO> TerminalIO::create(std::string prompt, bool use_readline,
 | 
			
		||||
td::actor::ActorOwn<TerminalIO> TerminalIO::create(std::string prompt, bool use_readline, bool no_input,
 | 
			
		||||
                                                   std::unique_ptr<Callback> callback) {
 | 
			
		||||
  return actor::create_actor<TerminalIOImpl>(actor::ActorOptions().with_name("terminal io").with_poll(), prompt,
 | 
			
		||||
                                             use_readline, std::move(callback));
 | 
			
		||||
                                             use_readline, no_input, std::move(callback));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TerminalIOImpl *TerminalIOImpl::instance_ = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ class TerminalIO : public actor::Actor {
 | 
			
		|||
  virtual void set_log_interface() = 0;
 | 
			
		||||
  virtual bool readline_used() const = 0;
 | 
			
		||||
 | 
			
		||||
  static td::actor::ActorOwn<TerminalIO> create(std::string prompt, bool use_readline,
 | 
			
		||||
  static td::actor::ActorOwn<TerminalIO> create(std::string prompt, bool use_readline, bool no_input,
 | 
			
		||||
                                                std::unique_ptr<Callback> callback);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,8 +66,8 @@ class TerminalIOImpl : public TerminalIO, td::ObserverBase {
 | 
			
		|||
  void on_net() {
 | 
			
		||||
    loop();
 | 
			
		||||
  }
 | 
			
		||||
  TerminalIOImpl(std::string prompt, bool use_readline, std::unique_ptr<Callback> callback)
 | 
			
		||||
      : prompt_(prompt), use_readline_(use_readline), callback_(std::move(callback)) {
 | 
			
		||||
  TerminalIOImpl(std::string prompt, bool use_readline, bool no_input, std::unique_ptr<Callback> callback)
 | 
			
		||||
      : prompt_(prompt), use_readline_(use_readline), no_input_(no_input), callback_(std::move(callback)) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int stdin_getc();
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +83,7 @@ class TerminalIOImpl : public TerminalIO, td::ObserverBase {
 | 
			
		|||
 | 
			
		||||
  std::string prompt_;
 | 
			
		||||
  bool use_readline_ = false;
 | 
			
		||||
  bool no_input_ = false;
 | 
			
		||||
  std::unique_ptr<Callback> callback_;
 | 
			
		||||
  std::mutex out_mutex_;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,7 +69,7 @@ if (TONLIB_ENABLE_JNI AND NOT ANDROID) # jni is available by default on Android
 | 
			
		|||
endif()
 | 
			
		||||
 | 
			
		||||
add_executable(tonlib-cli tonlib/tonlib-cli.cpp)
 | 
			
		||||
target_link_libraries(tonlib-cli tonlib tdactor tdutils terminal)
 | 
			
		||||
target_link_libraries(tonlib-cli tonlib tdactor tdutils terminal pow-miner-lib)
 | 
			
		||||
 | 
			
		||||
if (NOT CMAKE_CROSSCOMPILING)
 | 
			
		||||
  if (TONLIB_ENABLE_JNI)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,6 +77,16 @@ class TonlibClient : public td::actor::Actor {
 | 
			
		|||
    std::string rwallet_init_public_key;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template <class T, class P>
 | 
			
		||||
  void make_request(T&& request, P&& promise) {
 | 
			
		||||
    td::Promise<typename std::decay_t<T>::ReturnType> new_promise = std::move(promise);
 | 
			
		||||
 | 
			
		||||
    auto status = do_request(std::forward<T>(request), std::move(new_promise));
 | 
			
		||||
    if (status.is_error()) {
 | 
			
		||||
      new_promise.operator()(std::move(status));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  enum class State { Uninited, Running, Closed } state_ = State::Uninited;
 | 
			
		||||
  td::unique_ptr<TonlibCallback> callback_;
 | 
			
		||||
| 
						 | 
				
			
			@ -203,15 +213,6 @@ class TonlibClient : public td::actor::Actor {
 | 
			
		|||
 | 
			
		||||
  void make_any_request(tonlib_api::Function& function, QueryContext query_context,
 | 
			
		||||
                        td::Promise<tonlib_api::object_ptr<tonlib_api::Object>>&& promise);
 | 
			
		||||
  template <class T, class P>
 | 
			
		||||
  void make_request(T&& request, P&& promise) {
 | 
			
		||||
    td::Promise<typename std::decay_t<T>::ReturnType> new_promise = std::move(promise);
 | 
			
		||||
 | 
			
		||||
    auto status = do_request(std::forward<T>(request), std::move(new_promise));
 | 
			
		||||
    if (status.is_error()) {
 | 
			
		||||
      new_promise.operator()(std::move(status));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  td::Result<FullConfig> validate_config(tonlib_api::object_ptr<tonlib_api::config> config);
 | 
			
		||||
  void set_config(FullConfig config);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,8 +25,14 @@
 | 
			
		|||
 | 
			
		||||
    Copyright 2019-2020 Telegram Systems LLP
 | 
			
		||||
*/
 | 
			
		||||
#include "auto/tl/tonlib_api.h"
 | 
			
		||||
#include "block/block.h"
 | 
			
		||||
#include "common/bigint.hpp"
 | 
			
		||||
#include "common/refint.h"
 | 
			
		||||
#include "td/actor/actor.h"
 | 
			
		||||
 | 
			
		||||
#include "td/actor/common.h"
 | 
			
		||||
#include "td/utils/Time.h"
 | 
			
		||||
#include "td/utils/filesystem.h"
 | 
			
		||||
#include "td/utils/OptionParser.h"
 | 
			
		||||
#include "td/utils/overloaded.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +54,10 @@
 | 
			
		|||
 | 
			
		||||
#include "auto/tl/tonlib_api.hpp"
 | 
			
		||||
 | 
			
		||||
#include "crypto/util/Miner.h"
 | 
			
		||||
#include "vm/boc.h"
 | 
			
		||||
#include "vm/cells/CellBuilder.h"
 | 
			
		||||
 | 
			
		||||
#include <cinttypes>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <map>
 | 
			
		||||
| 
						 | 
				
			
			@ -106,6 +116,9 @@ td::Result<Grams> parse_grams(td::Slice grams) {
 | 
			
		|||
  return Grams{value};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Temporary hack
 | 
			
		||||
td::actor::Scheduler* global_scheduler_{nullptr};
 | 
			
		||||
 | 
			
		||||
class TonlibCli : public td::actor::Actor {
 | 
			
		||||
 public:
 | 
			
		||||
  struct Options {
 | 
			
		||||
| 
						 | 
				
			
			@ -153,6 +166,9 @@ class TonlibCli : public td::actor::Actor {
 | 
			
		|||
                                   make_object<tonlib_api::key>(public_key, secret.copy()), td::SecureString(password))
 | 
			
		||||
                             : nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    auto tonlib_api() const {
 | 
			
		||||
      return make_object<tonlib_api::accountAddress>(address->account_address_);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  std::map<std::uint64_t, td::Promise<tonlib_api::object_ptr<tonlib_api::Object>>> query_handlers_;
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +195,7 @@ class TonlibCli : public td::actor::Actor {
 | 
			
		|||
    };
 | 
			
		||||
    if (!options_.one_shot) {
 | 
			
		||||
      ref_cnt_++;
 | 
			
		||||
      io_ = td::TerminalIO::create("> ", options_.enable_readline, std::make_unique<Cb>(actor_shared(this)));
 | 
			
		||||
      io_ = td::TerminalIO::create("> ", options_.enable_readline, false, std::make_unique<Cb>(actor_shared(this)));
 | 
			
		||||
      td::actor::send_closure(io_, &td::TerminalIO::set_log_interface);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -317,6 +333,11 @@ class TonlibCli : public td::actor::Actor {
 | 
			
		|||
    td::TerminalIO::out() << "rwallet address <key_id> <public_key>\n";
 | 
			
		||||
    td::TerminalIO::out() << "rwallet init <key_id> <public_key> <start_at> [<seconds>:<value> ...]\n";
 | 
			
		||||
  }
 | 
			
		||||
  void pminer_help() {
 | 
			
		||||
    td::TerminalIO::out() << "pminer help\n";
 | 
			
		||||
    td::TerminalIO::out() << "pminer start <giver_addess> <my_address>\n";
 | 
			
		||||
    td::TerminalIO::out() << "pminer stop\n";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void parse_line(td::BufferSlice line) {
 | 
			
		||||
    if (is_closing_) {
 | 
			
		||||
| 
						 | 
				
			
			@ -374,6 +395,7 @@ class TonlibCli : public td::actor::Actor {
 | 
			
		|||
      dns_help();
 | 
			
		||||
      pchan_help();
 | 
			
		||||
      rwallet_help();
 | 
			
		||||
      pminer_help();
 | 
			
		||||
 | 
			
		||||
      td::TerminalIO::out()
 | 
			
		||||
          << "blockmode auto|manual\tWith auto mode, all queries will be executed with respect to the latest block. "
 | 
			
		||||
| 
						 | 
				
			
			@ -477,6 +499,8 @@ class TonlibCli : public td::actor::Actor {
 | 
			
		|||
      run_pchan_cmd(parser, std::move(cmd_promise));
 | 
			
		||||
    } else if (cmd == "rwallet") {
 | 
			
		||||
      run_rwallet_cmd(parser, std::move(cmd_promise));
 | 
			
		||||
    } else if (cmd == "pminer") {
 | 
			
		||||
      run_pminer_cmd(parser, std::move(cmd_promise));
 | 
			
		||||
    } else if (cmd == "gethistory") {
 | 
			
		||||
      get_history(parser.read_word(), std::move(cmd_promise));
 | 
			
		||||
    } else if (cmd == "guessrevision") {
 | 
			
		||||
| 
						 | 
				
			
			@ -556,6 +580,216 @@ class TonlibCli : public td::actor::Actor {
 | 
			
		|||
    promise.set_error(td::Status::Error("Unknown command"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  class PowMiner : public td::actor::Actor {
 | 
			
		||||
   public:
 | 
			
		||||
    class Callback {
 | 
			
		||||
     public:
 | 
			
		||||
    };
 | 
			
		||||
    struct Options {
 | 
			
		||||
      Address giver_address;
 | 
			
		||||
      Address my_address;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    PowMiner(Options options, td::actor::ActorId<tonlib::TonlibClient> client)
 | 
			
		||||
        : options_(std::move(options)), client_(std::move(client)) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   private:
 | 
			
		||||
    Options options_;
 | 
			
		||||
    td::actor::ActorId<tonlib::TonlibClient> client_;
 | 
			
		||||
 | 
			
		||||
    td::optional<ton::Miner::Options> miner_options_;
 | 
			
		||||
    static constexpr double QUERY_EACH = 5.0;
 | 
			
		||||
    td::Timestamp next_options_query_at_;
 | 
			
		||||
 | 
			
		||||
    bool need_run_miners_{false};
 | 
			
		||||
    td::CancellationTokenSource source_;
 | 
			
		||||
    ton::Miner::Options miner_options_copy_;
 | 
			
		||||
    std::size_t threads_alive_{0};
 | 
			
		||||
    std::vector<td::thread> threads_;
 | 
			
		||||
 | 
			
		||||
    bool close_flag_{false};
 | 
			
		||||
 | 
			
		||||
    template <class QueryT>
 | 
			
		||||
    void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> promise) {
 | 
			
		||||
      td::actor::send_lambda(client_,
 | 
			
		||||
                             [self = client_, query = std::move(query), promise = std::move(promise)]() mutable {
 | 
			
		||||
                               self.get_actor_unsafe().make_request(std::move(query), std::move(promise));
 | 
			
		||||
                             });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void start_up() override {
 | 
			
		||||
      next_options_query_at_ = td::Timestamp::now();
 | 
			
		||||
      loop();
 | 
			
		||||
    }
 | 
			
		||||
    void hangup() override {
 | 
			
		||||
      close_flag_ = true;
 | 
			
		||||
      source_.cancel();
 | 
			
		||||
      try_stop();
 | 
			
		||||
    }
 | 
			
		||||
    void try_stop() {
 | 
			
		||||
      if (threads_alive_ == 0) {
 | 
			
		||||
        td::TerminalIO::out() << "pminer: stopped\n";
 | 
			
		||||
        stop();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void loop() override {
 | 
			
		||||
      if (close_flag_) {
 | 
			
		||||
        try_stop();
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (next_options_query_at_ && next_options_query_at_.is_in_past()) {
 | 
			
		||||
        send_query(tonlib_api::smc_load(options_.giver_address.tonlib_api()),
 | 
			
		||||
                   promise_send_closure(td::actor::actor_id(this), &PowMiner::with_giver_state));
 | 
			
		||||
        next_options_query_at_ = {};
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (miner_options_ && threads_.empty() && need_run_miners_) {
 | 
			
		||||
        td::TerminalIO::out() << "pminer: start workers\n";
 | 
			
		||||
        need_run_miners_ = false;
 | 
			
		||||
        miner_options_copy_ = miner_options_.value();
 | 
			
		||||
        miner_options_copy_.token_ = source_.get_cancellation_token();
 | 
			
		||||
        auto n = td::thread::hardware_concurrency();
 | 
			
		||||
        threads_alive_ = n;
 | 
			
		||||
        for (td::uint32 i = 0; i < n; i++) {
 | 
			
		||||
          threads_.emplace_back([this, actor_id = actor_id(this)] {
 | 
			
		||||
            auto res = ton::Miner::run(miner_options_copy_);
 | 
			
		||||
            global_scheduler_->run_in_context_external(
 | 
			
		||||
                [&] { send_closure(actor_id, &PowMiner::got_answer, std::move(res)); });
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      alarm_timestamp().relax(next_options_query_at_);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void got_answer(td::optional<std::string> answer) {
 | 
			
		||||
      source_.cancel();
 | 
			
		||||
      if (--threads_alive_ == 0) {
 | 
			
		||||
        threads_.clear();
 | 
			
		||||
      }
 | 
			
		||||
      if (answer) {
 | 
			
		||||
        td::TerminalIO::out() << "pminer: got some result - sending query to the giver\n";
 | 
			
		||||
        vm::CellBuilder cb;
 | 
			
		||||
        cb.store_bytes(answer.unwrap());
 | 
			
		||||
        send_query(tonlib_api::raw_createAndSendMessage(
 | 
			
		||||
                       options_.giver_address.tonlib_api(), "",
 | 
			
		||||
                       vm::std_boc_serialize(cb.finalize_novm()).move_as_ok().as_slice().str()),
 | 
			
		||||
                   promise_send_closure(td::actor::actor_id(this), &PowMiner::on_query_sent));
 | 
			
		||||
      }
 | 
			
		||||
      loop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void on_query_sent(td::Result<tonlib_api::object_ptr<tonlib_api::ok>> r_ok) {
 | 
			
		||||
      LOG_IF(ERROR, r_ok.is_error()) << "pminer: " << r_ok.error();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void with_giver_state(td::Result<tonlib_api::object_ptr<tonlib_api::smc_info>> r_info) {
 | 
			
		||||
      if (r_info.is_error()) {
 | 
			
		||||
        return with_giver_info(r_info.move_as_error());
 | 
			
		||||
      }
 | 
			
		||||
      send_query(tonlib_api::smc_runGetMethod(r_info.ok()->id_,
 | 
			
		||||
                                              make_object<tonlib_api::smc_methodIdName>("get_pow_params"), {}),
 | 
			
		||||
                 promise_send_closure(td::actor::actor_id(this), &PowMiner::with_giver_info));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void with_giver_info(td::Result<tonlib_api::object_ptr<tonlib_api::smc_runResult>> r_info) {
 | 
			
		||||
      auto status = do_with_giver_info(std::move(r_info));
 | 
			
		||||
      LOG_IF(ERROR, status.is_error()) << "pminer: " << status;
 | 
			
		||||
      next_options_query_at_ = td::Timestamp::in(QUERY_EACH);
 | 
			
		||||
      return loop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    td::Result<td::RefInt256> to_number(const tonlib_api::object_ptr<tonlib_api::tvm_StackEntry>& entry,
 | 
			
		||||
                                        td::int32 bits) {
 | 
			
		||||
      if (entry->get_id() != tonlib_api::tvm_stackEntryNumber::ID) {
 | 
			
		||||
        return td::Status::Error("Expected stackEntryNumber");
 | 
			
		||||
      }
 | 
			
		||||
      auto& number_str = static_cast<const tonlib_api::tvm_stackEntryNumber&>(*entry.get()).number_->number_;
 | 
			
		||||
      auto num = td::make_refint();
 | 
			
		||||
      if (num.write().parse_dec(number_str.data(), (int)number_str.size()) < (int)number_str.size()) {
 | 
			
		||||
        return td::Status::Error("Failed to parse a number");
 | 
			
		||||
      }
 | 
			
		||||
      if (!num->unsigned_fits_bits(bits)) {
 | 
			
		||||
        return td::Status::Error(PSLICE() << "Number is too big " << num->to_dec_string() << " " << bits);
 | 
			
		||||
      }
 | 
			
		||||
      return num;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    td::Status do_with_giver_info(td::Result<tonlib_api::object_ptr<tonlib_api::smc_runResult>> r_info) {
 | 
			
		||||
      TRY_RESULT(info, std::move(r_info));
 | 
			
		||||
      if (info->stack_.size() < 2) {
 | 
			
		||||
        return td::Status::Error("Unexpected `get_pow_params` result format");
 | 
			
		||||
      }
 | 
			
		||||
      TRY_RESULT(seed, to_number(info->stack_[0], 128));
 | 
			
		||||
      TRY_RESULT(complexity, to_number(info->stack_[1], 256));
 | 
			
		||||
      ton::Miner::Options options;
 | 
			
		||||
      seed->export_bytes(options.seed.data(), 16, false);
 | 
			
		||||
      complexity->export_bytes(options.complexity.data(), 32, false);
 | 
			
		||||
 | 
			
		||||
      TRY_RESULT(address, block::StdAddress::parse(options_.my_address.address->account_address_));
 | 
			
		||||
      options.my_address = std::move(address);
 | 
			
		||||
      options.token_ = source_.get_cancellation_token();
 | 
			
		||||
 | 
			
		||||
      if (miner_options_ && miner_options_.value().seed == options.seed) {
 | 
			
		||||
        return td::Status::OK();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      td::TerminalIO::out() << "pminer: got new options\n";
 | 
			
		||||
      td::BigInt256 bigpower, hrate;
 | 
			
		||||
      bigpower.set_pow2(256).mod_div(*complexity, hrate);
 | 
			
		||||
      long long hash_rate = hrate.to_long();
 | 
			
		||||
      td::TerminalIO::out() << "[ expected required hashes for success: " << hash_rate << " ]\n";
 | 
			
		||||
      miner_options_ = std::move(options);
 | 
			
		||||
      need_run_miners_ = true;
 | 
			
		||||
      source_.cancel();
 | 
			
		||||
 | 
			
		||||
      return td::Status::OK();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  td::uint64 pow_miner_id_{0};
 | 
			
		||||
  std::map<td::uint64, td::actor::ActorOwn<PowMiner>> pow_miners_;
 | 
			
		||||
 | 
			
		||||
  void pminer_start(td::ConstParser& parser, td::Promise<td::Unit> promise) {
 | 
			
		||||
    if (!pow_miners_.empty()) {
 | 
			
		||||
      promise.set_error(td::Status::Error("One pminer is already running"));
 | 
			
		||||
    }
 | 
			
		||||
    TRY_RESULT_PROMISE_PREFIX(promise, giver_address, to_account_address(parser.read_word(), false), "giver address");
 | 
			
		||||
    TRY_RESULT_PROMISE_PREFIX(promise, my_address, to_account_address(parser.read_word(), false), "my address");
 | 
			
		||||
 | 
			
		||||
    auto id = ++pow_miner_id_;
 | 
			
		||||
 | 
			
		||||
    PowMiner::Options options;
 | 
			
		||||
    options.giver_address = std::move(giver_address);
 | 
			
		||||
    options.my_address = std::move(my_address);
 | 
			
		||||
    pow_miners_.emplace(id, td::actor::create_actor<PowMiner>("PowMiner", std::move(options), client_.get()));
 | 
			
		||||
    td::TerminalIO::out() << "Miner #" << id << " created";
 | 
			
		||||
    promise.set_value({});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void pminer_stop(td::ConstParser& parser, td::Promise<td::Unit> promise) {
 | 
			
		||||
    pow_miners_.clear();
 | 
			
		||||
    promise.set_value({});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void run_pminer_cmd(td::ConstParser& parser, td::Promise<td::Unit> promise) {
 | 
			
		||||
    auto cmd = parser.read_word();
 | 
			
		||||
    if (cmd == "help") {
 | 
			
		||||
      pminer_help();
 | 
			
		||||
      return promise.set_value(td::Unit());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (cmd == "start") {
 | 
			
		||||
      return pminer_start(parser, std::move(promise));
 | 
			
		||||
    }
 | 
			
		||||
    if (cmd == "stop") {
 | 
			
		||||
      return pminer_stop(parser, std::move(promise));
 | 
			
		||||
    }
 | 
			
		||||
    promise.set_error(td::Status::Error("Unknown command"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void run_pchan_cmd(td::ConstParser& parser, td::Promise<td::Unit> promise) {
 | 
			
		||||
    auto cmd = parser.read_word();
 | 
			
		||||
    if (cmd == "help") {
 | 
			
		||||
| 
						 | 
				
			
			@ -2121,6 +2355,8 @@ int main(int argc, char* argv[]) {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  td::actor::Scheduler scheduler({2});
 | 
			
		||||
  // temporaty hack
 | 
			
		||||
  global_scheduler_ = &scheduler;
 | 
			
		||||
  scheduler.run_in_context([&] { td::actor::create_actor<TonlibCli>("console", options).release(); });
 | 
			
		||||
  scheduler.run();
 | 
			
		||||
  return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ void ValidatorEngineConsole::run() {
 | 
			
		|||
   private:
 | 
			
		||||
    td::actor::ActorId<ValidatorEngineConsole> id_;
 | 
			
		||||
  };
 | 
			
		||||
  io_ = td::TerminalIO::create("> ", readline_enabled_, std::make_unique<Cb>(actor_id(this)));
 | 
			
		||||
  io_ = td::TerminalIO::create("> ", readline_enabled_, ex_mode_, std::make_unique<Cb>(actor_id(this)));
 | 
			
		||||
  td::actor::send_closure(io_, &td::TerminalIO::set_log_interface);
 | 
			
		||||
 | 
			
		||||
  td::TerminalIO::out() << "connecting to " << remote_addr_ << "\n";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1958,6 +1958,7 @@ void ValidatorManagerImpl::add_handle_to_lru(BlockHandle handle) {
 | 
			
		|||
  auto it = handle_lru_map_.find(handle->id());
 | 
			
		||||
  if (it != handle_lru_map_.end()) {
 | 
			
		||||
    CHECK(it->second->handle() == handle);
 | 
			
		||||
    it->second->remove();
 | 
			
		||||
    handle_lru_.put(it->second.get());
 | 
			
		||||
  } else {
 | 
			
		||||
    auto id = handle->id();
 | 
			
		||||
| 
						 | 
				
			
			@ -1978,6 +1979,7 @@ void ValidatorManagerImpl::add_handle_to_lru(BlockHandle handle) {
 | 
			
		|||
BlockHandle ValidatorManagerImpl::get_handle_from_lru(BlockIdExt id) {
 | 
			
		||||
  auto it = handle_lru_map_.find(id);
 | 
			
		||||
  if (it != handle_lru_map_.end()) {
 | 
			
		||||
    it->second->remove();
 | 
			
		||||
    handle_lru_.put(it->second.get());
 | 
			
		||||
    auto handle = it->second->handle();
 | 
			
		||||
    CHECK(handle->id() == id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue