BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
db_debug.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  */
24 
26 
34 
35 namespace graphene { namespace chain {
36 
42 {
43  const auto& db = *this;
44  const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db);
45 
46  const auto& balance_index = db.get_index_type<account_balance_index>().indices();
47  const auto& statistics_index = db.get_index_type<account_stats_index>().indices();
48  const auto& bids = db.get_index_type<collateral_bid_index>().indices();
49  const auto& settle_index = db.get_index_type<force_settlement_index>().indices();
50  const auto& htlcs = db.get_index_type<htlc_index>().indices();
51  map<asset_id_type,share_type> total_balances;
52  map<asset_id_type,share_type> total_debts;
53  share_type core_in_orders;
54  share_type reported_core_in_orders;
55 
56  for( const account_balance_object& a : balance_index )
57  {
58  // idump(("balance")(a));
59  total_balances[a.asset_type] += a.balance;
60  }
61  for( const force_settlement_object& s : settle_index )
62  {
63  total_balances[s.balance.asset_id] += s.balance.amount;
64  }
65  for( const vesting_balance_object& vbo : db.get_index_type< vesting_balance_index >().indices() )
66  total_balances[ vbo.balance.asset_id ] += vbo.balance.amount;
67  for( const fba_accumulator_object& fba : db.get_index_type< simple_index< fba_accumulator_object > >() )
68  total_balances[ asset_id_type() ] += fba.accumulated_fba_fees;
69  for( const account_statistics_object& s : statistics_index )
70  {
71  // idump(("statistics")(s));
72  reported_core_in_orders += s.total_core_in_orders;
73  }
74  for( const collateral_bid_object& b : bids )
75  total_balances[b.inv_swan_price.base.asset_id] += b.inv_swan_price.base.amount;
76  for( const limit_order_object& o : db.get_index_type<limit_order_index>().indices() )
77  {
78  // idump(("limit_order")(o));
79  auto for_sale = o.amount_for_sale();
80  if( for_sale.asset_id == asset_id_type() ) core_in_orders += for_sale.amount;
81  total_balances[for_sale.asset_id] += for_sale.amount;
82  }
83  for( const call_order_object& o : db.get_index_type<call_order_index>().indices() )
84  {
85 // idump(("call_order")(o));
86  auto col = o.get_collateral();
87  if( col.asset_id == asset_id_type() ) core_in_orders += col.amount;
88  total_balances[col.asset_id] += col.amount;
89  total_debts[o.get_debt().asset_id] += o.get_debt().amount;
90  }
91  for( const asset_object& asset_obj : db.get_index_type<asset_index>().indices() )
92  {
93  total_balances[asset_obj.get_id()] += asset_obj.dynamic_asset_data_id(db).accumulated_fees;
94  total_balances[asset_id_type()] += asset_obj.dynamic_asset_data_id(db).fee_pool;
95 // edump((total_balances[asset_obj.id])(asset_obj.dynamic_asset_data_id(db).current_supply ) );
96  }
97  for( const auto& htlc : htlcs )
98  total_balances[htlc.transfer.asset_id] += htlc.transfer.amount;
99 
100  if( total_balances[asset_id_type()].value != core_asset_data.current_supply.value )
101  {
102  FC_THROW( "computed balance of CORE mismatch",
103  ("computed value",total_balances[asset_id_type()].value)
104  ("current supply",core_asset_data.current_supply.value) );
105  }
106 
107 
108  /*
109  const auto& vbidx = db.get_index_type<simple_index<vesting_balance_object>>();
110  for( const auto& s : vbidx )
111  {
112 // idump(("vesting_balance")(s));
113  }
114  */
115 }
116 
118 {
119  constexpr uint8_t db_action_nil = 0;
120  constexpr uint8_t db_action_create = 1;
121  constexpr uint8_t db_action_write = 2;
122  constexpr uint8_t db_action_update = 3;
123  constexpr uint8_t db_action_delete = 4;
124 
125  // "_action" : "create" object must not exist, unspecified fields take defaults
126  // "_action" : "write" object may exist, is replaced entirely, unspecified fields take defaults
127  // "_action" : "update" object must exist, unspecified fields don't change
128  // "_action" : "delete" object must exist, will be deleted
129 
130  // if _action is unspecified:
131  // - delete if object contains only ID field
132  // - otherwise, write
133 
134  object_id_type oid;
135  uint8_t action = db_action_nil;
136  auto it_id = vo.find("id");
137  FC_ASSERT( it_id != vo.end() );
138 
139  from_variant( it_id->value(), oid );
140  action = ( vo.size() == 1 ) ? db_action_delete : db_action_write;
141 
142  from_variant( vo["id"], oid );
143  if( vo.size() == 1 )
144  action = db_action_delete;
145  auto it_action = vo.find("_action" );
146  if( it_action != vo.end() )
147  {
148  const std::string& str_action = it_action->value().get_string();
149  if( str_action == "create" )
150  action = db_action_create;
151  else if( str_action == "write" )
152  action = db_action_write;
153  else if( str_action == "update" )
154  action = db_action_update;
155  else if( str_action == "delete" )
156  action = db_action_delete;
157  }
158 
159  auto& idx = db.get_index( oid );
160 
161  switch( action )
162  {
163  case db_action_create:
164  FC_ASSERT( false );
165  break;
166  case db_action_write:
167  db.modify( db.get_object( oid ), [&]( object& obj )
168  {
169  idx.object_default( obj );
170  idx.object_from_variant( vo, obj, GRAPHENE_MAX_NESTED_OBJECTS );
171  } );
172  break;
173  case db_action_update:
174  db.modify( db.get_object( oid ), [&]( object& obj )
175  {
176  idx.object_from_variant( vo, obj, GRAPHENE_MAX_NESTED_OBJECTS );
177  } );
178  break;
179  case db_action_delete:
180  db.remove( db.get_object( oid ) );
181  break;
182  default:
183  FC_ASSERT( false );
184  }
185 }
186 
188 {
189  block_id_type head_id = head_block_id();
190  auto it = _node_property_object.debug_updates.find( head_id );
191  if( it == _node_property_object.debug_updates.end() )
192  return;
193  for( const fc::variant_object& update : it->second )
194  debug_apply_update( *this, update );
195 }
196 
198 {
199  block_id_type head_id = head_block_id();
200  auto it = _node_property_object.debug_updates.find( head_id );
201  if( it == _node_property_object.debug_updates.end() )
202  it = _node_property_object.debug_updates.emplace( head_id, std::vector< fc::variant_object >() ).first;
203  it->second.emplace_back( update );
204 
205  optional<signed_block> head_block = fetch_block_by_id( head_id );
206  FC_ASSERT( head_block.valid() );
207 
208  // What the last block does has been changed by adding to node_property_object, so we have to re-apply it
209  pop_block();
210  push_block( *head_block );
211 }
212 
213 } }
fc::variant_object::find
iterator find(const string &key) const
Definition: variant_object.cpp:64
fc::variant_object
An order-perserving dictionary of variant's.
Definition: variant_object.hpp:20
graphene::chain::database
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
asset_object.hpp
graphene::chain::node_property_object::debug_updates
std::map< block_id_type, std::vector< fc::variant_object > > debug_updates
Definition: node_property_object.hpp:46
database.hpp
graphene::db::simple_index
A simple index uses a vector<unique_ptr<T>> to store data.
Definition: simple_index.hpp:38
FC_THROW
#define FC_THROW( ...)
Definition: exception.hpp:366
graphene::chain::asset_dynamic_data_object::current_supply
share_type current_supply
The number of shares currently in existence.
Definition: asset_object.hpp:61
graphene::chain::asset_object
tracks the parameters of an asset
Definition: asset_object.hpp:75
graphene::chain::database::push_block
bool push_block(const signed_block &b, uint32_t skip=skip_nothing)
Definition: db_block.cpp:118
graphene::chain::database::pop_block
void pop_block()
Definition: db_block.cpp:523
graphene::chain::account_balance_object
Tracks the balance of a single account/asset pair.
Definition: account_object.hpp:157
fc::from_variant
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
Definition: flat.hpp:116
graphene::chain::database::fetch_block_by_id
optional< signed_block > fetch_block_by_id(const block_id_type &id) const
Definition: db_block.cpp:68
graphene::chain::vesting_balance_object
Definition: vesting_balance_object.hpp:151
graphene::chain::database::head_block_id
block_id_type head_block_id() const
Definition: db_getter.cpp:77
graphene::chain::account_statistics_object
Definition: account_object.hpp:46
graphene::db::generic_index::indices
const index_type & indices() const
Definition: generic_index.hpp:115
fc::optional::valid
bool valid() const
Definition: optional.hpp:186
graphene::chain::asset_dynamic_data_object
tracks the asset information that changes frequently
Definition: asset_object.hpp:56
graphene::db::object_database::get_object
const object & get_object(const object_id_type &id) const
Definition: object_database.cpp:47
account_object.hpp
fc::variant_object::size
size_t size() const
Definition: variant_object.cpp:93
htlc_object.hpp
fc::ripemd160
Definition: ripemd160.hpp:11
vesting_balance_object.hpp
graphene::chain::collateral_bid_object
bids of collateral for debt after a black swan
Definition: market_object.hpp:206
graphene::chain::debug_apply_update
void debug_apply_update(database &db, const fc::variant_object &vo)
Definition: db_debug.cpp:117
graphene::chain::database::debug_dump
void debug_dump()
Definition: db_debug.cpp:41
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
graphene::db::object_id_type
Definition: object_id.hpp:30
graphene::chain::force_settlement_object
tracks bitassets scheduled for force settlement at some point in the future.
Definition: market_object.hpp:187
graphene::chain::call_order_object
tracks debt and call price information
Definition: market_object.hpp:140
graphene::db::generic_index
Definition: generic_index.hpp:43
graphene::db::object_database::get_index
const index & get_index() const
Definition: object_database.hpp:83
graphene::chain::database::apply_debug_updates
void apply_debug_updates()
Definition: db_debug.cpp:187
graphene::chain::fba_accumulator_object
Definition: fba_object.hpp:37
fc::optional
provides stack-based nullable value similar to boost::optional
Definition: optional.hpp:20
fc::variant_object::end
iterator end() const
Definition: variant_object.cpp:59
market_object.hpp
fba_object.hpp
witness_object.hpp
graphene::chain::database::debug_update
void debug_update(const fc::variant_object &update)
Definition: db_debug.cpp:197
graphene::db::object_database::remove
void remove(const object &obj)
Definition: object_database.hpp:97
fc::safe::value
T value
Definition: safe.hpp:28
graphene::chain::limit_order_object
an offer to sell an amount of an asset at a specified exchange rate by a certain time
Definition: market_object.hpp:45
graphene
Definition: api.cpp:48
graphene::db::object_database::modify
void modify(const T &obj, const Lambda &m)
Definition: object_database.hpp:99
fc::safe
Definition: safe.hpp:26