BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet 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 {
43  cleanup();
44 }
45 
46 void debug_witness_plugin::plugin_set_program_options(
47  boost::program_options::options_description& command_line_options,
48  boost::program_options::options_description& config_file_options)
49 {
50  auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
51  command_line_options.add_options()
52  ("debug-private-key", bpo::value<vector<string>>()->composing()->multitoken()->
53  DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
54  "Tuple of [PublicKey, WIF private key] (may specify multiple times)");
55  config_file_options.add(command_line_options);
56 }
57 
58 std::string debug_witness_plugin::plugin_name()const
59 {
60  return "debug_witness";
61 }
62 
63 void debug_witness_plugin::plugin_initialize(const boost::program_options::variables_map& options)
64 { try {
65  ilog("debug_witness plugin: plugin_initialize() begin");
66  _options = &options;
67 
68  if( options.count("debug-private-key") > 0 )
69  {
70  const std::vector<std::string> key_id_to_wif_pair_strings = options["debug-private-key"].as<std::vector<std::string>>();
71  for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
72  {
73  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);
74  idump((key_id_to_wif_pair));
75  fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
76  if (!private_key)
77  {
78  // the key isn't in WIF format; see if they are still passing the old native private key format. This is
79  // just here to ease the transition, can be removed soon
80  try
81  {
82  private_key = fc::variant( key_id_to_wif_pair.second, GRAPHENE_MAX_NESTED_OBJECTS ).as<fc::ecc::private_key>( GRAPHENE_MAX_NESTED_OBJECTS );
83  }
84  catch (const fc::exception&)
85  {
86  FC_THROW("Invalid WIF-format private key ${key_string}", ("key_string", key_id_to_wif_pair.second));
87  }
88  }
89  _private_keys[key_id_to_wif_pair.first] = *private_key;
90  }
91  }
92  ilog("debug_witness plugin: plugin_initialize() end");
94 
95 void debug_witness_plugin::plugin_startup()
96 {
97  ilog("debug_witness_plugin::plugin_startup() begin");
98  chain::database& db = database();
99 
100  // connect needed signals
101 
102  _applied_block_conn = db.applied_block.connect([this](const graphene::chain::signed_block& b){ on_applied_block(b); });
103  _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); });
104  _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); });
105 
106 }
107 
108 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 )
109 {
110  if( _json_object_stream && (ids.size() > 0) )
111  {
112  const chain::database& db = database();
113  for( const graphene::db::object_id_type& oid : ids )
114  {
115  const graphene::db::object* obj = db.find_object( oid );
116  if( obj != nullptr )
117  {
118  (*_json_object_stream) << fc::json::to_string( obj->to_variant() ) << '\n';
119  }
120  }
121  }
122 }
123 
124 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 )
125 {
126  if( _json_object_stream )
127  {
128  for( const graphene::db::object* obj : objs )
129  {
130  (*_json_object_stream) << "{\"id\":" << fc::json::to_string( obj->id ) << "}\n";
131  }
132  }
133 }
134 
135 void debug_witness_plugin::on_applied_block( const graphene::chain::signed_block& b )
136 {
137  if( _json_object_stream )
138  {
139  (*_json_object_stream) << "{\"bn\":" << fc::to_string( b.block_num() ) << "}\n";
140  }
141 }
142 
143 void debug_witness_plugin::set_json_object_stream( const std::string& filename )
144 {
145  if( _json_object_stream )
146  {
147  _json_object_stream->close();
148  _json_object_stream.reset();
149  }
150  _json_object_stream = std::make_shared< std::ofstream >( filename );
151 }
152 
153 void debug_witness_plugin::flush_json_object_stream()
154 {
155  if( _json_object_stream )
156  _json_object_stream->flush();
157 }
158 
159 void debug_witness_plugin::plugin_shutdown()
160 {
161  cleanup();
162 }
163 
164 void debug_witness_plugin::cleanup()
165 {
166  if( _json_object_stream )
167  {
168  _json_object_stream->close();
169  _json_object_stream.reset();
170  }
171 }
graphene::db::object_database::find_object
const object * find_object(const object_id_type &id) const
Definition: object_database.cpp:43
graphene::chain::database
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
fc::exception
Used to generate a useful error report when an exception is thrown.
Definition: exception.hpp:56
fc::to_string
std::string to_string(double)
Definition: string.cpp:73
database.hpp
debug_witness.hpp
graphene::app::plugin::database
chain::database & database()
Definition: plugin.hpp:115
graphene::utilities::key_to_wif
std::string key_to_wif(const fc::sha256 &private_secret)
Definition: key_conversion.cpp:30
graphene::utilities::wif_to_key
fc::optional< fc::ecc::private_key > wif_to_key(const std::string &wif_key)
Definition: key_conversion.cpp:47
FC_THROW
#define FC_THROW( ...)
Definition: exception.hpp:366
FC_LOG_AND_RETHROW
#define FC_LOG_AND_RETHROW()
Definition: exception.hpp:395
graphene::chain::database::removed_objects
fc::signal< void(const vector< object_id_type > &, const vector< const object * > &, const flat_set< account_id_type > &)> removed_objects
Definition: database.hpp:648
graphene::chain::database::applied_block
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:624
graphene::protocol::public_key_type
Definition: types.hpp:312
fc::json::to_string
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:650
graphene::chain::database::changed_objects
fc::signal< void(const vector< object_id_type > &, const flat_set< account_id_type > &)> changed_objects
Definition: database.hpp:642
graphene::protocol::block_header::block_num
uint32_t block_num() const
Definition: block.hpp:34
graphene::db::object::to_variant
virtual fc::variant to_variant() const =0
fc::ecc::private_key
an elliptic curve private key.
Definition: elliptic.hpp:89
ilog
#define ilog(FORMAT,...)
Definition: logger.hpp:117
thread.hpp
fc::variant::as
T as(uint32_t max_depth) const
Definition: variant.hpp:337
DEFAULT_VALUE_VECTOR
#define DEFAULT_VALUE_VECTOR(value)
Definition: plugin.hpp:136
fc::variant
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition: variant.hpp:198
graphene::db::object_id_type
Definition: object_id.hpp:30
idump
#define idump(SEQ)
Definition: logger.hpp:166
GRAPHENE_MAX_NESTED_OBJECTS
#define GRAPHENE_MAX_NESTED_OBJECTS
Definition: config.hpp:33
fc::optional
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
key_conversion.hpp
graphene::protocol::signed_block
Definition: block.hpp:64
witness_object.hpp
fc::ecc::private_key::regenerate
static private_key regenerate(const fc::sha256 &secret)
Definition: elliptic_impl_priv.cpp:52
fc::sha256::hash
static sha256 hash(const char *d, uint32_t dlen)
Definition: sha256.cpp:41
graphene::debug_witness_plugin
Definition: debug_witness.hpp:33
graphene::db::object
base for all database objects
Definition: object.hpp:61