Scorum
debug_node_plugin.cpp
Go to the documentation of this file.
1 
3 #include <scorum/app/plugin.hpp>
7 
8 #include <fc/io/buffered_iostream.hpp>
9 #include <fc/io/fstream.hpp>
10 #include <fc/io/json.hpp>
11 
12 #include <fc/thread/future.hpp>
13 #include <fc/thread/mutex.hpp>
14 #include <fc/thread/scoped_lock.hpp>
15 
16 #include <graphene/utilities/key_conversion.hpp>
17 
18 #include <sstream>
19 #include <string>
20 
21 namespace scorum {
22 namespace plugin {
23 namespace debug_node {
24 
26  : plugin(app)
27 {
28 }
30 {
31 }
32 
33 std::string debug_node_plugin::plugin_name() const
34 {
35  return "debug_node";
36 }
37 
38 void debug_node_plugin::plugin_set_program_options(boost::program_options::options_description& cli,
39  boost::program_options::options_description& cfg)
40 {
41  // cli.add_options()("edit-script,e", boost::program_options::value<std::vector<std::string>>()->composing(),
42  // "Database edits to apply on startup (may specify multiple times)");
43  cfg.add(cli);
44 }
45 
46 void debug_node_plugin::plugin_initialize(const boost::program_options::variables_map& options)
47 {
49 }
50 
52 {
53  if (logging)
54  ilog("debug_node_plugin::plugin_startup() begin");
55  chain::database& db = database();
56 
57  // connect needed signals
58  _applied_block_conn = db.applied_block.connect([this](const chain::signed_block& b) { on_applied_block(b); });
59 
60  app().register_api_factory<debug_node_api>("debug_node_api");
61 }
62 
64  const std::string& debug_key, uint32_t count, uint32_t skip, uint32_t miss_blocks, private_key_storage* key_storage)
65 {
66  if (count == 0)
67  return 0;
68 
70 
71  auto& witness_svc = db.witness_service();
72 
73  fc::optional<fc::ecc::private_key> debug_private_key;
74  scorum::chain::public_key_type debug_public_key;
75  if (debug_key != "")
76  {
77  debug_private_key = graphene::utilities::wif_to_key(debug_key);
78  FC_ASSERT(debug_private_key.valid());
79  debug_public_key = debug_private_key->get_public_key();
80  }
81 
82  uint32_t slot = miss_blocks + 1, produced = 0;
83  while (produced < count)
84  {
85  uint32_t new_slot = miss_blocks + 1;
86  std::string scheduled_witness_name = db.get_scheduled_witness(slot);
87  fc::time_point_sec scheduled_time = db.get_slot_time(slot);
88  const chain::witness_object& scheduled_witness = witness_svc.get(scheduled_witness_name);
89  scorum::chain::public_key_type scheduled_key = scheduled_witness.signing_key;
90  if (debug_key != "")
91  {
92  if (logging)
93  wlog("scheduled key is: ${sk} dbg key is: ${dk}", ("sk", scheduled_key)("dk", debug_public_key));
94  if (scheduled_key != debug_public_key)
95  {
96  if (logging)
97  wlog("Modified key for witness ${w}", ("w", scheduled_witness_name));
99  [=](chain::database& db) {
100  db.modify(scheduled_witness,
101  [&](chain::witness_object& w) { w.signing_key = debug_public_key; });
102  },
103  skip);
104  }
105  }
106  else
107  {
108  debug_private_key.reset();
109  if (key_storage != nullptr)
110  key_storage->maybe_get_private_key(debug_private_key, scheduled_key, scheduled_witness_name);
111  if (!debug_private_key.valid())
112  {
113  if (logging)
114  elog("Skipping ${wit} because I don't know the private key", ("wit", scheduled_witness_name));
115  new_slot = slot + 1;
116  FC_ASSERT(slot < miss_blocks + 50);
117  }
118  }
119  db.generate_block(scheduled_time, scheduled_witness_name, *debug_private_key, skip);
120  ++produced;
121  slot = new_slot;
122  }
123 
124  return count;
125 }
126 
127 uint32_t debug_node_plugin::debug_generate_blocks_until(const std::string& debug_key,
128  const fc::time_point_sec& head_block_time,
129  bool generate_sparsely,
130  uint32_t skip,
131  private_key_storage* key_storage)
132 {
134 
135  if (db.head_block_time() >= head_block_time)
136  return 0;
137 
138  uint32_t new_blocks = 0;
139 
140  if (generate_sparsely)
141  {
142  new_blocks += debug_generate_blocks(debug_key, 1, skip);
143  auto slots_to_miss = db.get_slot_at_time(head_block_time);
144  if (slots_to_miss > 1)
145  {
146  slots_to_miss--;
147  new_blocks += debug_generate_blocks(debug_key, 1, skip, slots_to_miss, key_storage);
148  }
149  }
150  else
151  {
152  while (db.head_block_time() < head_block_time)
153  new_blocks += debug_generate_blocks(debug_key, 1);
154  }
155 
156  return new_blocks;
157 }
158 
159 void debug_node_plugin::apply_debug_updates()
160 {
161  // this was a method on database in Graphene
162  chain::database& db = database();
163  chain::block_id_type head_id = db.head_block_id();
164  auto it = _debug_updates.find(head_id);
165  if (it == _debug_updates.end())
166  return;
167 
168  for (auto& update : it->second)
169  update(db);
170 }
171 
172 void debug_node_plugin::on_applied_block(const chain::signed_block& b)
173 {
174  try
175  {
176  if (!_debug_updates.empty())
177  apply_debug_updates();
178  }
179  FC_LOG_AND_RETHROW()
180 }
181 
183 {
184 }
185 
186 } // namespace debug_node
187 } // namespace plugin
188 } // namespace scorum
189 
void register_api_factory(const std::string &name, std::function< fc::api_ptr(const api_context &)> factory)
application & app() const
Definition: plugin.hpp:119
void print_greeting()
Definition: plugin.cpp:69
chain::database & database()
Definition: plugin.hpp:115
tracks the blockchain state in an extensible manner
Definition: database.hpp:52
signed_block generate_block(const fc::time_point_sec when, const account_name_type &witness_owner, const fc::ecc::private_key &block_signing_private_key, uint32_t skip)
Definition: database.cpp:800
uint32_t get_slot_at_time(fc::time_point_sec when) const
Definition: database.cpp:1122
time_point_sec head_block_time() const
Definition: database.cpp:1222
account_name_type get_scheduled_witness(uint32_t slot_num) const
Get the witness scheduled for block production in a slot.
Definition: database.cpp:1086
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:221
block_id_type head_block_id() const
Definition: database.cpp:1232
fc::time_point_sec get_slot_time(uint32_t slot_num) const
Definition: database.cpp:1095
virtual void plugin_startup() override
Begin normal runtime operations.
uint32_t debug_generate_blocks_until(const std::string &debug_key, const fc::time_point_sec &head_block_time, bool generate_sparsely, uint32_t skip=scorum::chain::database::skip_nothing, private_key_storage *key_storage=nullptr)
void debug_update(Lambda &&callback, uint32_t skip=scorum::chain::database::skip_nothing)
uint32_t debug_generate_blocks(const std::string &debug_key, uint32_t count, uint32_t skip=scorum::chain::database::skip_nothing, uint32_t miss_blocks=0, private_key_storage *key_storage=nullptr)
virtual void plugin_set_program_options(boost::program_options::options_description &cli, boost::program_options::options_description &cfg) override
Fill in command line parameters used by the plugin.
virtual std::string plugin_name() const override
virtual void plugin_initialize(const boost::program_options::variables_map &options) override
Perform early startup routines and register plugin indexes, callbacks, etc.
virtual void plugin_shutdown() override
Cleanly shut down the plugin.
virtual void maybe_get_private_key(fc::optional< fc::ecc::private_key > &result, const scorum::chain::public_key_type &pubkey, const std::string &account_name)=0
void update(fc::flat_map< uuid_type, bet_resolved_operation > &results, const bet_data &bet, asset income, uuid_type game_uuid, bet_resolve_kind kind)
fc::ripemd160 block_id_type
Definition: types.hpp:63
Definition: asset.cpp:15
#define SCORUM_DEFINE_PLUGIN(plugin_name, plugin_class)
Definition: plugin.hpp:156