Skip to content

Commit bac55a4

Browse files
authored
Merge branch 'develop' into pull1427_2
2 parents caf7f7f + d2bf27e commit bac55a4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1593
-893
lines changed

CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ LIST(APPEND BOOST_COMPONENTS thread
4848
system
4949
filesystem
5050
program_options
51-
signals
5251
serialization
5352
chrono
5453
unit_test_framework

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Visit [BitShares.org](https://bitshares.org/) to learn about BitShares and join
2222

2323
Information for developers can be found in the [Bitshares Developer Portal](https://dev.bitshares.works/). Users interested in how bitshares works can go to the [BitShares Documentation](https://how.bitshares.works/) site.
2424

25+
For security issues and bug bounty program please visit [Hack the DEX](https://hackthedex.io).
26+
2527
Getting Started
2628
---------------
2729
Build instructions and additional documentation are available in the

libraries/app/api.cpp

+11-10
Original file line numberDiff line numberDiff line change
@@ -159,18 +159,18 @@ namespace graphene { namespace app {
159159
}
160160
}
161161

162-
void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
162+
void network_broadcast_api::broadcast_transaction(const precomputable_transaction& trx)
163163
{
164-
trx.validate();
164+
_app.chain_database()->precompute_parallel( trx ).wait();
165165
_app.chain_database()->push_transaction(trx);
166166
if( _app.p2p_node() != nullptr )
167167
_app.p2p_node()->broadcast_transaction(trx);
168168
}
169169

170-
fc::variant network_broadcast_api::broadcast_transaction_synchronous(const signed_transaction& trx)
170+
fc::variant network_broadcast_api::broadcast_transaction_synchronous(const precomputable_transaction& trx)
171171
{
172172
fc::promise<fc::variant>::ptr prom( new fc::promise<fc::variant>() );
173-
broadcast_transaction_with_callback( [=]( const fc::variant& v ){
173+
broadcast_transaction_with_callback( [prom]( const fc::variant& v ){
174174
prom->set_value(v);
175175
}, trx );
176176

@@ -179,14 +179,15 @@ namespace graphene { namespace app {
179179

180180
void network_broadcast_api::broadcast_block( const signed_block& b )
181181
{
182+
_app.chain_database()->precompute_parallel( b ).wait();
182183
_app.chain_database()->push_block(b);
183184
if( _app.p2p_node() != nullptr )
184185
_app.p2p_node()->broadcast( net::block_message( b ));
185186
}
186187

187-
void network_broadcast_api::broadcast_transaction_with_callback(confirmation_callback cb, const signed_transaction& trx)
188+
void network_broadcast_api::broadcast_transaction_with_callback(confirmation_callback cb, const precomputable_transaction& trx)
188189
{
189-
trx.validate();
190+
_app.chain_database()->precompute_parallel( trx ).wait();
190191
_callbacks[trx.id()] = cb;
191192
_app.chain_database()->push_transaction(trx);
192193
if( _app.p2p_node() != nullptr )
@@ -369,15 +370,15 @@ namespace graphene { namespace app {
369370

370371
if(node->operation_id(db).op.which() == operation_id)
371372
result.push_back( node->operation_id(db) );
372-
}
373+
}
373374
if( node->next == account_transaction_history_id_type() )
374375
node = nullptr;
375376
else node = &node->next(db);
376377
}
377378
if( stop.instance.value == 0 && result.size() < limit ) {
378-
const account_transaction_history_object head = account_transaction_history_id_type()(db);
379-
if( head.account == account && head.operation_id(db).op.which() == operation_id )
380-
result.push_back(head.operation_id(db));
379+
auto head = db.find(account_transaction_history_id_type());
380+
if (head != nullptr && head->account == account && head->operation_id(db).op.which() == operation_id)
381+
result.push_back(head->operation_id(db));
381382
}
382383
return result;
383384
}

libraries/app/application.cpp

+43-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <graphene/app/application.hpp>
2727
#include <graphene/app/plugin.hpp>
2828

29+
#include <graphene/chain/db_with.hpp>
2930
#include <graphene/chain/genesis_state.hpp>
3031
#include <graphene/chain/protocol/fee_schedule.hpp>
3132
#include <graphene/chain/protocol/types.hpp>
@@ -394,12 +395,34 @@ void application_impl::startup()
394395
_chain_db->enable_standby_votes_tracking( _options->at("enable-standby-votes-tracking").as<bool>() );
395396
}
396397

397-
if( _options->count("replay-blockchain") )
398+
if( _options->count("replay-blockchain") || _options->count("revalidate-blockchain") )
398399
_chain_db->wipe( _data_dir / "blockchain", false );
399400

400401
try
401402
{
402-
_chain_db->open( _data_dir / "blockchain", initial_state, GRAPHENE_CURRENT_DB_VERSION );
403+
// these flags are used in open() only, i. e. during replay
404+
uint32_t skip;
405+
if( _options->count("revalidate-blockchain") ) // see also handle_block()
406+
{
407+
if( !loaded_checkpoints.empty() )
408+
wlog( "Warning - revalidate will not validate before last checkpoint" );
409+
if( _options->count("force-validate") )
410+
skip = graphene::chain::database::skip_nothing;
411+
else
412+
skip = graphene::chain::database::skip_transaction_signatures;
413+
}
414+
else // no revalidate, skip most checks
415+
skip = graphene::chain::database::skip_witness_signature |
416+
graphene::chain::database::skip_block_size_check |
417+
graphene::chain::database::skip_merkle_check |
418+
graphene::chain::database::skip_transaction_signatures |
419+
graphene::chain::database::skip_transaction_dupe_check |
420+
graphene::chain::database::skip_tapos_check |
421+
graphene::chain::database::skip_witness_schedule_check;
422+
423+
graphene::chain::detail::with_skip_flags( *_chain_db, skip, [this,&initial_state] () {
424+
_chain_db->open( _data_dir / "blockchain", initial_state, GRAPHENE_CURRENT_DB_VERSION );
425+
});
403426
}
404427
catch( const fc::exception& e )
405428
{
@@ -517,13 +540,17 @@ bool application_impl::handle_block(const graphene::net::block_message& blk_msg,
517540
FC_ASSERT( (latency.count()/1000) > -5000, "Rejecting block with timestamp in the future" );
518541

519542
try {
520-
// TODO: in the case where this block is valid but on a fork that's too old for us to switch to,
521-
// you can help the network code out by throwing a block_older_than_undo_history exception.
522-
// when the net code sees that, it will stop trying to push blocks from that chain, but
523-
// leave that peer connected so that they can get sync blocks from us
524-
bool result = _chain_db->push_block( blk_msg.block,
525-
(_is_block_producer | _force_validate) ?
526-
database::skip_nothing : database::skip_transaction_signatures );
543+
const uint32_t skip = (_is_block_producer | _force_validate) ?
544+
database::skip_nothing : database::skip_transaction_signatures;
545+
bool result = valve.do_serial( [this,&blk_msg,skip] () {
546+
_chain_db->precompute_parallel( blk_msg.block, skip ).wait();
547+
}, [this,&blk_msg,skip] () {
548+
// TODO: in the case where this block is valid but on a fork that's too old for us to switch to,
549+
// you can help the network code out by throwing a block_older_than_undo_history exception.
550+
// when the net code sees that, it will stop trying to push blocks from that chain, but
551+
// leave that peer connected so that they can get sync blocks from us
552+
return _chain_db->push_block( blk_msg.block, skip );
553+
});
527554

528555
// the block was accepted, so we now know all of the transactions contained in the block
529556
if (!sync_mode)
@@ -573,6 +600,7 @@ void application_impl::handle_transaction(const graphene::net::trx_message& tran
573600
trx_count = 0;
574601
}
575602

603+
_chain_db->precompute_parallel( transaction_message.trx ).wait();
576604
_chain_db->push_transaction( transaction_message.trx );
577605
} FC_CAPTURE_AND_RETHROW( (transaction_message) ) }
578606

@@ -960,9 +988,10 @@ void application::set_program_options(boost::program_options::options_descriptio
960988
"Path to create a Genesis State at. If a well-formed JSON file exists at the path, it will be parsed and any "
961989
"missing fields in a Genesis State will be added, and any unknown fields will be removed. If no file or an "
962990
"invalid file is found, it will be replaced with an example Genesis State.")
963-
("replay-blockchain", "Rebuild object graph by replaying all blocks")
991+
("replay-blockchain", "Rebuild object graph by replaying all blocks without validation")
992+
("revalidate-blockchain", "Rebuild object graph by replaying all blocks with full validation")
964993
("resync-blockchain", "Delete all blocks and re-sync with network from scratch")
965-
("force-validate", "Force validation of all transactions")
994+
("force-validate", "Force validation of all transactions during normal operation")
966995
("genesis-timestamp", bpo::value<uint32_t>(),
967996
"Replace timestamp from genesis.json with current time plus this many seconds (experts only!)")
968997
;
@@ -1094,7 +1123,10 @@ void application::initialize_plugins( const boost::program_options::variables_ma
10941123
void application::startup_plugins()
10951124
{
10961125
for( auto& entry : my->_active_plugins )
1126+
{
10971127
entry.second->plugin_startup();
1128+
ilog( "Plugin ${name} started", ( "name", entry.second->plugin_name() ) );
1129+
}
10981130
return;
10991131
}
11001132

libraries/app/application_impl.hxx

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#pragma once
22

33
#include <fc/network/http/websocket.hpp>
4+
#include <fc/thread/parallel.hpp>
5+
46
#include <graphene/app/application.hpp>
57
#include <graphene/app/api_access.hpp>
68
#include <graphene/chain/genesis_state.hpp>
@@ -194,6 +196,8 @@ class application_impl : public net::node_delegate
194196
std::map<string, std::shared_ptr<abstract_plugin>> _available_plugins;
195197

196198
bool _is_finished_syncing = false;
199+
private:
200+
fc::serial_valve valve;
197201
};
198202

199203
}}} // namespace graphene namespace app namespace detail

libraries/app/database_api.cpp

+21-23
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,7 @@ dynamic_global_property_object database_api_impl::get_dynamic_global_properties(
539539

540540
vector<vector<account_id_type>> database_api::get_key_references( vector<public_key_type> key )const
541541
{
542+
FC_ASSERT(key.size() <= 100, "Number of keys must be 100 or less");
542543
return my->get_key_references( key );
543544
}
544545

@@ -547,6 +548,10 @@ vector<vector<account_id_type>> database_api::get_key_references( vector<public_
547548
*/
548549
vector<vector<account_id_type>> database_api_impl::get_key_references( vector<public_key_type> keys )const
549550
{
551+
const auto& idx = _db.get_index_type<account_index>();
552+
const auto& aidx = dynamic_cast<const base_primary_index&>(idx);
553+
const auto& refs = aidx.get_secondary_index<graphene::chain::account_member_index>();
554+
550555
vector< vector<account_id_type> > final_result;
551556
final_result.reserve(keys.size());
552557

@@ -566,36 +571,30 @@ vector<vector<account_id_type>> database_api_impl::get_key_references( vector<pu
566571
subscribe_to_item( a4 );
567572
subscribe_to_item( a5 );
568573

569-
const auto& idx = _db.get_index_type<account_index>();
570-
const auto& aidx = dynamic_cast<const primary_index<account_index>&>(idx);
571-
const auto& refs = aidx.get_secondary_index<graphene::chain::account_member_index>();
572-
auto itr = refs.account_to_key_memberships.find(key);
573574
vector<account_id_type> result;
574575

575576
for( auto& a : {a1,a2,a3,a4,a5} )
576577
{
577578
auto itr = refs.account_to_address_memberships.find(a);
578579
if( itr != refs.account_to_address_memberships.end() )
579580
{
580-
result.reserve( itr->second.size() );
581+
result.reserve( result.size() + itr->second.size() );
581582
for( auto item : itr->second )
582583
{
583584
result.push_back(item);
584585
}
585586
}
586587
}
587588

589+
auto itr = refs.account_to_key_memberships.find(key);
588590
if( itr != refs.account_to_key_memberships.end() )
589591
{
590-
result.reserve( itr->second.size() );
592+
result.reserve( result.size() + itr->second.size() );
591593
for( auto item : itr->second ) result.push_back(item);
592594
}
593595
final_result.emplace_back( std::move(result) );
594596
}
595597

596-
for( auto i : final_result )
597-
subscribe_to_item(i);
598-
599598
return final_result;
600599
}
601600

@@ -620,7 +619,7 @@ bool database_api_impl::is_public_key_registered(string public_key) const
620619
return false;
621620
}
622621
const auto& idx = _db.get_index_type<account_index>();
623-
const auto& aidx = dynamic_cast<const primary_index<account_index>&>(idx);
622+
const auto& aidx = dynamic_cast<const base_primary_index&>(idx);
624623
const auto& refs = aidx.get_secondary_index<graphene::chain::account_member_index>();
625624
auto itr = refs.account_to_key_memberships.find(key);
626625
bool is_known = itr != refs.account_to_key_memberships.end();
@@ -755,6 +754,10 @@ std::map<string,full_account> database_api::get_full_accounts( const vector<stri
755754

756755
std::map<std::string, full_account> database_api_impl::get_full_accounts( const vector<std::string>& names_or_ids, bool subscribe)
757756
{
757+
const auto& proposal_idx = _db.get_index_type<proposal_index>();
758+
const auto& pidx = dynamic_cast<const base_primary_index&>(proposal_idx);
759+
const auto& proposals_by_account = pidx.get_secondary_index<graphene::chain::required_approval_index>();
760+
758761
std::map<std::string, full_account> results;
759762

760763
for (const std::string& account_name_or_id : names_or_ids)
@@ -784,9 +787,6 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
784787
acnt.cashback_balance = account->cashback_balance(_db);
785788
}
786789
// Add the account's proposals
787-
const auto& proposal_idx = _db.get_index_type<proposal_index>();
788-
const auto& pidx = dynamic_cast<const primary_index<proposal_index>&>(proposal_idx);
789-
const auto& proposals_by_account = pidx.get_secondary_index<graphene::chain::required_approval_index>();
790790
auto required_approvals_itr = proposals_by_account._account_to_proposals.find( account->id );
791791
if( required_approvals_itr != proposals_by_account._account_to_proposals.end() )
792792
{
@@ -797,11 +797,9 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
797797

798798

799799
// Add the account's balances
800-
auto balance_range = _db.get_index_type<account_balance_index>().indices().get<by_account_asset>().equal_range(boost::make_tuple(account->id));
801-
std::for_each(balance_range.first, balance_range.second,
802-
[&acnt](const account_balance_object& balance) {
803-
acnt.balances.emplace_back(balance);
804-
});
800+
const auto& balances = _db.get_index_type< primary_index< account_balance_index > >().get_secondary_index< balances_by_account_index >().get_account_balances( account->id );
801+
for( const auto balance : balances )
802+
acnt.balances.emplace_back( *balance.second );
805803

806804
// Add the account's vesting balances
807805
auto vesting_range = _db.get_index_type<vesting_balance_index>().indices().get<by_account>().equal_range(account->id);
@@ -869,7 +867,7 @@ vector<account_id_type> database_api::get_account_references( const std::string
869867
vector<account_id_type> database_api_impl::get_account_references( const std::string account_id_or_name )const
870868
{
871869
const auto& idx = _db.get_index_type<account_index>();
872-
const auto& aidx = dynamic_cast<const primary_index<account_index>&>(idx);
870+
const auto& aidx = dynamic_cast<const base_primary_index&>(idx);
873871
const auto& refs = aidx.get_secondary_index<graphene::chain::account_member_index>();
874872
const account_id_type account_id = get_account_from_string(account_id_or_name)->id;
875873
auto itr = refs.account_to_account_memberships.find(account_id);
@@ -953,10 +951,10 @@ vector<asset> database_api_impl::get_account_balances(const std::string& account
953951
if (assets.empty())
954952
{
955953
// if the caller passes in an empty list of assets, return balances for all assets the account owns
956-
const account_balance_index& balance_index = _db.get_index_type<account_balance_index>();
957-
auto range = balance_index.indices().get<by_account_asset>().equal_range(boost::make_tuple(acnt));
958-
for (const account_balance_object& balance : boost::make_iterator_range(range.first, range.second))
959-
result.push_back(asset(balance.get_balance()));
954+
const auto& balance_index = _db.get_index_type< primary_index< account_balance_index > >();
955+
const auto& balances = balance_index.get_secondary_index< balances_by_account_index >().get_account_balances( acnt );
956+
for( const auto balance : balances )
957+
result.push_back( balance.second->get_balance() );
960958
}
961959
else
962960
{

libraries/app/include/graphene/app/api.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -266,19 +266,19 @@ namespace graphene { namespace app {
266266
* The transaction will be checked for validity in the local database prior to broadcasting. If it fails to
267267
* apply locally, an error will be thrown and the transaction will not be broadcast.
268268
*/
269-
void broadcast_transaction(const signed_transaction& trx);
269+
void broadcast_transaction(const precomputable_transaction& trx);
270270

271271
/** this version of broadcast transaction registers a callback method that will be called when the transaction is
272272
* included into a block. The callback method includes the transaction id, block number, and transaction number in the
273273
* block.
274274
*/
275-
void broadcast_transaction_with_callback( confirmation_callback cb, const signed_transaction& trx);
275+
void broadcast_transaction_with_callback( confirmation_callback cb, const precomputable_transaction& trx);
276276

277277
/** this version of broadcast transaction registers a callback method that will be called when the transaction is
278278
* included into a block. The callback method includes the transaction id, block number, and transaction number in the
279279
* block.
280280
*/
281-
fc::variant broadcast_transaction_synchronous(const signed_transaction& trx);
281+
fc::variant broadcast_transaction_synchronous(const precomputable_transaction& trx);
282282

283283
/**
284284
* @brief Broadcast a signed block to the network

libraries/chain/account_evaluator.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ void verify_account_votes( const database& db, const account_options& options )
119119
}
120120
}
121121

122-
123122
void_result account_create_evaluator::do_evaluate( const account_create_operation& op )
124123
{ try {
125124
database& d = db();
@@ -318,11 +317,16 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
318317
bool sa_before = acnt->has_special_authority();
319318

320319
// update account statistics
321-
if( o.new_options.valid() && o.new_options->is_voting() != acnt->options.is_voting() )
320+
if( o.new_options.valid() )
322321
{
323-
d.modify( acnt->statistics( d ), []( account_statistics_object& aso )
322+
d.modify( acnt->statistics( d ), [&]( account_statistics_object& aso )
324323
{
325-
aso.is_voting = !aso.is_voting;
324+
if(o.new_options->is_voting() != acnt->options.is_voting())
325+
aso.is_voting = !aso.is_voting;
326+
327+
if((o.new_options->votes != acnt->options.votes ||
328+
o.new_options->voting_account != acnt->options.voting_account))
329+
aso.last_vote_time = d.head_block_time();
326330
} );
327331
}
328332

0 commit comments

Comments
 (0)