BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
debug_witness.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
25 
28 
30 
31 #include <fc/thread/thread.hpp>
32 
33 #include <iostream>
34 
35 using namespace graphene::debug_witness_plugin;
36 using std::string;
37 using std::vector;
38 
39 namespace bpo = boost::program_options;
40 
41 debug_witness_plugin::~debug_witness_plugin() {}
42 
44  boost::program_options::options_description& command_line_options,
45  boost::program_options::options_description& config_file_options)
46 {
47  auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
48  command_line_options.add_options()
49  ("debug-private-key", bpo::value<vector<string>>()->composing()->multitoken()->
50  DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
51  "Tuple of [PublicKey, WIF private key] (may specify multiple times)");
52  config_file_options.add(command_line_options);
53 }
54 
56 {
57  return "debug_witness";
58 }
59 
60 void debug_witness_plugin::plugin_initialize(const boost::program_options::variables_map& options)
61 { try {
62  ilog("debug_witness plugin: plugin_initialize() begin");
63  _options = &options;
64 
65  if( options.count("debug-private-key") )
66  {
67  const std::vector<std::string> key_id_to_wif_pair_strings = options["debug-private-key"].as<std::vector<std::string>>();
68  for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
69  {
70  auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >(key_id_to_wif_pair_string, GRAPHENE_MAX_NESTED_OBJECTS);
71  idump((key_id_to_wif_pair));
72  fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
73  if (!private_key)
74  {
75  // the key isn't in WIF format; see if they are still passing the old native private key format. This is
76  // just here to ease the transition, can be removed soon
77  try
78  {
79  private_key = fc::variant( key_id_to_wif_pair.second, GRAPHENE_MAX_NESTED_OBJECTS ).as<fc::ecc::private_key>( GRAPHENE_MAX_NESTED_OBJECTS );
80  }
81  catch (const fc::exception&)
82  {
83  FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second));
84  }
85  }
86  _private_keys[key_id_to_wif_pair.first] = *private_key;
87  }
88  }
89  ilog("debug_witness plugin: plugin_initialize() end");
91 
93 {
94  ilog("debug_witness_plugin::plugin_startup() begin");
95  chain::database& db = database();
96 
97  // connect needed signals
98 
99  _applied_block_conn = db.applied_block.connect([this](const graphene::chain::signed_block& b){ on_applied_block(b); });
100  _changed_objects_conn = db.changed_objects.connect([this](const std::vector<graphene::db::object_id_type>& ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ on_changed_objects(ids, impacted_accounts); });
101  _removed_objects_conn = db.removed_objects.connect([this](const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*>& objs, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts){ on_removed_objects(ids, objs, impacted_accounts); });
102 
103  return;
104 }
105 
106 void debug_witness_plugin::on_changed_objects( const std::vector<graphene::db::object_id_type>& ids, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts )
107 {
108  if( _json_object_stream && (ids.size() > 0) )
109  {
110  const chain::database& db = database();
111  for( const graphene::db::object_id_type& oid : ids )
112  {
113  const graphene::db::object* obj = db.find_object( oid );
114  if( obj != nullptr )
115  {
116  (*_json_object_stream) << fc::json::to_string( obj->to_variant() ) << '\n';
117  }
118  }
119  }
120 }
121 
122 void debug_witness_plugin::on_removed_objects( const std::vector<graphene::db::object_id_type>& ids, const std::vector<const graphene::db::object*> objs, const fc::flat_set<graphene::chain::account_id_type>& impacted_accounts )
123 {
124  if( _json_object_stream )
125  {
126  for( const graphene::db::object* obj : objs )
127  {
128  (*_json_object_stream) << "{\"id\":" << fc::json::to_string( obj->id ) << "}\n";
129  }
130  }
131 }
132 
133 void debug_witness_plugin::on_applied_block( const graphene::chain::signed_block& b )
134 {
135  if( _json_object_stream )
136  {
137  (*_json_object_stream) << "{\"bn\":" << fc::to_string( b.block_num() ) << "}\n";
138  }
139 }
140 
141 void debug_witness_plugin::set_json_object_stream( const std::string& filename )
142 {
143  if( _json_object_stream )
144  {
145  _json_object_stream->close();
146  _json_object_stream.reset();
147  }
148  _json_object_stream = std::make_shared< std::ofstream >( filename );
149 }
150 
152 {
153  if( _json_object_stream )
154  _json_object_stream->flush();
155 }
156 
158 {
159  if( _json_object_stream )
160  {
161  _json_object_stream->close();
162  _json_object_stream.reset();
163  }
164  return;
165 }
static string to_string(const variant &v, output_formatting format=stringify_large_ints_and_doubles, uint32_t max_depth=DEFAULT_MAX_RECURSION_DEPTH)
Definition: json.cpp:638
virtual void plugin_initialize(const boost::program_options::variables_map &options) override
Perform early startup routines and register plugin indexes, callbacks, etc.
fc::signal< void(const vector< object_id_type > &, const vector< const object * > &, const flat_set< account_id_type > &)> removed_objects
Definition: database.hpp:220
T as(uint32_t max_depth) const
Definition: variant.hpp:336
const object * find_object(object_id_type id) const
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:197
#define GRAPHENE_MAX_NESTED_OBJECTS
Definition: config.hpp:31
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
fc::optional< fc::ecc::private_key > wif_to_key(const std::string &wif_key)
fc::signal< void(const vector< object_id_type > &, const flat_set< account_id_type > &)> changed_objects
Definition: database.hpp:215
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
Definition: exception.hpp:56
void set_json_object_stream(const std::string &filename)
#define FC_THROW(...)
Definition: exception.hpp:366
static sha256 hash(const char *d, uint32_t dlen)
Definition: sha256.cpp:41
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
std::string key_to_wif(const fc::sha256 &private_secret)
chain::database & database()
Definition: plugin.hpp:114
virtual void plugin_set_program_options(boost::program_options::options_description &command_line_options, boost::program_options::options_description &config_file_options) override
Fill in command line parameters used by the plugin.
#define ilog(FORMAT,...)
Definition: logger.hpp:117
#define idump(SEQ)
Definition: logger.hpp:166
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object&#39;s.
Definition: variant.hpp:198
static private_key regenerate(const fc::sha256 &secret)
#define DEFAULT_VALUE_VECTOR(value)
Definition: plugin.hpp:139
virtual void plugin_startup() override
Begin normal runtime operations.
virtual variant to_variant() const =0
std::string to_string(double)
Definition: string.cpp:73
uint32_t block_num() const
Definition: block.hpp:34
base for all database objects
Definition: object.hpp:62
an elliptic curve private key.
Definition: elliptic.hpp:89
#define FC_LOG_AND_RETHROW()
Definition: exception.hpp:394
virtual void plugin_shutdown() override
Cleanly shut down the plugin.