Merge pull request #714 from pmconrad/json_fix

JSON fix
This commit is contained in:
Abit 2018-03-19 23:23:59 +01:00 committed by Miha Čančula
parent b787d62d06
commit a49f8bf47c
No known key found for this signature in database
GPG key ID: 4FC9D4BD4FBAB9B9
44 changed files with 576 additions and 256 deletions

View file

@ -160,7 +160,7 @@ namespace graphene { namespace app {
{ {
auto block_num = b.block_num(); auto block_num = b.block_num();
auto& callback = _callbacks.find(id)->second; auto& callback = _callbacks.find(id)->second;
fc::async( [capture_this,this,id,block_num,trx_num,trx,callback](){ callback( fc::variant(transaction_confirmation{ id, block_num, trx_num, trx}) ); } ); fc::async( [capture_this,this,id,block_num,trx_num,trx,callback](){ callback( fc::variant(transaction_confirmation{ id, block_num, trx_num, trx}, 5) ); } );
} }
} }
} }

View file

@ -142,7 +142,7 @@ namespace detail {
if( _options->count("seed-nodes") ) if( _options->count("seed-nodes") )
{ {
auto seeds_str = _options->at("seed-nodes").as<string>(); auto seeds_str = _options->at("seed-nodes").as<string>();
auto seeds = fc::json::from_string(seeds_str).as<vector<string>>(); auto seeds = fc::json::from_string(seeds_str).as<vector<string>>(2);
for( const string& endpoint_string : seeds ) for( const string& endpoint_string : seeds )
{ {
try { try {
@ -226,7 +226,7 @@ namespace detail {
void new_connection( const fc::http::websocket_connection_ptr& c ) void new_connection( const fc::http::websocket_connection_ptr& c )
{ {
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(*c); auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(*c, GRAPHENE_NET_MAX_NESTED_OBJECTS);
auto login = std::make_shared<graphene::app::login_api>( std::ref(*_self) ); auto login = std::make_shared<graphene::app::login_api>( std::ref(*_self) );
login->enable_api("database_api"); login->enable_api("database_api");
@ -292,7 +292,7 @@ namespace detail {
_websocket_tls_server->start_accept(); _websocket_tls_server->start_accept();
} FC_CAPTURE_AND_RETHROW() } } FC_CAPTURE_AND_RETHROW() }
application_impl(application* self) explicit application_impl(application* self)
: _self(self), : _self(self),
_chain_db(std::make_shared<chain::database>()) _chain_db(std::make_shared<chain::database>())
{ {
@ -309,7 +309,6 @@ namespace detail {
public_key_type init_pubkey( init_key ); public_key_type init_pubkey( init_key );
for( uint64_t i=0; i<genesis.initial_active_witnesses; i++ ) for( uint64_t i=0; i<genesis.initial_active_witnesses; i++ )
genesis.initial_witness_candidates[i].block_signing_key = init_pubkey; genesis.initial_witness_candidates[i].block_signing_key = init_pubkey;
return;
} }
void startup() void startup()
@ -317,13 +316,13 @@ namespace detail {
bool clean = !fc::exists(_data_dir / "blockchain/dblock"); bool clean = !fc::exists(_data_dir / "blockchain/dblock");
fc::create_directories(_data_dir / "blockchain/dblock"); fc::create_directories(_data_dir / "blockchain/dblock");
auto initial_state = [&] { auto initial_state = [this] {
ilog("Initializing database..."); ilog("Initializing database...");
if( _options->count("genesis-json") ) if( _options->count("genesis-json") )
{ {
std::string genesis_str; std::string genesis_str;
fc::read_file_contents( _options->at("genesis-json").as<boost::filesystem::path>(), genesis_str ); fc::read_file_contents( _options->at("genesis-json").as<boost::filesystem::path>(), genesis_str );
genesis_state_type genesis = fc::json::from_string( genesis_str ).as<genesis_state_type>(); genesis_state_type genesis = fc::json::from_string( genesis_str ).as<genesis_state_type>( 20 );
bool modified_genesis = false; bool modified_genesis = false;
if( _options->count("genesis-timestamp") ) if( _options->count("genesis-timestamp") )
{ {
@ -356,7 +355,7 @@ namespace detail {
graphene::egenesis::compute_egenesis_json( egenesis_json ); graphene::egenesis::compute_egenesis_json( egenesis_json );
FC_ASSERT( egenesis_json != "" ); FC_ASSERT( egenesis_json != "" );
FC_ASSERT( graphene::egenesis::get_egenesis_json_hash() == fc::sha256::hash( egenesis_json ) ); FC_ASSERT( graphene::egenesis::get_egenesis_json_hash() == fc::sha256::hash( egenesis_json ) );
auto genesis = fc::json::from_string( egenesis_json ).as<genesis_state_type>(); auto genesis = fc::json::from_string( egenesis_json ).as<genesis_state_type>( 20 );
genesis.initial_chain_id = fc::sha256::hash( egenesis_json ); genesis.initial_chain_id = fc::sha256::hash( egenesis_json );
return genesis; return genesis;
} }
@ -372,7 +371,7 @@ namespace detail {
loaded_checkpoints.reserve( cps.size() ); loaded_checkpoints.reserve( cps.size() );
for( auto cp : cps ) for( auto cp : cps )
{ {
auto item = fc::json::from_string(cp).as<std::pair<uint32_t,block_id_type> >(); auto item = fc::json::from_string(cp).as<std::pair<uint32_t,block_id_type> >( 2 );
loaded_checkpoints[item.first] = item.second; loaded_checkpoints[item.first] = item.second;
} }
} }
@ -447,9 +446,21 @@ namespace detail {
_force_validate = true; _force_validate = true;
} }
if( _options->count("api-access") ) if( _options->count("api-access") ) {
_apiaccess = fc::json::from_file( _options->at("api-access").as<boost::filesystem::path>() )
.as<api_access>(); if(fc::exists(_options->at("api-access").as<boost::filesystem::path>()))
{
_apiaccess = fc::json::from_file( _options->at("api-access").as<boost::filesystem::path>() ).as<api_access>( 20 );
ilog( "Using api access file from ${path}",
("path", _options->at("api-access").as<boost::filesystem::path>().string()) );
}
else
{
elog("Failed to load file from ${path}",
("path", _options->at("api-access").as<boost::filesystem::path>().string()));
std::exit(EXIT_FAILURE);
}
}
else else
{ {
// TODO: Remove this generous default access policy // TODO: Remove this generous default access policy
@ -991,7 +1002,7 @@ void application::initialize(const fc::path& data_dir, const boost::program_opti
if( fc::exists(genesis_out) ) if( fc::exists(genesis_out) )
{ {
try { try {
genesis_state = fc::json::from_file(genesis_out).as<genesis_state_type>(); genesis_state = fc::json::from_file(genesis_out).as<genesis_state_type>( 20 );
} catch(const fc::exception& e) { } catch(const fc::exception& e) {
std::cerr << "Unable to parse existing genesis file:\n" << e.to_string() std::cerr << "Unable to parse existing genesis file:\n" << e.to_string()
<< "\nWould you like to replace it? [y/N] "; << "\nWould you like to replace it? [y/N] ";

View file

@ -47,9 +47,6 @@ typedef std::map< std::pair<graphene::chain::asset_id_type, graphene::chain::ass
namespace graphene { namespace app { namespace graphene { namespace app {
class database_api_impl;
class database_api_impl : public std::enable_shared_from_this<database_api_impl> class database_api_impl : public std::enable_shared_from_this<database_api_impl>
{ {
public: public:
@ -217,7 +214,7 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
auto sub = _market_subscriptions.find( market ); auto sub = _market_subscriptions.find( market );
if( sub != _market_subscriptions.end() ) { if( sub != _market_subscriptions.end() ) {
queue[market].emplace_back( full_object ? obj->to_variant() : fc::variant(obj->id) ); queue[market].emplace_back( full_object ? obj->to_variant() : fc::variant(obj->id, 1) );
} }
} }
@ -273,7 +270,7 @@ database_api_impl::database_api_impl( graphene::chain::database& db ):_db(db)
_applied_block_connection = _db.applied_block.connect([this](const signed_block&){ on_applied_block(); }); _applied_block_connection = _db.applied_block.connect([this](const signed_block&){ on_applied_block(); });
_pending_trx_connection = _db.on_pending_transaction.connect([this](const signed_transaction& trx ){ _pending_trx_connection = _db.on_pending_transaction.connect([this](const signed_transaction& trx ){
if( _pending_trx_callback ) _pending_trx_callback( fc::variant(trx) ); if( _pending_trx_callback ) _pending_trx_callback( fc::variant(trx, GRAPHENE_MAX_NESTED_OBJECTS) );
}); });
} }
@ -645,7 +642,7 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
{ {
const account_object* account = nullptr; const account_object* account = nullptr;
if (std::isdigit(account_name_or_id[0])) if (std::isdigit(account_name_or_id[0]))
account = _db.find(fc::variant(account_name_or_id).as<account_id_type>()); account = _db.find(fc::variant(account_name_or_id, 1).as<account_id_type>(1));
else else
{ {
const auto& idx = _db.get_index_type<account_index>().indices().get<by_name>(); const auto& idx = _db.get_index_type<account_index>().indices().get<by_name>();
@ -663,7 +660,6 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
subscribe_to_item( account->id ); subscribe_to_item( account->id );
} }
// fc::mutable_variant_object full_account;
full_account acnt; full_account acnt;
acnt.account = *account; acnt.account = *account;
acnt.statistics = account->statistics(_db); acnt.statistics = account->statistics(_db);
@ -672,12 +668,6 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
acnt.lifetime_referrer_name = account->lifetime_referrer(_db).name; acnt.lifetime_referrer_name = account->lifetime_referrer(_db).name;
acnt.votes = lookup_vote_ids( vector<vote_id_type>(account->options.votes.begin(),account->options.votes.end()) ); acnt.votes = lookup_vote_ids( vector<vote_id_type>(account->options.votes.begin(),account->options.votes.end()) );
// Add the account itself, its statistics object, cashback balance, and referral account names
/*
full_account("account", *account)("statistics", account->statistics(_db))
("registrar_name", account->registrar(_db).name)("referrer_name", account->referrer(_db).name)
("lifetime_referrer_name", account->lifetime_referrer(_db).name);
*/
if (account->cashback_vb) if (account->cashback_vb)
{ {
acnt.cashback_balance = account->cashback_balance(_db); acnt.cashback_balance = account->cashback_balance(_db);
@ -697,7 +687,6 @@ std::map<std::string, full_account> database_api_impl::get_full_accounts( const
// Add the account's balances // Add the account's balances
auto balance_range = _db.get_index_type<account_balance_index>().indices().get<by_account_asset>().equal_range(boost::make_tuple(account->id)); auto balance_range = _db.get_index_type<account_balance_index>().indices().get<by_account_asset>().equal_range(boost::make_tuple(account->id));
//vector<account_balance_object> balances;
std::for_each(balance_range.first, balance_range.second, std::for_each(balance_range.first, balance_range.second,
[&acnt](const account_balance_object& balance) { [&acnt](const account_balance_object& balance) {
acnt.balances.emplace_back(balance); acnt.balances.emplace_back(balance);
@ -1013,7 +1002,7 @@ vector<optional<asset_object>> database_api_impl::lookup_asset_symbols(const vec
[this, &assets_by_symbol](const string& symbol_or_id) -> optional<asset_object> { [this, &assets_by_symbol](const string& symbol_or_id) -> optional<asset_object> {
if( !symbol_or_id.empty() && std::isdigit(symbol_or_id[0]) ) if( !symbol_or_id.empty() && std::isdigit(symbol_or_id[0]) )
{ {
auto ptr = _db.find(variant(symbol_or_id).as<asset_id_type>()); auto ptr = _db.find(variant(symbol_or_id, 1).as<asset_id_type>(1));
return ptr == nullptr? optional<asset_object>() : *ptr; return ptr == nullptr? optional<asset_object>() : *ptr;
} }
auto itr = assets_by_symbol.find(symbol_or_id); auto itr = assets_by_symbol.find(symbol_or_id);
@ -1712,7 +1701,7 @@ vector<variant> database_api_impl::lookup_vote_ids( const vector<vote_id_type>&
{ {
auto itr = committee_idx.find( id ); auto itr = committee_idx.find( id );
if( itr != committee_idx.end() ) if( itr != committee_idx.end() )
result.emplace_back( variant( *itr ) ); result.emplace_back( variant( *itr, 1 ) );
else else
result.emplace_back( variant() ); result.emplace_back( variant() );
break; break;
@ -1721,7 +1710,7 @@ vector<variant> database_api_impl::lookup_vote_ids( const vector<vote_id_type>&
{ {
auto itr = witness_idx.find( id ); auto itr = witness_idx.find( id );
if( itr != witness_idx.end() ) if( itr != witness_idx.end() )
result.emplace_back( variant( *itr ) ); result.emplace_back( variant( *itr, 1 ) );
else else
result.emplace_back( variant() ); result.emplace_back( variant() );
break; break;
@ -1730,12 +1719,12 @@ vector<variant> database_api_impl::lookup_vote_ids( const vector<vote_id_type>&
{ {
auto itr = for_worker_idx.find( id ); auto itr = for_worker_idx.find( id );
if( itr != for_worker_idx.end() ) { if( itr != for_worker_idx.end() ) {
result.emplace_back( variant( *itr ) ); result.emplace_back( variant( *itr, 1 ) );
} }
else { else {
auto itr = against_worker_idx.find( id ); auto itr = against_worker_idx.find( id );
if( itr != against_worker_idx.end() ) { if( itr != against_worker_idx.end() ) {
result.emplace_back( variant( *itr ) ); result.emplace_back( variant( *itr, 1 ) );
} }
else { else {
result.emplace_back( variant() ); result.emplace_back( variant() );
@ -1744,6 +1733,8 @@ vector<variant> database_api_impl::lookup_vote_ids( const vector<vote_id_type>&
break; break;
} }
case vote_id_type::VOTE_TYPE_COUNT: break; // supress unused enum value warnings case vote_id_type::VOTE_TYPE_COUNT: break; // supress unused enum value warnings
default:
FC_CAPTURE_AND_THROW( fc::out_of_range_exception, (id) );
} }
} }
return result; return result;
@ -1852,8 +1843,8 @@ bool database_api::verify_authority( const signed_transaction& trx )const
bool database_api_impl::verify_authority( const signed_transaction& trx )const bool database_api_impl::verify_authority( const signed_transaction& trx )const
{ {
trx.verify_authority( _db.get_chain_id(), trx.verify_authority( _db.get_chain_id(),
[&]( account_id_type id ){ return &id(_db).active; }, [this]( account_id_type id ){ return &id(_db).active; },
[&]( account_id_type id ){ return &id(_db).owner; }, [this]( account_id_type id ){ return &id(_db).owner; },
_db.get_global_properties().parameters.max_authority_depth ); _db.get_global_properties().parameters.max_authority_depth );
return true; return true;
} }
@ -1868,7 +1859,7 @@ bool database_api_impl::verify_account_authority( const string& name_or_id, cons
FC_ASSERT( name_or_id.size() > 0); FC_ASSERT( name_or_id.size() > 0);
const account_object* account = nullptr; const account_object* account = nullptr;
if (std::isdigit(name_or_id[0])) if (std::isdigit(name_or_id[0]))
account = _db.find(fc::variant(name_or_id).as<account_id_type>()); account = _db.find(fc::variant(name_or_id, 1).as<account_id_type>(1));
else else
{ {
const auto& idx = _db.get_index_type<account_index>().indices().get<by_name>(); const auto& idx = _db.get_index_type<account_index>().indices().get<by_name>();
@ -1929,7 +1920,7 @@ struct get_required_fees_helper
{ {
asset fee = current_fee_schedule.set_fee( op, core_exchange_rate ); asset fee = current_fee_schedule.set_fee( op, core_exchange_rate );
fc::variant result; fc::variant result;
fc::to_variant( fee, result ); fc::to_variant( fee, result, GRAPHENE_NET_MAX_NESTED_OBJECTS );
return result; return result;
} }
} }
@ -1949,7 +1940,7 @@ struct get_required_fees_helper
// two mutually recursive functions instead of a visitor // two mutually recursive functions instead of a visitor
result.first = current_fee_schedule.set_fee( proposal_create_op, core_exchange_rate ); result.first = current_fee_schedule.set_fee( proposal_create_op, core_exchange_rate );
fc::variant vresult; fc::variant vresult;
fc::to_variant( result, vresult ); fc::to_variant( result, vresult, GRAPHENE_NET_MAX_NESTED_OBJECTS );
return vresult; return vresult;
} }
@ -2211,7 +2202,7 @@ void database_api_impl::handle_object_changed(bool force_notify, bool full_objec
} }
else else
{ {
updates.emplace_back( id ); updates.emplace_back( fc::variant( id, 1 ) );
} }
} }
} }
@ -2255,7 +2246,7 @@ void database_api_impl::on_applied_block()
auto capture_this = shared_from_this(); auto capture_this = shared_from_this();
block_id_type block_id = _db.head_block_id(); block_id_type block_id = _db.head_block_id();
fc::async([this,capture_this,block_id](){ fc::async([this,capture_this,block_id](){
_block_applied_callback(fc::variant(block_id)); _block_applied_callback(fc::variant(block_id, 1));
}); });
} }
@ -2296,7 +2287,7 @@ void database_api_impl::on_applied_block()
{ {
auto itr = _market_subscriptions.find(item.first); auto itr = _market_subscriptions.find(item.first);
if(itr != _market_subscriptions.end()) if(itr != _market_subscriptions.end())
itr->second(fc::variant(item.second)); itr->second(fc::variant(item.second, GRAPHENE_NET_MAX_NESTED_OBJECTS));
} }
}); });
} }

View file

@ -121,16 +121,24 @@ class plugin : public abstract_plugin
/// @group Some useful tools for boost::program_options arguments using vectors of JSON strings /// @group Some useful tools for boost::program_options arguments using vectors of JSON strings
/// @{ /// @{
template<typename T> template<typename T>
T dejsonify(const string& s) T dejsonify(const string& s, uint32_t max_depth)
{ {
return fc::json::from_string(s).as<T>(); return fc::json::from_string(s).as<T>(max_depth);
}
namespace impl {
template<typename T>
T dejsonify( const string& s )
{
return graphene::app::dejsonify<T>( s, GRAPHENE_MAX_NESTED_OBJECTS );
}
} }
#define DEFAULT_VALUE_VECTOR(value) default_value({fc::json::to_string(value)}, fc::json::to_string(value)) #define DEFAULT_VALUE_VECTOR(value) default_value({fc::json::to_string(value)}, fc::json::to_string(value))
#define LOAD_VALUE_SET(options, name, container, type) \ #define LOAD_VALUE_SET(options, name, container, type) \
if( options.count(name) ) { \ if( options.count(name) ) { \
const std::vector<std::string>& ops = options[name].as<std::vector<std::string>>(); \ const std::vector<std::string>& ops = options[name].as<std::vector<std::string>>(); \
std::transform(ops.begin(), ops.end(), std::inserter(container, container.end()), &graphene::app::dejsonify<type>); \ std::transform(ops.begin(), ops.end(), std::inserter(container, container.end()), &graphene::app::impl::dejsonify<type>); \
} }
/// @} /// @}

View file

@ -143,25 +143,19 @@ void debug_apply_update( database& db, const fc::variant_object& vo )
switch( action ) switch( action )
{ {
case db_action_create: case db_action_create:
/*
idx.create( [&]( object& obj )
{
idx.object_from_variant( vo, obj );
} );
*/
FC_ASSERT( false ); FC_ASSERT( false );
break; break;
case db_action_write: case db_action_write:
db.modify( db.get_object( oid ), [&]( object& obj ) db.modify( db.get_object( oid ), [&]( object& obj )
{ {
idx.object_default( obj ); idx.object_default( obj );
idx.object_from_variant( vo, obj ); idx.object_from_variant( vo, obj, GRAPHENE_MAX_NESTED_OBJECTS );
} ); } );
break; break;
case db_action_update: case db_action_update:
db.modify( db.get_object( oid ), [&]( object& obj ) db.modify( db.get_object( oid ), [&]( object& obj )
{ {
idx.object_from_variant( vo, obj ); idx.object_from_variant( vo, obj, GRAPHENE_MAX_NESTED_OBJECTS );
} ); } );
break; break;
case db_action_delete: case db_action_delete:

View file

@ -103,11 +103,11 @@ fc::variant_object get_config()
result[ "GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS" ] = GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS; result[ "GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS" ] = GRAPHENE_DEFAULT_WITNESS_PAY_VESTING_SECONDS;
result[ "GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY" ] = GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY; result[ "GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY" ] = GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY;
result[ "GRAPHENE_MAX_INTEREST_APR" ] = GRAPHENE_MAX_INTEREST_APR; result[ "GRAPHENE_MAX_INTEREST_APR" ] = GRAPHENE_MAX_INTEREST_APR;
result[ "GRAPHENE_COMMITTEE_ACCOUNT" ] = GRAPHENE_COMMITTEE_ACCOUNT; result[ "GRAPHENE_COMMITTEE_ACCOUNT" ] = fc::variant(GRAPHENE_COMMITTEE_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_WITNESS_ACCOUNT" ] = GRAPHENE_WITNESS_ACCOUNT; result[ "GRAPHENE_WITNESS_ACCOUNT" ] = fc::variant(GRAPHENE_WITNESS_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_RELAXED_COMMITTEE_ACCOUNT" ] = GRAPHENE_RELAXED_COMMITTEE_ACCOUNT; result[ "GRAPHENE_RELAXED_COMMITTEE_ACCOUNT" ] = fc::variant(GRAPHENE_RELAXED_COMMITTEE_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_NULL_ACCOUNT" ] = GRAPHENE_NULL_ACCOUNT; result[ "GRAPHENE_NULL_ACCOUNT" ] = fc::variant(GRAPHENE_NULL_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
result[ "GRAPHENE_TEMP_ACCOUNT" ] = GRAPHENE_TEMP_ACCOUNT; result[ "GRAPHENE_TEMP_ACCOUNT" ] = fc::variant(GRAPHENE_TEMP_ACCOUNT, GRAPHENE_MAX_NESTED_OBJECTS);
return result; return result;
} }

View file

@ -211,6 +211,7 @@
{ 10000000, 100000} } /* <= 1000: 10.00 */ { 10000000, 100000} } /* <= 1000: 10.00 */
#define GRAPHENE_DEFAULT_BETTING_PERCENT_FEE (2 * GRAPHENE_1_PERCENT) #define GRAPHENE_DEFAULT_BETTING_PERCENT_FEE (2 * GRAPHENE_1_PERCENT)
#define GRAPHENE_DEFAULT_LIVE_BETTING_DELAY_TIME 5 // seconds #define GRAPHENE_DEFAULT_LIVE_BETTING_DELAY_TIME 5 // seconds
#define GRAPHENE_MAX_NESTED_OBJECTS (200)
#define TOURNAMENT_MIN_ROUND_DELAY 0 #define TOURNAMENT_MIN_ROUND_DELAY 0
#define TOURNAMENT_MAX_ROUND_DELAY 600 #define TOURNAMENT_MAX_ROUND_DELAY 600
#define TOURNAMENT_MIN_TIME_PER_COMMIT_MOVE 0 #define TOURNAMENT_MIN_TIME_PER_COMMIT_MOVE 0

View file

@ -78,8 +78,8 @@ namespace graphene { namespace chain {
namespace fc namespace fc
{ {
void to_variant( const graphene::chain::address& var, fc::variant& vo ); void to_variant( const graphene::chain::address& var, fc::variant& vo, uint32_t max_depth = 1 );
void from_variant( const fc::variant& var, graphene::chain::address& vo ); void from_variant( const fc::variant& var, graphene::chain::address& vo, uint32_t max_depth = 1 );
} }
namespace std namespace std

View file

@ -145,9 +145,10 @@ namespace fc {
template< typename T > template< typename T >
struct graphene_extension_from_variant_visitor struct graphene_extension_from_variant_visitor
{ {
graphene_extension_from_variant_visitor( const variant_object& v, T& val ) graphene_extension_from_variant_visitor( const variant_object& v, T& val, uint32_t max_depth )
: vo( v ), value( val ) : vo( v ), value( val ), _max_depth(max_depth - 1)
{ {
FC_ASSERT( max_depth > 0, "Recursion depth exceeded!" );
count_left = vo.size(); count_left = vo.size();
} }
@ -157,7 +158,7 @@ struct graphene_extension_from_variant_visitor
auto it = vo.find(name); auto it = vo.find(name);
if( it != vo.end() ) if( it != vo.end() )
{ {
from_variant( it->value(), (value.*member) ); from_variant( it->value(), (value.*member), _max_depth );
assert( count_left > 0 ); // x.find(k) returns true for n distinct values of k only if x.size() >= n assert( count_left > 0 ); // x.find(k) returns true for n distinct values of k only if x.size() >= n
--count_left; --count_left;
} }
@ -165,11 +166,12 @@ struct graphene_extension_from_variant_visitor
const variant_object& vo; const variant_object& vo;
T& value; T& value;
const uint32_t _max_depth;
mutable uint32_t count_left = 0; mutable uint32_t count_left = 0;
}; };
template< typename T > template< typename T >
void from_variant( const fc::variant& var, graphene::chain::extension<T>& value ) void from_variant( const fc::variant& var, graphene::chain::extension<T>& value, uint32_t max_depth )
{ {
value = graphene::chain::extension<T>(); value = graphene::chain::extension<T>();
if( var.is_null() ) if( var.is_null() )
@ -180,7 +182,7 @@ void from_variant( const fc::variant& var, graphene::chain::extension<T>& value
return; return;
} }
graphene_extension_from_variant_visitor<T> vtor( var.get_object(), value.value ); graphene_extension_from_variant_visitor<T> vtor( var.get_object(), value.value, max_depth );
fc::reflector<T>::visit( vtor ); fc::reflector<T>::visit( vtor );
FC_ASSERT( vtor.count_left == 0 ); // unrecognized extension throws here FC_ASSERT( vtor.count_left == 0 ); // unrecognized extension throws here
} }
@ -188,23 +190,23 @@ void from_variant( const fc::variant& var, graphene::chain::extension<T>& value
template< typename T > template< typename T >
struct graphene_extension_to_variant_visitor struct graphene_extension_to_variant_visitor
{ {
graphene_extension_to_variant_visitor( const T& v ) : value(v) {} graphene_extension_to_variant_visitor( const T& v, uint32_t max_depth ) : value(v), mvo(max_depth) {}
template<typename Member, class Class, Member (Class::*member)> template<typename Member, class Class, Member (Class::*member)>
void operator()( const char* name )const void operator()( const char* name )const
{ {
if( (value.*member).valid() ) if( (value.*member).valid() )
mvo[ name ] = (value.*member); mvo( name, value.*member );
} }
const T& value; const T& value;
mutable mutable_variant_object mvo; mutable limited_mutable_variant_object mvo;
}; };
template< typename T > template< typename T >
void to_variant( const graphene::chain::extension<T>& value, fc::variant& var ) void to_variant( const graphene::chain::extension<T>& value, fc::variant& var, uint32_t max_depth )
{ {
graphene_extension_to_variant_visitor<T> vtor( value.value ); graphene_extension_to_variant_visitor<T> vtor( value.value, max_depth );
fc::reflector<T>::visit( vtor ); fc::reflector<T>::visit( vtor );
var = vtor.mvo; var = vtor.mvo;
} }

View file

@ -367,12 +367,12 @@ namespace graphene { namespace chain {
namespace fc namespace fc
{ {
void to_variant( const graphene::chain::public_key_type& var, fc::variant& vo ); void to_variant( const graphene::chain::public_key_type& var, fc::variant& vo, uint32_t max_depth = 2 );
void from_variant( const fc::variant& var, graphene::chain::public_key_type& vo ); void from_variant( const fc::variant& var, graphene::chain::public_key_type& vo, uint32_t max_depth = 2 );
void to_variant( const graphene::chain::extended_public_key_type& var, fc::variant& vo ); void to_variant( const graphene::chain::extended_public_key_type& var, fc::variant& vo, uint32_t max_depth = 2 );
void from_variant( const fc::variant& var, graphene::chain::extended_public_key_type& vo ); void from_variant( const fc::variant& var, graphene::chain::extended_public_key_type& vo, uint32_t max_depth = 2 );
void to_variant( const graphene::chain::extended_private_key_type& var, fc::variant& vo ); void to_variant( const graphene::chain::extended_private_key_type& var, fc::variant& vo, uint32_t max_depth = 2 );
void from_variant( const fc::variant& var, graphene::chain::extended_private_key_type& vo ); void from_variant( const fc::variant& var, graphene::chain::extended_private_key_type& vo, uint32_t max_depth = 2 );
} }
FC_REFLECT( graphene::chain::public_key_type, (key_data) ) FC_REFLECT( graphene::chain::public_key_type, (key_data) )

View file

@ -141,8 +141,8 @@ namespace fc
class variant; class variant;
void to_variant( const graphene::chain::vote_id_type& var, fc::variant& vo ); void to_variant( const graphene::chain::vote_id_type& var, fc::variant& vo, uint32_t max_depth = 1 );
void from_variant( const fc::variant& var, graphene::chain::vote_id_type& vo ); void from_variant( const fc::variant& var, graphene::chain::vote_id_type& vo, uint32_t max_depth = 1 );
} // fc } // fc

View file

@ -73,6 +73,6 @@ FC_REFLECT( graphene::chain::pts_address, (addr) )
namespace fc namespace fc
{ {
void to_variant( const graphene::chain::pts_address& var, fc::variant& vo ); void to_variant( const graphene::chain::pts_address& var, fc::variant& vo, uint32_t max_depth = 1 );
void from_variant( const fc::variant& var, graphene::chain::pts_address& vo ); void from_variant( const fc::variant& var, graphene::chain::pts_address& vo, uint32_t max_depth = 1 );
} }

View file

@ -101,11 +101,11 @@ namespace graphene {
namespace fc namespace fc
{ {
void to_variant( const graphene::chain::address& var, variant& vo ) void to_variant( const graphene::chain::address& var, variant& vo, uint32_t max_depth )
{ {
vo = std::string(var); vo = std::string(var);
} }
void from_variant( const variant& var, graphene::chain::address& vo ) void from_variant( const variant& var, graphene::chain::address& vo, uint32_t max_depth )
{ {
vo = graphene::chain::address( var.as_string() ); vo = graphene::chain::address( var.as_string() );
} }

View file

@ -248,32 +248,32 @@ namespace graphene { namespace chain {
namespace fc namespace fc
{ {
using namespace std; using namespace std;
void to_variant( const graphene::chain::public_key_type& var, fc::variant& vo ) void to_variant( const graphene::chain::public_key_type& var, fc::variant& vo, uint32_t max_depth )
{ {
vo = std::string( var ); vo = std::string( var );
} }
void from_variant( const fc::variant& var, graphene::chain::public_key_type& vo ) void from_variant( const fc::variant& var, graphene::chain::public_key_type& vo, uint32_t max_depth )
{ {
vo = graphene::chain::public_key_type( var.as_string() ); vo = graphene::chain::public_key_type( var.as_string() );
} }
void to_variant( const graphene::chain::extended_public_key_type& var, fc::variant& vo ) void to_variant( const graphene::chain::extended_public_key_type& var, fc::variant& vo, uint32_t max_depth )
{ {
vo = std::string( var ); vo = std::string( var );
} }
void from_variant( const fc::variant& var, graphene::chain::extended_public_key_type& vo ) void from_variant( const fc::variant& var, graphene::chain::extended_public_key_type& vo, uint32_t max_depth )
{ {
vo = graphene::chain::extended_public_key_type( var.as_string() ); vo = graphene::chain::extended_public_key_type( var.as_string() );
} }
void to_variant( const graphene::chain::extended_private_key_type& var, fc::variant& vo ) void to_variant( const graphene::chain::extended_private_key_type& var, fc::variant& vo, uint32_t max_depth )
{ {
vo = std::string( var ); vo = std::string( var );
} }
void from_variant( const fc::variant& var, graphene::chain::extended_private_key_type& vo ) void from_variant( const fc::variant& var, graphene::chain::extended_private_key_type& vo, uint32_t max_depth )
{ {
vo = graphene::chain::extended_private_key_type( var.as_string() ); vo = graphene::chain::extended_private_key_type( var.as_string() );
} }

View file

@ -38,12 +38,12 @@ vote_id_type get_next_vote_id( global_property_object& gpo, vote_id_type::vote_t
namespace fc namespace fc
{ {
void to_variant(const graphene::chain::vote_id_type& var, variant& vo) void to_variant( const graphene::chain::vote_id_type& var, variant& vo, uint32_t max_depth )
{ {
vo = string(var); vo = string(var);
} }
void from_variant(const variant& var, graphene::chain::vote_id_type& vo) void from_variant( const variant& var, graphene::chain::vote_id_type& vo, uint32_t max_depth )
{ {
vo = graphene::chain::vote_id_type(var.as_string()); vo = graphene::chain::vote_id_type(var.as_string());
} }

View file

@ -89,11 +89,11 @@ namespace graphene { namespace chain {
namespace fc namespace fc
{ {
void to_variant( const graphene::chain::pts_address& var, variant& vo ) void to_variant( const graphene::chain::pts_address& var, variant& vo, uint32_t max_depth )
{ {
vo = std::string(var); vo = std::string(var);
} }
void from_variant( const variant& var, graphene::chain::pts_address& vo ) void from_variant( const variant& var, graphene::chain::pts_address& vo, uint32_t max_depth )
{ {
vo = graphene::chain::pts_address( var.as_string() ); vo = graphene::chain::pts_address( var.as_string() );
} }

View file

@ -130,7 +130,7 @@ namespace graphene { namespace db {
virtual fc::uint128 hash()const = 0; virtual fc::uint128 hash()const = 0;
virtual void add_observer( const shared_ptr<index_observer>& ) = 0; virtual void add_observer( const shared_ptr<index_observer>& ) = 0;
virtual void object_from_variant( const fc::variant& var, object& obj )const = 0; virtual void object_from_variant( const fc::variant& var, object& obj, uint32_t max_depth )const = 0;
virtual void object_default( object& obj )const = 0; virtual void object_default( object& obj )const = 0;
}; };
@ -301,12 +301,12 @@ namespace graphene { namespace db {
_observers.emplace_back( o ); _observers.emplace_back( o );
} }
virtual void object_from_variant( const fc::variant& var, object& obj )const override virtual void object_from_variant( const fc::variant& var, object& obj, uint32_t max_depth )const override
{ {
object_id_type id = obj.id; object_id_type id = obj.id;
object_type* result = dynamic_cast<object_type*>( &obj ); object_type* result = dynamic_cast<object_type*>( &obj );
FC_ASSERT( result != nullptr ); FC_ASSERT( result != nullptr );
fc::from_variant( var, *result ); fc::from_variant( var, *result, max_depth );
obj.id = id; obj.id = id;
} }

View file

@ -27,6 +27,8 @@
#include <fc/crypto/city.hpp> #include <fc/crypto/city.hpp>
#include <fc/uint128.hpp> #include <fc/uint128.hpp>
#define MAX_NESTING (200)
namespace graphene { namespace db { namespace graphene { namespace db {
/** /**
@ -98,7 +100,7 @@ namespace graphene { namespace db {
{ {
static_cast<DerivedClass&>(*this) = std::move( static_cast<DerivedClass&>(obj) ); static_cast<DerivedClass&>(*this) = std::move( static_cast<DerivedClass&>(obj) );
} }
virtual variant to_variant()const { return variant( static_cast<const DerivedClass&>(*this) ); } virtual variant to_variant()const { return variant( static_cast<const DerivedClass&>(*this), MAX_NESTING ); }
virtual vector<char> pack()const { return fc::raw::pack( static_cast<const DerivedClass&>(*this) ); } virtual vector<char> pack()const { return fc::raw::pack( static_cast<const DerivedClass&>(*this) ); }
virtual fc::uint128 hash()const { virtual fc::uint128 hash()const {
auto tmp = this->pack(); auto tmp = this->pack();

View file

@ -169,12 +169,12 @@ struct reflector<graphene::db::object_id<SpaceID,TypeID,T> >
}; };
inline void to_variant( const graphene::db::object_id_type& var, fc::variant& vo ) inline void to_variant( const graphene::db::object_id_type& var, fc::variant& vo, uint32_t max_depth = 1 )
{ {
vo = std::string( var ); vo = std::string( var );
} }
inline void from_variant( const fc::variant& var, graphene::db::object_id_type& vo ) inline void from_variant( const fc::variant& var, graphene::db::object_id_type& vo, uint32_t max_depth = 1 )
{ try { { try {
vo.number = 0; vo.number = 0;
const auto& s = var.get_string(); const auto& s = var.get_string();
@ -191,12 +191,12 @@ struct reflector<graphene::db::object_id<SpaceID,TypeID,T> >
vo.number |= (space_id << 56) | (type_id << 48); vo.number |= (space_id << 56) | (type_id << 48);
} FC_CAPTURE_AND_RETHROW( (var) ) } } FC_CAPTURE_AND_RETHROW( (var) ) }
template<uint8_t SpaceID, uint8_t TypeID, typename T> template<uint8_t SpaceID, uint8_t TypeID, typename T>
void to_variant( const graphene::db::object_id<SpaceID,TypeID,T>& var, fc::variant& vo ) void to_variant( const graphene::db::object_id<SpaceID,TypeID,T>& var, fc::variant& vo, uint32_t max_depth = 1 )
{ {
vo = fc::to_string(SpaceID) + "." + fc::to_string(TypeID) + "." + fc::to_string(var.instance.value); vo = fc::to_string(SpaceID) + "." + fc::to_string(TypeID) + "." + fc::to_string(var.instance.value);
} }
template<uint8_t SpaceID, uint8_t TypeID, typename T> template<uint8_t SpaceID, uint8_t TypeID, typename T>
void from_variant( const fc::variant& var, graphene::db::object_id<SpaceID,TypeID,T>& vo ) void from_variant( const fc::variant& var, graphene::db::object_id<SpaceID,TypeID,T>& vo, uint32_t max_depth = 1 )
{ try { { try {
const auto& s = var.get_string(); const auto& s = var.get_string();
auto first_dot = s.find('.'); auto first_dot = s.find('.');

View file

@ -26,7 +26,7 @@ using namespace graphene::chain;
chain_id_type get_egenesis_chain_id() chain_id_type get_egenesis_chain_id()
{ {
return chain_id_type( "${chain_id}$" ); return chain_id_type( "${chain_id}" );
} }
void compute_egenesis_json( std::string& result ) void compute_egenesis_json( std::string& result )

View file

@ -24,26 +24,25 @@ namespace graphene { namespace egenesis {
using namespace graphene::chain; using namespace graphene::chain;
static const char genesis_json_array[${genesis_json_array_height}$][${genesis_json_array_width}$+1] = static const char genesis_json_array[${genesis_json_array_height}][${genesis_json_array_width}+1] =
{ {
${genesis_json_array}$ ${genesis_json_array}
}; };
chain_id_type get_egenesis_chain_id() chain_id_type get_egenesis_chain_id()
{ {
return chain_id_type( "${chain_id}$" ); return chain_id_type( "${chain_id}" );
} }
void compute_egenesis_json( std::string& result ) void compute_egenesis_json( std::string& result )
{ {
result.reserve( ${genesis_json_length}$ ); result.reserve( ${genesis_json_length} );
result.resize(0); result.resize(0);
for( size_t i=0; i<${genesis_json_array_height}$-1; i++ ) for( size_t i=0; i<${genesis_json_array_height}-1; i++ )
{ {
result.append( genesis_json_array[i], ${genesis_json_array_width}$ ); result.append( genesis_json_array[i], ${genesis_json_array_width} );
} }
result.append( std::string( genesis_json_array[ ${genesis_json_array_height}$-1 ] ) ); result.append( std::string( genesis_json_array[ ${genesis_json_array_height}-1 ] ) );
return;
} }
fc::sha256 get_egenesis_json_hash() fc::sha256 get_egenesis_json_hash()

View file

@ -168,7 +168,7 @@ struct egenesis_info
// If genesis not exist, generate from genesis_json // If genesis not exist, generate from genesis_json
try try
{ {
genesis = fc::json::from_string( *genesis_json ).as< genesis_state_type >(); genesis = fc::json::from_string( *genesis_json ).as< genesis_state_type >( 20 );
} }
catch (const fc::exception& e) catch (const fc::exception& e)
{ {
@ -223,7 +223,6 @@ void load_genesis(
std::cerr << "embed_genesis: Genesis ID from argument is " << chain_id_str << "\n"; std::cerr << "embed_genesis: Genesis ID from argument is " << chain_id_str << "\n";
info.chain_id = chain_id_str; info.chain_id = chain_id_str;
} }
return;
} }
int main( int argc, char** argv ) int main( int argc, char** argv )

View file

@ -106,3 +106,7 @@
#define GRAPHENE_NET_MIN_BLOCK_IDS_TO_PREFETCH 10000 #define GRAPHENE_NET_MIN_BLOCK_IDS_TO_PREFETCH 10000
#define GRAPHENE_NET_MAX_TRX_PER_SECOND 1000 #define GRAPHENE_NET_MAX_TRX_PER_SECOND 1000
#define GRAPHENE_NET_MAX_NESTED_OBJECTS (250)
#define MAXIMUM_PEERDB_SIZE 1000

View file

@ -1853,10 +1853,10 @@ namespace graphene { namespace net { namespace detail {
#endif #endif
user_data["bitness"] = sizeof(void*) * 8; user_data["bitness"] = sizeof(void*) * 8;
user_data["node_id"] = _node_id; user_data["node_id"] = fc::variant( _node_id, 1 );
item_hash_t head_block_id = _delegate->get_head_block_id(); item_hash_t head_block_id = _delegate->get_head_block_id();
user_data["last_known_block_hash"] = head_block_id; user_data["last_known_block_hash"] = fc::variant( head_block_id, 1 );
user_data["last_known_block_number"] = _delegate->get_block_number(head_block_id); user_data["last_known_block_number"] = _delegate->get_block_number(head_block_id);
user_data["last_known_block_time"] = _delegate->get_block_time(head_block_id); user_data["last_known_block_time"] = _delegate->get_block_time(head_block_id);
@ -1872,19 +1872,19 @@ namespace graphene { namespace net { namespace detail {
if (user_data.contains("graphene_git_revision_sha")) if (user_data.contains("graphene_git_revision_sha"))
originating_peer->graphene_git_revision_sha = user_data["graphene_git_revision_sha"].as_string(); originating_peer->graphene_git_revision_sha = user_data["graphene_git_revision_sha"].as_string();
if (user_data.contains("graphene_git_revision_unix_timestamp")) if (user_data.contains("graphene_git_revision_unix_timestamp"))
originating_peer->graphene_git_revision_unix_timestamp = fc::time_point_sec(user_data["graphene_git_revision_unix_timestamp"].as<uint32_t>()); originating_peer->graphene_git_revision_unix_timestamp = fc::time_point_sec(user_data["graphene_git_revision_unix_timestamp"].as<uint32_t>(1));
if (user_data.contains("fc_git_revision_sha")) if (user_data.contains("fc_git_revision_sha"))
originating_peer->fc_git_revision_sha = user_data["fc_git_revision_sha"].as_string(); originating_peer->fc_git_revision_sha = user_data["fc_git_revision_sha"].as_string();
if (user_data.contains("fc_git_revision_unix_timestamp")) if (user_data.contains("fc_git_revision_unix_timestamp"))
originating_peer->fc_git_revision_unix_timestamp = fc::time_point_sec(user_data["fc_git_revision_unix_timestamp"].as<uint32_t>()); originating_peer->fc_git_revision_unix_timestamp = fc::time_point_sec(user_data["fc_git_revision_unix_timestamp"].as<uint32_t>(1));
if (user_data.contains("platform")) if (user_data.contains("platform"))
originating_peer->platform = user_data["platform"].as_string(); originating_peer->platform = user_data["platform"].as_string();
if (user_data.contains("bitness")) if (user_data.contains("bitness"))
originating_peer->bitness = user_data["bitness"].as<uint32_t>(); originating_peer->bitness = user_data["bitness"].as<uint32_t>(1);
if (user_data.contains("node_id")) if (user_data.contains("node_id"))
originating_peer->node_id = user_data["node_id"].as<node_id_t>(); originating_peer->node_id = user_data["node_id"].as<node_id_t>(1);
if (user_data.contains("last_known_fork_block_number")) if (user_data.contains("last_known_fork_block_number"))
originating_peer->last_known_fork_block_number = user_data["last_known_fork_block_number"].as<uint32_t>(); originating_peer->last_known_fork_block_number = user_data["last_known_fork_block_number"].as<uint32_t>(1);
} }
void node_impl::on_hello_message( peer_connection* originating_peer, const hello_message& hello_message_received ) void node_impl::on_hello_message( peer_connection* originating_peer, const hello_message& hello_message_received )
@ -1894,7 +1894,7 @@ namespace graphene { namespace net { namespace detail {
node_id_t peer_node_id = hello_message_received.node_public_key; node_id_t peer_node_id = hello_message_received.node_public_key;
try try
{ {
peer_node_id = hello_message_received.user_data["node_id"].as<node_id_t>(); peer_node_id = hello_message_received.user_data["node_id"].as<node_id_t>(1);
} }
catch (const fc::exception&) catch (const fc::exception&)
{ {
@ -2935,7 +2935,7 @@ namespace graphene { namespace net { namespace detail {
( "msg", closing_connection_message_received.reason_for_closing ) ( "msg", closing_connection_message_received.reason_for_closing )
( "error", closing_connection_message_received.error ) ); ( "error", closing_connection_message_received.error ) );
std::ostringstream message; std::ostringstream message;
message << "Peer " << fc::variant( originating_peer->get_remote_endpoint() ).as_string() << message << "Peer " << fc::variant( originating_peer->get_remote_endpoint(), GRAPHENE_NET_MAX_NESTED_OBJECTS ).as_string() <<
" disconnected us: " << closing_connection_message_received.reason_for_closing; " disconnected us: " << closing_connection_message_received.reason_for_closing;
fc::exception detailed_error(FC_LOG_MESSAGE(warn, "Peer ${peer} is disconnecting us because of an error: ${msg}, exception: ${error}", fc::exception detailed_error(FC_LOG_MESSAGE(warn, "Peer ${peer} is disconnecting us because of an error: ${msg}, exception: ${error}",
( "peer", originating_peer->get_remote_endpoint() ) ( "peer", originating_peer->get_remote_endpoint() )
@ -3841,7 +3841,7 @@ namespace graphene { namespace net { namespace detail {
user_data["bitness"] = *peer->bitness; user_data["bitness"] = *peer->bitness;
user_data["user_agent"] = peer->user_agent; user_data["user_agent"] = peer->user_agent;
user_data["last_known_block_hash"] = peer->last_block_delegate_has_seen; user_data["last_known_block_hash"] = fc::variant( peer->last_block_delegate_has_seen, 1 );
user_data["last_known_block_number"] = _delegate->get_block_number(peer->last_block_delegate_has_seen); user_data["last_known_block_number"] = _delegate->get_block_number(peer->last_block_delegate_has_seen);
user_data["last_known_block_time"] = peer->last_block_time_delegate_has_seen; user_data["last_known_block_time"] = peer->last_block_time_delegate_has_seen;
@ -4452,7 +4452,7 @@ namespace graphene { namespace net { namespace detail {
{ {
try try
{ {
_node_configuration = fc::json::from_file( configuration_file_name ).as<detail::node_configuration>(); _node_configuration = fc::json::from_file( configuration_file_name ).as<detail::node_configuration>(GRAPHENE_NET_MAX_NESTED_OBJECTS);
ilog( "Loaded configuration from file ${filename}", ("filename", configuration_file_name ) ); ilog( "Loaded configuration from file ${filename}", ("filename", configuration_file_name ) );
if( _node_configuration.private_key == fc::ecc::private_key() ) if( _node_configuration.private_key == fc::ecc::private_key() )
@ -4816,20 +4816,19 @@ namespace graphene { namespace net { namespace detail {
peer_to_disconnect->send_message( closing_message ); peer_to_disconnect->send_message( closing_message );
} }
// notify the user. This will be useful in testing, but we might want to remove it later; // notify the user. This will be useful in testing, but we might want to remove it later.
// it makes good sense to notify the user if other nodes think she is behaving badly, but // It makes good sense to notify the user if other nodes think she is behaving badly, but
// if we're just detecting and dissconnecting other badly-behaving nodes, they don't really care. // if we're just detecting and dissconnecting other badly-behaving nodes, they don't really care.
if (caused_by_error) if (caused_by_error)
{ {
std::ostringstream error_message; std::ostringstream error_message;
error_message << "I am disconnecting peer " << fc::variant( peer_to_disconnect->get_remote_endpoint() ).as_string() << error_message << "I am disconnecting peer " << fc::variant( peer_to_disconnect->get_remote_endpoint(), GRAPHENE_NET_MAX_NESTED_OBJECTS ).as_string() <<
" for reason: " << reason_for_disconnect; " for reason: " << reason_for_disconnect;
_delegate->error_encountered(error_message.str(), fc::oexception()); _delegate->error_encountered(error_message.str(), fc::oexception());
dlog(error_message.str()); dlog(error_message.str());
} }
else else
dlog("Disconnecting from ${peer} for ${reason}", ("peer",peer_to_disconnect->get_remote_endpoint()) ("reason",reason_for_disconnect)); dlog("Disconnecting from ${peer} for ${reason}", ("peer",peer_to_disconnect->get_remote_endpoint()) ("reason",reason_for_disconnect));
// peer_to_disconnect->close_connection();
} }
void node_impl::listen_on_endpoint( const fc::ip::endpoint& ep, bool wait_if_not_available ) void node_impl::listen_on_endpoint( const fc::ip::endpoint& ep, bool wait_if_not_available )
@ -4888,7 +4887,7 @@ namespace graphene { namespace net { namespace detail {
peer_details["version"] = ""; peer_details["version"] = "";
peer_details["subver"] = peer->user_agent; peer_details["subver"] = peer->user_agent;
peer_details["inbound"] = peer->direction == peer_connection_direction::inbound; peer_details["inbound"] = peer->direction == peer_connection_direction::inbound;
peer_details["firewall_status"] = peer->is_firewalled; peer_details["firewall_status"] = fc::variant( peer->is_firewalled, 1 );
peer_details["startingheight"] = ""; peer_details["startingheight"] = "";
peer_details["banscore"] = ""; peer_details["banscore"] = "";
peer_details["syncnode"] = ""; peer_details["syncnode"] = "";
@ -4922,7 +4921,7 @@ namespace graphene { namespace net { namespace detail {
// provide these for debugging // provide these for debugging
// warning: these are just approximations, if the peer is "downstream" of us, they may // warning: these are just approximations, if the peer is "downstream" of us, they may
// have received blocks from other peers that we are unaware of // have received blocks from other peers that we are unaware of
peer_details["current_head_block"] = peer->last_block_delegate_has_seen; peer_details["current_head_block"] = fc::variant( peer->last_block_delegate_has_seen, 1 );
peer_details["current_head_block_number"] = _delegate->get_block_number(peer->last_block_delegate_has_seen); peer_details["current_head_block_number"] = _delegate->get_block_number(peer->last_block_delegate_has_seen);
peer_details["current_head_block_time"] = peer->last_block_time_delegate_has_seen; peer_details["current_head_block_time"] = peer->last_block_time_delegate_has_seen;
@ -4998,17 +4997,17 @@ namespace graphene { namespace net { namespace detail {
{ {
VERIFY_CORRECT_THREAD(); VERIFY_CORRECT_THREAD();
if (params.contains("peer_connection_retry_timeout")) if (params.contains("peer_connection_retry_timeout"))
_peer_connection_retry_timeout = params["peer_connection_retry_timeout"].as<uint32_t>(); _peer_connection_retry_timeout = params["peer_connection_retry_timeout"].as<uint32_t>(1);
if (params.contains("desired_number_of_connections")) if (params.contains("desired_number_of_connections"))
_desired_number_of_connections = params["desired_number_of_connections"].as<uint32_t>(); _desired_number_of_connections = params["desired_number_of_connections"].as<uint32_t>(1);
if (params.contains("maximum_number_of_connections")) if (params.contains("maximum_number_of_connections"))
_maximum_number_of_connections = params["maximum_number_of_connections"].as<uint32_t>(); _maximum_number_of_connections = params["maximum_number_of_connections"].as<uint32_t>(1);
if (params.contains("maximum_number_of_blocks_to_handle_at_one_time")) if (params.contains("maximum_number_of_blocks_to_handle_at_one_time"))
_maximum_number_of_blocks_to_handle_at_one_time = params["maximum_number_of_blocks_to_handle_at_one_time"].as<uint32_t>(); _maximum_number_of_blocks_to_handle_at_one_time = params["maximum_number_of_blocks_to_handle_at_one_time"].as<uint32_t>(1);
if (params.contains("maximum_number_of_sync_blocks_to_prefetch")) if (params.contains("maximum_number_of_sync_blocks_to_prefetch"))
_maximum_number_of_sync_blocks_to_prefetch = params["maximum_number_of_sync_blocks_to_prefetch"].as<uint32_t>(); _maximum_number_of_sync_blocks_to_prefetch = params["maximum_number_of_sync_blocks_to_prefetch"].as<uint32_t>(1);
if (params.contains("maximum_blocks_per_peer_during_syncing")) if (params.contains("maximum_blocks_per_peer_during_syncing"))
_maximum_blocks_per_peer_during_syncing = params["maximum_blocks_per_peer_during_syncing"].as<uint32_t>(); _maximum_blocks_per_peer_during_syncing = params["maximum_blocks_per_peer_during_syncing"].as<uint32_t>(1);
_desired_number_of_connections = std::min(_desired_number_of_connections, _maximum_number_of_connections); _desired_number_of_connections = std::min(_desired_number_of_connections, _maximum_number_of_connections);
@ -5093,9 +5092,9 @@ namespace graphene { namespace net { namespace detail {
VERIFY_CORRECT_THREAD(); VERIFY_CORRECT_THREAD();
fc::mutable_variant_object info; fc::mutable_variant_object info;
info["listening_on"] = _actual_listening_endpoint; info["listening_on"] = _actual_listening_endpoint;
info["node_public_key"] = _node_public_key; info["node_public_key"] = fc::variant( _node_public_key, 1 );
info["node_id"] = _node_id; info["node_id"] = fc::variant( _node_id, 1 );
info["firewalled"] = _is_firewalled; info["firewalled"] = fc::variant( _is_firewalled, 1 );
return info; return info;
} }
fc::variant_object node_impl::network_get_usage_stats() const fc::variant_object node_impl::network_get_usage_stats() const
@ -5123,9 +5122,9 @@ namespace graphene { namespace net { namespace detail {
std::plus<uint32_t>()); std::plus<uint32_t>());
fc::mutable_variant_object result; fc::mutable_variant_object result;
result["usage_by_second"] = network_usage_by_second; result["usage_by_second"] = fc::variant( network_usage_by_second, 2 );
result["usage_by_minute"] = network_usage_by_minute; result["usage_by_minute"] = fc::variant( network_usage_by_minute, 2 );
result["usage_by_hour"] = network_usage_by_hour; result["usage_by_hour"] = fc::variant( network_usage_by_hour, 2 );
return result; return result;
} }

View file

@ -34,8 +34,7 @@
#include <fc/io/json.hpp> #include <fc/io/json.hpp>
#include <graphene/net/peer_database.hpp> #include <graphene/net/peer_database.hpp>
#include <graphene/net/config.hpp>
namespace graphene { namespace net { namespace graphene { namespace net {
namespace detail namespace detail
@ -81,7 +80,7 @@ namespace graphene { namespace net {
public: public:
typedef peer_database_impl::potential_peer_set::index<peer_database_impl::last_seen_time_index>::type::iterator last_seen_time_index_iterator; typedef peer_database_impl::potential_peer_set::index<peer_database_impl::last_seen_time_index>::type::iterator last_seen_time_index_iterator;
last_seen_time_index_iterator _iterator; last_seen_time_index_iterator _iterator;
peer_database_iterator_impl(const last_seen_time_index_iterator& iterator) : explicit peer_database_iterator_impl(const last_seen_time_index_iterator& iterator) :
_iterator(iterator) _iterator(iterator)
{} {}
}; };
@ -95,9 +94,8 @@ namespace graphene { namespace net {
{ {
try try
{ {
std::vector<potential_peer_record> peer_records = fc::json::from_file(_peer_database_filename).as<std::vector<potential_peer_record> >(); std::vector<potential_peer_record> peer_records = fc::json::from_file(_peer_database_filename).as<std::vector<potential_peer_record> >( GRAPHENE_NET_MAX_NESTED_OBJECTS );
std::copy(peer_records.begin(), peer_records.end(), std::inserter(_potential_peer_set, _potential_peer_set.end())); std::copy(peer_records.begin(), peer_records.end(), std::inserter(_potential_peer_set, _potential_peer_set.end()));
#define MAXIMUM_PEERDB_SIZE 1000
if (_potential_peer_set.size() > MAXIMUM_PEERDB_SIZE) if (_potential_peer_set.size() > MAXIMUM_PEERDB_SIZE)
{ {
// prune database to a reasonable size // prune database to a reasonable size
@ -125,7 +123,7 @@ namespace graphene { namespace net {
fc::path peer_database_filename_dir = _peer_database_filename.parent_path(); fc::path peer_database_filename_dir = _peer_database_filename.parent_path();
if (!fc::exists(peer_database_filename_dir)) if (!fc::exists(peer_database_filename_dir))
fc::create_directories(peer_database_filename_dir); fc::create_directories(peer_database_filename_dir);
fc::json::save_to_file(peer_records, _peer_database_filename); fc::json::save_to_file( peer_records, _peer_database_filename, GRAPHENE_NET_MAX_NESTED_OBJECTS );
} }
catch (const fc::exception& e) catch (const fc::exception& e)
{ {

View file

@ -22,12 +22,11 @@ namespace detail {
class debug_api_impl class debug_api_impl
{ {
public: public:
debug_api_impl( graphene::app::application& _app ); explicit debug_api_impl( graphene::app::application& _app );
void debug_push_blocks( const std::string& src_filename, uint32_t count ); void debug_push_blocks( const std::string& src_filename, uint32_t count );
void debug_generate_blocks( const std::string& debug_key, uint32_t count ); void debug_generate_blocks( const std::string& debug_key, uint32_t count );
void debug_update_object( const fc::variant_object& update ); void debug_update_object( const fc::variant_object& update );
//void debug_save_db( std::string db_path );
void debug_stream_json_objects( const std::string& filename ); void debug_stream_json_objects( const std::string& filename );
void debug_stream_json_objects_flush(); void debug_stream_json_objects_flush();
std::shared_ptr< graphene::debug_witness_plugin::debug_witness_plugin > get_plugin(); std::shared_ptr< graphene::debug_witness_plugin::debug_witness_plugin > get_plugin();
@ -71,7 +70,6 @@ void debug_api_impl::debug_push_blocks( const std::string& src_filename, uint32_
} }
} }
ilog( "Completed loading block_database successfully" ); ilog( "Completed loading block_database successfully" );
return;
} }
} }
@ -93,7 +91,7 @@ void debug_api_impl::debug_generate_blocks( const std::string& debug_key, uint32
if( scheduled_key != debug_public_key ) if( scheduled_key != debug_public_key )
{ {
ilog( "Modified key for witness ${w}", ("w", scheduled_witness) ); ilog( "Modified key for witness ${w}", ("w", scheduled_witness) );
fc::mutable_variant_object update; fc::limited_mutable_variant_object update( GRAPHENE_MAX_NESTED_OBJECTS );
update("_action", "update")("id", scheduled_witness)("signing_key", debug_public_key); update("_action", "update")("id", scheduled_witness)("signing_key", debug_public_key);
db->debug_update( update ); db->debug_update( update );
} }

View file

@ -68,7 +68,7 @@ void debug_witness_plugin::plugin_initialize(const boost::program_options::varia
const std::vector<std::string> key_id_to_wif_pair_strings = options["private-key"].as<std::vector<std::string>>(); const std::vector<std::string> key_id_to_wif_pair_strings = options["private-key"].as<std::vector<std::string>>();
for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings) for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
{ {
auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >(key_id_to_wif_pair_string); 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);
idump((key_id_to_wif_pair)); idump((key_id_to_wif_pair));
fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second); fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
if (!private_key) if (!private_key)
@ -77,7 +77,7 @@ void debug_witness_plugin::plugin_initialize(const boost::program_options::varia
// just here to ease the transition, can be removed soon // just here to ease the transition, can be removed soon
try try
{ {
private_key = fc::variant(key_id_to_wif_pair.second).as<fc::ecc::private_key>(); private_key = fc::variant( key_id_to_wif_pair.second, GRAPHENE_MAX_NESTED_OBJECTS ).as<fc::ecc::private_key>( GRAPHENE_MAX_NESTED_OBJECTS );
} }
catch (const fc::exception&) catch (const fc::exception&)
{ {

View file

@ -65,7 +65,7 @@ void delayed_node_plugin::plugin_set_program_options(bpo::options_description& c
void delayed_node_plugin::connect() void delayed_node_plugin::connect()
{ {
my->client_connection = std::make_shared<fc::rpc::websocket_api_connection>(*my->client.connect(my->remote_endpoint)); my->client_connection = std::make_shared<fc::rpc::websocket_api_connection>(*my->client.connect(my->remote_endpoint), GRAPHENE_NET_MAX_NESTED_OBJECTS);
my->database_api = my->client_connection->get_remote_api<graphene::app::database_api>(0); my->database_api = my->client_connection->get_remote_api<graphene::app::database_api>(0);
my->client_connection_closed = my->client_connection->closed.connect([this] { my->client_connection_closed = my->client_connection->closed.connect([this] {
connection_failed(); connection_failed();
@ -142,7 +142,7 @@ void delayed_node_plugin::plugin_startup()
connect(); connect();
my->database_api->set_block_applied_callback([this]( const fc::variant& block_id ) my->database_api->set_block_applied_callback([this]( const fc::variant& block_id )
{ {
fc::from_variant( block_id, my->last_received_remote_head ); fc::from_variant( block_id, my->last_received_remote_head, GRAPHENE_MAX_NESTED_OBJECTS );
} ); } );
return; return;
} }

View file

@ -0,0 +1,303 @@
/*
* Copyright (c) 2018 Abit More, and contributors.
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <graphene/grouped_orders/grouped_orders_plugin.hpp>
#include <graphene/chain/market_object.hpp>
namespace graphene { namespace grouped_orders {
namespace detail
{
class grouped_orders_plugin_impl
{
public:
grouped_orders_plugin_impl(grouped_orders_plugin& _plugin)
:_self( _plugin ) {}
virtual ~grouped_orders_plugin_impl();
graphene::chain::database& database()
{
return _self.database();
}
grouped_orders_plugin& _self;
flat_set<uint16_t> _tracked_groups;
};
/**
* @brief This secondary index is used to track changes on limit order objects.
*/
class limit_order_group_index : public secondary_index
{
public:
limit_order_group_index( const flat_set<uint16_t>& groups ) : _tracked_groups( groups ) {};
virtual void object_inserted( const object& obj ) override;
virtual void object_removed( const object& obj ) override;
virtual void about_to_modify( const object& before ) override;
virtual void object_modified( const object& after ) override;
const flat_set<uint16_t>& get_tracked_groups() const
{ return _tracked_groups; }
const map< limit_order_group_key, limit_order_group_data >& get_order_groups() const
{ return _og_data; }
private:
void remove_order( const limit_order_object& obj, bool remove_empty = true );
/** tracked groups */
flat_set<uint16_t> _tracked_groups;
/** maps the group key to group data */
map< limit_order_group_key, limit_order_group_data > _og_data;
};
void limit_order_group_index::object_inserted( const object& objct )
{ try {
const limit_order_object& o = static_cast<const limit_order_object&>( objct );
auto& idx = _og_data;
for( uint16_t group : get_tracked_groups() )
{
auto create_ogo = [&]() {
idx[ limit_order_group_key( group, o.sell_price ) ] = limit_order_group_data( o.sell_price, o.for_sale );
};
// if idx is empty, insert this order
// Note: not capped
if( idx.empty() )
{
create_ogo();
continue;
}
// cap the price
price capped_price = o.sell_price;
price max = o.sell_price.max();
price min = o.sell_price.min();
bool capped_max = false;
bool capped_min = false;
if( o.sell_price > max )
{
capped_price = max;
capped_max = true;
}
else if( o.sell_price < min )
{
capped_price = min;
capped_min = true;
}
// if idx is not empty, find the group that is next to this order
auto itr = idx.lower_bound( limit_order_group_key( group, capped_price ) );
bool check_previous = false;
if( itr == idx.end() || itr->first.group != group
|| itr->first.min_price.base.asset_id != o.sell_price.base.asset_id
|| itr->first.min_price.quote.asset_id != o.sell_price.quote.asset_id )
// not same market or group type
check_previous = true;
else // same market and group type
{
bool update_max = false;
if( capped_price > itr->second.max_price ) // implies itr->min_price <= itr->max_price < max
{
update_max = true;
price max_price = itr->first.min_price * ratio_type( GRAPHENE_100_PERCENT + group, GRAPHENE_100_PERCENT );
// max_price should have been capped here
if( capped_price > max_price ) // new order is out of range
check_previous = true;
}
if( !check_previous ) // new order is within the range
{
if( capped_min && o.sell_price < itr->first.min_price )
{ // need to update itr->min_price here, if itr is below min, and new order is even lower
// TODO improve performance
limit_order_group_data data( itr->second.max_price, o.for_sale + itr->second.total_for_sale );
idx.erase( itr );
idx[ limit_order_group_key( group, o.sell_price ) ] = data;
}
else
{
if( update_max || ( capped_max && o.sell_price > itr->second.max_price ) )
itr->second.max_price = o.sell_price; // store real price here, not capped
itr->second.total_for_sale += o.for_sale;
}
}
}
if( check_previous )
{
if( itr == idx.begin() ) // no previous
create_ogo();
else
{
--itr; // should be valid
if( itr->first.group != group || itr->first.min_price.base.asset_id != o.sell_price.base.asset_id
|| itr->first.min_price.quote.asset_id != o.sell_price.quote.asset_id )
// not same market or group type
create_ogo();
else // same market and group type
{
// due to lower_bound, always true: capped_price < itr->first.min_price, so no need to check again,
// if new order is in range of itr group, always need to update itr->first.min_price, unless
// o.sell_price is higher than max
price min_price = itr->second.max_price / ratio_type( GRAPHENE_100_PERCENT + group, GRAPHENE_100_PERCENT );
// min_price should have been capped here
if( capped_price < min_price ) // new order is out of range
create_ogo();
else if( capped_max && o.sell_price >= itr->first.min_price )
{ // itr is above max, and price of new order is even higher
if( o.sell_price > itr->second.max_price )
itr->second.max_price = o.sell_price;
itr->second.total_for_sale += o.for_sale;
}
else
{ // new order is within the range
// TODO improve performance
limit_order_group_data data( itr->second.max_price, o.for_sale + itr->second.total_for_sale );
idx.erase( itr );
idx[ limit_order_group_key( group, o.sell_price ) ] = data;
}
}
}
}
}
} FC_CAPTURE_AND_RETHROW( (objct) ); }
void limit_order_group_index::object_removed( const object& objct )
{ try {
const limit_order_object& o = static_cast<const limit_order_object&>( objct );
remove_order( o );
} FC_CAPTURE_AND_RETHROW( (objct) ); }
void limit_order_group_index::about_to_modify( const object& objct )
{ try {
const limit_order_object& o = static_cast<const limit_order_object&>( objct );
remove_order( o, false );
} FC_CAPTURE_AND_RETHROW( (objct) ); }
void limit_order_group_index::object_modified( const object& objct )
{ try {
object_inserted( objct );
} FC_CAPTURE_AND_RETHROW( (objct) ); }
void limit_order_group_index::remove_order( const limit_order_object& o, bool remove_empty )
{
auto& idx = _og_data;
for( uint16_t group : get_tracked_groups() )
{
// find the group that should contain this order
auto itr = idx.lower_bound( limit_order_group_key( group, o.sell_price ) );
if( itr == idx.end() || itr->first.group != group
|| itr->first.min_price.base.asset_id != o.sell_price.base.asset_id
|| itr->first.min_price.quote.asset_id != o.sell_price.quote.asset_id
|| itr->second.max_price < o.sell_price )
{
// can not find corresponding group, should not happen
wlog( "can not find the order group containing order for removing (price dismatch): ${o}", ("o",o) );
continue;
}
else // found
{
if( itr->second.total_for_sale < o.for_sale )
// should not happen
wlog( "can not find the order group containing order for removing (amount dismatch): ${o}", ("o",o) );
else if( !remove_empty || itr->second.total_for_sale > o.for_sale )
itr->second.total_for_sale -= o.for_sale;
else
// it's the only order in the group and need to be removed
idx.erase( itr );
}
}
}
grouped_orders_plugin_impl::~grouped_orders_plugin_impl()
{}
} // end namespace detail
grouped_orders_plugin::grouped_orders_plugin() :
my( new detail::grouped_orders_plugin_impl(*this) )
{
}
grouped_orders_plugin::~grouped_orders_plugin()
{
}
std::string grouped_orders_plugin::plugin_name()const
{
return "grouped_orders";
}
void grouped_orders_plugin::plugin_set_program_options(
boost::program_options::options_description& cli,
boost::program_options::options_description& cfg
)
{
cli.add_options()
("tracked-groups", boost::program_options::value<string>()->default_value("[10,100]"), // 0.1% and 1%
"Group orders by percentage increase on price. Specify a JSON array of numbers here, each number is a group, number 1 means 0.01%. ")
;
cfg.add(cli);
}
void grouped_orders_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ try {
if( options.count( "tracked-groups" ) )
{
const std::string& groups = options["tracked-groups"].as<string>();
my->_tracked_groups = fc::json::from_string(groups).as<flat_set<uint16_t>>( 2 );
my->_tracked_groups.erase( 0 );
}
else
my->_tracked_groups = fc::json::from_string("[10,100]").as<flat_set<uint16_t>>(2);
database().add_secondary_index< primary_index<limit_order_index>, detail::limit_order_group_index >( my->_tracked_groups );
} FC_CAPTURE_AND_RETHROW() }
void grouped_orders_plugin::plugin_startup()
{
}
const flat_set<uint16_t>& grouped_orders_plugin::tracked_groups() const
{
return my->_tracked_groups;
}
const map< limit_order_group_key, limit_order_group_data >& grouped_orders_plugin::limit_order_groups()
{
const auto& idx = database().get_index_type< limit_order_index >();
const auto& pidx = dynamic_cast<const primary_index< limit_order_index >&>(idx);
const auto& logidx = pidx.get_secondary_index< detail::limit_order_group_index >();
return logidx.get_order_groups();
}
} }

View file

@ -265,14 +265,15 @@ void market_history_plugin::plugin_set_program_options(
void market_history_plugin::plugin_initialize(const boost::program_options::variables_map& options) void market_history_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ try { { try {
database().applied_block.connect( [&]( const signed_block& b){ my->update_market_histories(b); } ); database().applied_block.connect( [this]( const signed_block& b){ my->update_market_histories(b); } );
database().add_index< primary_index< bucket_index > >(); database().add_index< primary_index< bucket_index > >();
database().add_index< primary_index< history_index > >(); database().add_index< primary_index< history_index > >();
if( options.count( "bucket-size" ) ) if( options.count( "bucket-size" ) )
{ {
const std::string& buckets = options["bucket-size"].as<string>(); const std::string& buckets = options["bucket-size"].as<string>();
my->_tracked_buckets = fc::json::from_string(buckets).as<flat_set<uint32_t>>(); my->_tracked_buckets = fc::json::from_string(buckets).as<flat_set<uint32_t>>(2);
my->_tracked_buckets.erase( 0 );
} }
if( options.count( "history-per-size" ) ) if( options.count( "history-per-size" ) )
my->_maximum_history_per_bucket_size = options["history-per-size"].as<uint32_t>(); my->_maximum_history_per_bucket_size = options["history-per-size"].as<uint32_t>();

View file

@ -75,7 +75,7 @@ public:
private: private:
void schedule_production_loop(); void schedule_production_loop();
block_production_condition::block_production_condition_enum block_production_loop(); block_production_condition::block_production_condition_enum block_production_loop();
block_production_condition::block_production_condition_enum maybe_produce_block( fc::mutable_variant_object& capture ); block_production_condition::block_production_condition_enum maybe_produce_block( fc::limited_mutable_variant_object& capture );
boost::program_options::variables_map _options; boost::program_options::variables_map _options;
bool _production_enabled = false; bool _production_enabled = false;

View file

@ -59,7 +59,6 @@ void new_chain_banner( const graphene::chain::database& db )
"\n" "\n"
; ;
} }
return;
} }
void witness_plugin::plugin_set_program_options( void witness_plugin::plugin_set_program_options(
@ -101,8 +100,7 @@ void witness_plugin::plugin_initialize(const boost::program_options::variables_m
const std::vector<std::string> key_id_to_wif_pair_strings = options["private-key"].as<std::vector<std::string>>(); const std::vector<std::string> key_id_to_wif_pair_strings = options["private-key"].as<std::vector<std::string>>();
for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings) for (const std::string& key_id_to_wif_pair_string : key_id_to_wif_pair_strings)
{ {
auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >(key_id_to_wif_pair_string); auto key_id_to_wif_pair = graphene::app::dejsonify<std::pair<chain::public_key_type, std::string> >(key_id_to_wif_pair_string, 5);
//idump((key_id_to_wif_pair));
ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first)); ilog("Public Key: ${public}", ("public", key_id_to_wif_pair.first));
fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second); fc::optional<fc::ecc::private_key> private_key = graphene::utilities::wif_to_key(key_id_to_wif_pair.second);
if (!private_key) if (!private_key)
@ -111,7 +109,7 @@ void witness_plugin::plugin_initialize(const boost::program_options::variables_m
// just here to ease the transition, can be removed soon // just here to ease the transition, can be removed soon
try try
{ {
private_key = fc::variant(key_id_to_wif_pair.second).as<fc::ecc::private_key>(); private_key = fc::variant(key_id_to_wif_pair.second, 2).as<fc::ecc::private_key>(1);
} }
catch (const fc::exception&) catch (const fc::exception&)
{ {
@ -147,7 +145,7 @@ void witness_plugin::plugin_startup()
void witness_plugin::plugin_shutdown() void witness_plugin::plugin_shutdown()
{ {
return; // nothing to do
} }
void witness_plugin::schedule_production_loop() void witness_plugin::schedule_production_loop()
@ -161,7 +159,6 @@ void witness_plugin::schedule_production_loop()
fc::time_point next_wakeup( now + fc::microseconds( time_to_next_second ) ); fc::time_point next_wakeup( now + fc::microseconds( time_to_next_second ) );
//wdump( (now.time_since_epoch().count())(next_wakeup.time_since_epoch().count()) );
_block_production_task = fc::schedule([this]{block_production_loop();}, _block_production_task = fc::schedule([this]{block_production_loop();},
next_wakeup, "Witness Block Production"); next_wakeup, "Witness Block Production");
} }
@ -169,7 +166,7 @@ void witness_plugin::schedule_production_loop()
block_production_condition::block_production_condition_enum witness_plugin::block_production_loop() block_production_condition::block_production_condition_enum witness_plugin::block_production_loop()
{ {
block_production_condition::block_production_condition_enum result; block_production_condition::block_production_condition_enum result;
fc::mutable_variant_object capture; fc::limited_mutable_variant_object capture( GRAPHENE_MAX_NESTED_OBJECTS );
try try
{ {
result = maybe_produce_block(capture); result = maybe_produce_block(capture);
@ -197,10 +194,8 @@ block_production_condition::block_production_condition_enum witness_plugin::bloc
ilog("Not producing block because production is disabled until we receive a recent block (see: --enable-stale-production)"); ilog("Not producing block because production is disabled until we receive a recent block (see: --enable-stale-production)");
break; break;
case block_production_condition::not_my_turn: case block_production_condition::not_my_turn:
//ilog("Not producing block because it isn't my turn");
break; break;
case block_production_condition::not_time_yet: case block_production_condition::not_time_yet:
//dlog("Not producing block because slot has not yet arrived");
break; break;
case block_production_condition::no_private_key: case block_production_condition::no_private_key:
ilog("Not producing block because I don't have the private key for ${scheduled_key}", ilog("Not producing block because I don't have the private key for ${scheduled_key}",
@ -217,7 +212,7 @@ block_production_condition::block_production_condition_enum witness_plugin::bloc
elog("Not producing block because the last block was generated by the same witness.\nThis node is probably disconnected from the network so block production has been disabled.\nDisable this check with --allow-consecutive option."); elog("Not producing block because the last block was generated by the same witness.\nThis node is probably disconnected from the network so block production has been disabled.\nDisable this check with --allow-consecutive option.");
break; break;
case block_production_condition::exception_producing_block: case block_production_condition::exception_producing_block:
elog( "exception prodcing block" ); elog( "exception producing block" );
break; break;
} }
@ -225,7 +220,7 @@ block_production_condition::block_production_condition_enum witness_plugin::bloc
return result; return result;
} }
block_production_condition::block_production_condition_enum witness_plugin::maybe_produce_block( fc::mutable_variant_object& capture ) block_production_condition::block_production_condition_enum witness_plugin::maybe_produce_block( fc::limited_mutable_variant_object& capture )
{ {
chain::database& db = database(); chain::database& db = database();
fc::time_point now_fine = fc::time_point::now(); fc::time_point now_fine = fc::time_point::now();

View file

@ -58,7 +58,7 @@ fc::optional<fc::ecc::private_key> wif_to_key( const std::string& wif_key )
if (wif_bytes.size() < 5) if (wif_bytes.size() < 5)
return fc::optional<fc::ecc::private_key>(); return fc::optional<fc::ecc::private_key>();
std::vector<char> key_bytes(wif_bytes.begin() + 1, wif_bytes.end() - 4); std::vector<char> key_bytes(wif_bytes.begin() + 1, wif_bytes.end() - 4);
fc::ecc::private_key key = fc::variant(key_bytes).as<fc::ecc::private_key>(); fc::ecc::private_key key = fc::variant( key_bytes, 1 ).as<fc::ecc::private_key>( 1 );
fc::sha256 check = fc::sha256::hash(wif_bytes.data(), wif_bytes.size() - 4); fc::sha256 check = fc::sha256::hash(wif_bytes.data(), wif_bytes.size() - 4);
fc::sha256 check2 = fc::sha256::hash(check); fc::sha256 check2 = fc::sha256::hash(check);

View file

@ -39,7 +39,6 @@ namespace impl {
std::string clean_name( const std::string& name ) std::string clean_name( const std::string& name )
{ {
std::string result;
const static std::string prefix = "graphene::chain::"; const static std::string prefix = "graphene::chain::";
const static std::string suffix = "_operation"; const static std::string suffix = "_operation";
// graphene::chain::.*_operation // graphene::chain::.*_operation
@ -81,24 +80,25 @@ struct from_which_visitor
result_type operator()( const Member& dummy ) result_type operator()( const Member& dummy )
{ {
Member result; Member result;
from_variant( v, result ); from_variant( v, result, _max_depth );
return result; // converted from StaticVariant to Result automatically due to return type return result; // converted from StaticVariant to Result automatically due to return type
} }
const variant& v; const variant& v;
const uint32_t _max_depth;
from_which_visitor( const variant& _v ) : v(_v) {} from_which_visitor( const variant& _v, uint32_t max_depth ) : v(_v), _max_depth(max_depth) {}
}; };
} // namespace impl } // namespace impl
template< typename T > template< typename T >
T from_which_variant( int which, const variant& v ) T from_which_variant( int which, const variant& v, uint32_t max_depth )
{ {
// Parse a variant for a known which() // Parse a variant for a known which()
T dummy; T dummy;
dummy.set_which( which ); dummy.set_which( which );
impl::from_which_visitor< T > vtor(v); impl::from_which_visitor< T > vtor(v, max_depth);
return dummy.visit( vtor ); return dummy.visit( vtor );
} }

View file

@ -34,8 +34,8 @@ using namespace std;
namespace fc namespace fc
{ {
void to_variant(const account_multi_index_type& accts, variant& vo); void to_variant( const account_multi_index_type& accts, variant& vo, uint32_t max_depth );
void from_variant(const variant &var, account_multi_index_type &vo); void from_variant( const variant &var, account_multi_index_type &vo, uint32_t max_depth );
} }
namespace graphene { namespace wallet { namespace graphene { namespace wallet {

View file

@ -98,7 +98,7 @@ namespace detail {
struct operation_result_printer struct operation_result_printer
{ {
public: public:
operation_result_printer( const wallet_api_impl& w ) explicit operation_result_printer( const wallet_api_impl& w )
: _wallet(w) {} : _wallet(w) {}
const wallet_api_impl& _wallet; const wallet_api_impl& _wallet;
typedef std::string result_type; typedef std::string result_type;
@ -151,10 +151,10 @@ optional<T> maybe_id( const string& name_or_id )
{ {
try try
{ {
return fc::variant(name_or_id).as<T>(); return fc::variant(name_or_id, 1).as<T>(1);
} }
catch (const fc::exception&) catch (const fc::exception&)
{ { // not an ID
} }
} }
return optional<T>(); return optional<T>();
@ -641,7 +641,7 @@ public:
T get_object(object_id<T::space_id, T::type_id, T> id)const T get_object(object_id<T::space_id, T::type_id, T> id)const
{ {
auto ob = _remote_db->get_objects({id}).front(); auto ob = _remote_db->get_objects({id}).front();
return ob.template as<T>(); return ob.template as<T>( GRAPHENE_MAX_NESTED_OBJECTS );
} }
void set_operation_fees( signed_transaction& tx, const fee_schedule& s ) void set_operation_fees( signed_transaction& tx, const fee_schedule& s )
@ -657,16 +657,16 @@ public:
auto dynamic_props = get_dynamic_global_properties(); auto dynamic_props = get_dynamic_global_properties();
fc::mutable_variant_object result; fc::mutable_variant_object result;
result["head_block_num"] = dynamic_props.head_block_number; result["head_block_num"] = dynamic_props.head_block_number;
result["head_block_id"] = dynamic_props.head_block_id; result["head_block_id"] = fc::variant(dynamic_props.head_block_id, 1);
result["head_block_age"] = fc::get_approximate_relative_time_string(dynamic_props.time, result["head_block_age"] = fc::get_approximate_relative_time_string(dynamic_props.time,
time_point_sec(time_point::now()), time_point_sec(time_point::now()),
" old"); " old");
result["next_maintenance_time"] = fc::get_approximate_relative_time_string(dynamic_props.next_maintenance_time); result["next_maintenance_time"] = fc::get_approximate_relative_time_string(dynamic_props.next_maintenance_time);
result["chain_id"] = chain_props.chain_id; result["chain_id"] = chain_props.chain_id;
result["participation"] = (100*dynamic_props.recent_slots_filled.popcount()) / 128.0; result["participation"] = (100*dynamic_props.recent_slots_filled.popcount()) / 128.0;
result["active_witnesses"] = global_props.active_witnesses; result["active_witnesses"] = fc::variant(global_props.active_witnesses, GRAPHENE_MAX_NESTED_OBJECTS);
result["active_committee_members"] = global_props.active_committee_members; result["active_committee_members"] = fc::variant(global_props.active_committee_members, GRAPHENE_MAX_NESTED_OBJECTS);
result["entropy"] = dynamic_props.random; result["entropy"] = fc::variant(dynamic_props.random, GRAPHENE_MAX_NESTED_OBJECTS);
return result; return result;
} }
@ -801,7 +801,7 @@ public:
FC_ASSERT( asset_symbol_or_id.size() > 0 ); FC_ASSERT( asset_symbol_or_id.size() > 0 );
vector<optional<asset_object>> opt_asset; vector<optional<asset_object>> opt_asset;
if( std::isdigit( asset_symbol_or_id.front() ) ) if( std::isdigit( asset_symbol_or_id.front() ) )
return fc::variant(asset_symbol_or_id).as<asset_id_type>(); return fc::variant(asset_symbol_or_id, 1).as<asset_id_type>( 1 );
opt_asset = _remote_db->lookup_asset_symbols( {asset_symbol_or_id} ); opt_asset = _remote_db->lookup_asset_symbols( {asset_symbol_or_id} );
FC_ASSERT( (opt_asset.size() > 0) && (opt_asset[0].valid()) ); FC_ASSERT( (opt_asset.size() > 0) && (opt_asset[0].valid()) );
return opt_asset[0]->id; return opt_asset[0]->id;
@ -1013,7 +1013,7 @@ public:
if( ! fc::exists( wallet_filename ) ) if( ! fc::exists( wallet_filename ) )
return false; return false;
_wallet = fc::json::from_file( wallet_filename ).as< wallet_data >(); _wallet = fc::json::from_file( wallet_filename ).as< wallet_data >( 2 * GRAPHENE_MAX_NESTED_OBJECTS );
if( _wallet.chain_id != _chain_id ) if( _wallet.chain_id != _chain_id )
FC_THROW( "Wallet chain ID does not match", FC_THROW( "Wallet chain ID does not match",
("wallet.chain_id", _wallet.chain_id) ("wallet.chain_id", _wallet.chain_id)
@ -1843,7 +1843,6 @@ public:
{ try { { try {
witness_object witness = get_witness(witness_name); witness_object witness = get_witness(witness_name);
account_object witness_account = get_account( witness.witness_account ); account_object witness_account = get_account( witness.witness_account );
fc::ecc::private_key active_private_key = get_private_key_for_account(witness_account);
witness_update_operation witness_update_op; witness_update_operation witness_update_op;
witness_update_op.witness = witness.id; witness_update_op.witness = witness.id;
@ -1867,7 +1866,7 @@ public:
static WorkerInit _create_worker_initializer( const variant& worker_settings ) static WorkerInit _create_worker_initializer( const variant& worker_settings )
{ {
WorkerInit result; WorkerInit result;
from_variant( worker_settings, result ); from_variant( worker_settings, result, GRAPHENE_MAX_NESTED_OBJECTS );
return result; return result;
} }
@ -1921,7 +1920,6 @@ public:
) )
{ {
account_object acct = get_account( account ); account_object acct = get_account( account );
account_update_operation op;
// you could probably use a faster algorithm for this, but flat_set is fast enough :) // you could probably use a faster algorithm for this, but flat_set is fast enough :)
flat_set< worker_id_type > merged; flat_set< worker_id_type > merged;
@ -1955,7 +1953,7 @@ public:
for( const variant& obj : objects ) for( const variant& obj : objects )
{ {
worker_object wo; worker_object wo;
from_variant( obj, wo ); from_variant( obj, wo, GRAPHENE_MAX_NESTED_OBJECTS );
new_votes.erase( wo.vote_for ); new_votes.erase( wo.vote_for );
new_votes.erase( wo.vote_against ); new_votes.erase( wo.vote_against );
if( delta.vote_for.find( wo.id ) != delta.vote_for.end() ) if( delta.vote_for.find( wo.id ) != delta.vote_for.end() )
@ -2485,7 +2483,7 @@ public:
m["get_account_history"] = [this](variant result, const fc::variants& a) m["get_account_history"] = [this](variant result, const fc::variants& a)
{ {
auto r = result.as<vector<operation_detail>>(); auto r = result.as<vector<operation_detail>>( GRAPHENE_MAX_NESTED_OBJECTS );
std::stringstream ss; std::stringstream ss;
for( operation_detail& d : r ) for( operation_detail& d : r )
@ -2502,7 +2500,7 @@ public:
}; };
m["get_relative_account_history"] = [this](variant result, const fc::variants& a) m["get_relative_account_history"] = [this](variant result, const fc::variants& a)
{ {
auto r = result.as<vector<operation_detail>>(); auto r = result.as<vector<operation_detail>>( GRAPHENE_MAX_NESTED_OBJECTS );
std::stringstream ss; std::stringstream ss;
for( operation_detail& d : r ) for( operation_detail& d : r )
@ -2518,9 +2516,32 @@ public:
return ss.str(); return ss.str();
}; };
m["get_account_history_by_operations"] = [this](variant result, const fc::variants& a) {
auto r = result.as<account_history_operation_detail>( GRAPHENE_MAX_NESTED_OBJECTS );
std::stringstream ss;
ss << "total_count : ";
ss << r.total_count;
ss << " \n";
ss << "result_count : ";
ss << r.result_count;
ss << " \n";
for (operation_detail_ex& d : r.details) {
operation_history_object& i = d.op;
auto b = _remote_db->get_block_header(i.block_num);
FC_ASSERT(b);
ss << b->timestamp.to_iso_string() << " ";
i.op.visit(operation_printer(ss, *this, i.result));
ss << " transaction_id : ";
ss << d.transaction_id.str();
ss << " \n";
}
return ss.str();
};
m["list_account_balances"] = [this](variant result, const fc::variants& a) m["list_account_balances"] = [this](variant result, const fc::variants& a)
{ {
auto r = result.as<vector<asset>>(); auto r = result.as<vector<asset>>( GRAPHENE_MAX_NESTED_OBJECTS );
vector<asset_object> asset_recs; vector<asset_object> asset_recs;
std::transform(r.begin(), r.end(), std::back_inserter(asset_recs), [this](const asset& a) { std::transform(r.begin(), r.end(), std::back_inserter(asset_recs), [this](const asset& a) {
return get_asset(a.asset_id); return get_asset(a.asset_id);
@ -2550,7 +2571,7 @@ public:
m["get_blind_balances"] = [this](variant result, const fc::variants& a) m["get_blind_balances"] = [this](variant result, const fc::variants& a)
{ {
auto r = result.as<vector<asset>>(); auto r = result.as<vector<asset>>( GRAPHENE_MAX_NESTED_OBJECTS );
vector<asset_object> asset_recs; vector<asset_object> asset_recs;
std::transform(r.begin(), r.end(), std::back_inserter(asset_recs), [this](const asset& a) { std::transform(r.begin(), r.end(), std::back_inserter(asset_recs), [this](const asset& a) {
return get_asset(a.asset_id); return get_asset(a.asset_id);
@ -2564,7 +2585,7 @@ public:
}; };
m["transfer_to_blind"] = [this](variant result, const fc::variants& a) m["transfer_to_blind"] = [this](variant result, const fc::variants& a)
{ {
auto r = result.as<blind_confirmation>(); auto r = result.as<blind_confirmation>( GRAPHENE_MAX_NESTED_OBJECTS );
std::stringstream ss; std::stringstream ss;
r.trx.operations[0].visit( operation_printer( ss, *this, operation_result() ) ); r.trx.operations[0].visit( operation_printer( ss, *this, operation_result() ) );
ss << "\n"; ss << "\n";
@ -2577,7 +2598,7 @@ public:
}; };
m["blind_transfer"] = [this](variant result, const fc::variants& a) m["blind_transfer"] = [this](variant result, const fc::variants& a)
{ {
auto r = result.as<blind_confirmation>(); auto r = result.as<blind_confirmation>( GRAPHENE_MAX_NESTED_OBJECTS );
std::stringstream ss; std::stringstream ss;
r.trx.operations[0].visit( operation_printer( ss, *this, operation_result() ) ); r.trx.operations[0].visit( operation_printer( ss, *this, operation_result() ) );
ss << "\n"; ss << "\n";
@ -2590,7 +2611,7 @@ public:
}; };
m["receive_blind_transfer"] = [this](variant result, const fc::variants& a) m["receive_blind_transfer"] = [this](variant result, const fc::variants& a)
{ {
auto r = result.as<blind_receipt>(); auto r = result.as<blind_receipt>( GRAPHENE_MAX_NESTED_OBJECTS );
std::stringstream ss; std::stringstream ss;
asset_object as = get_asset( r.amount.asset_id ); asset_object as = get_asset( r.amount.asset_id );
ss << as.amount_to_pretty_string( r.amount ) << " " << r.from_label << " => " << r.to_label << " " << r.memo <<"\n"; ss << as.amount_to_pretty_string( r.amount ) << " " << r.from_label << " => " << r.to_label << " " << r.memo <<"\n";
@ -2598,7 +2619,7 @@ public:
}; };
m["blind_history"] = [this](variant result, const fc::variants& a) m["blind_history"] = [this](variant result, const fc::variants& a)
{ {
auto records = result.as<vector<blind_receipt>>(); auto records = result.as<vector<blind_receipt>>( GRAPHENE_MAX_NESTED_OBJECTS );
std::stringstream ss; std::stringstream ss;
ss << "WHEN " ss << "WHEN "
<< " " << "AMOUNT" << " " << "FROM" << " => " << "TO" << " " << "MEMO" <<"\n"; << " " << "AMOUNT" << " " << "FROM" << " => " << "TO" << " " << "MEMO" <<"\n";
@ -2762,7 +2783,7 @@ public:
}; };
m["get_order_book"] = [this](variant result, const fc::variants& a) m["get_order_book"] = [this](variant result, const fc::variants& a)
{ {
auto orders = result.as<order_book>(); auto orders = result.as<order_book>( GRAPHENE_MAX_NESTED_OBJECTS );
auto bids = orders.bids; auto bids = orders.bids;
auto asks = orders.asks; auto asks = orders.asks;
std::stringstream ss; std::stringstream ss;
@ -2772,12 +2793,10 @@ public:
double ask_sum = 0; double ask_sum = 0;
const int spacing = 20; const int spacing = 20;
auto prettify_num = [&]( double n ) auto prettify_num = [&ss]( double n )
{ {
//ss << n;
if (abs( round( n ) - n ) < 0.00000000001 ) if (abs( round( n ) - n ) < 0.00000000001 )
{ {
//ss << setiosflags( !ios::fixed ) << (int) n; // doesn't compile on Linux with gcc
ss << (int) n; ss << (int) n;
} }
else if (n - floor(n) < 0.000001) else if (n - floor(n) < 0.000001)
@ -2859,7 +2878,7 @@ public:
const chain_parameters& current_params = get_global_properties().parameters; const chain_parameters& current_params = get_global_properties().parameters;
chain_parameters new_params = current_params; chain_parameters new_params = current_params;
fc::reflector<chain_parameters>::visit( fc::reflector<chain_parameters>::visit(
fc::from_variant_visitor<chain_parameters>( changed_values, new_params ) fc::from_variant_visitor<chain_parameters>( changed_values, new_params, GRAPHENE_MAX_NESTED_OBJECTS )
); );
committee_member_update_global_parameters_operation update_op; committee_member_update_global_parameters_operation update_op;
@ -2909,7 +2928,7 @@ public:
continue; continue;
} }
// is key a number? // is key a number?
auto is_numeric = [&]() -> bool auto is_numeric = [&key]() -> bool
{ {
size_t n = key.size(); size_t n = key.size();
for( size_t i=0; i<n; i++ ) for( size_t i=0; i<n; i++ )
@ -2931,7 +2950,7 @@ public:
which = it->second; which = it->second;
} }
fee_parameters fp = from_which_variant< fee_parameters >( which, item.value() ); fee_parameters fp = from_which_variant< fee_parameters >( which, item.value(), GRAPHENE_MAX_NESTED_OBJECTS );
fee_map[ which ] = fp; fee_map[ which ] = fp;
} }
@ -3013,7 +3032,7 @@ public:
proposal_update_operation update_op; proposal_update_operation update_op;
update_op.fee_paying_account = get_account(fee_paying_account).id; update_op.fee_paying_account = get_account(fee_paying_account).id;
update_op.proposal = fc::variant(proposal_id).as<proposal_id_type>(); update_op.proposal = fc::variant(proposal_id, 1).as<proposal_id_type>( 1 );
// make sure the proposal exists // make sure the proposal exists
get_object( update_op.proposal ); get_object( update_op.proposal );
@ -3140,7 +3159,7 @@ public:
for( const auto& peer : peers ) for( const auto& peer : peers )
{ {
variant v; variant v;
fc::to_variant( peer, v ); fc::to_variant( peer, v, GRAPHENE_MAX_NESTED_OBJECTS );
result.push_back( v ); result.push_back( v );
} }
return result; return result;
@ -3153,7 +3172,6 @@ public:
const account_object& master = *_wallet.my_accounts.get<by_name>().lower_bound("import"); const account_object& master = *_wallet.my_accounts.get<by_name>().lower_bound("import");
int number_of_accounts = number_of_transactions / 3; int number_of_accounts = number_of_transactions / 3;
number_of_transactions -= number_of_accounts; number_of_transactions -= number_of_accounts;
//auto key = derive_private_key("floodshill", 0);
try { try {
dbg_make_uia(master.name, "SHILL"); dbg_make_uia(master.name, "SHILL");
} catch(...) {/* Ignore; the asset probably already exists.*/} } catch(...) {/* Ignore; the asset probably already exists.*/}
@ -4621,7 +4639,7 @@ string wallet_api::get_private_key( public_key_type pubkey )const
public_key_type wallet_api::get_public_key( string label )const public_key_type wallet_api::get_public_key( string label )const
{ {
try { return fc::variant(label).as<public_key_type>(); } catch ( ... ){} try { return fc::variant(label, 1).as<public_key_type>( 1 ); } catch ( ... ){}
auto key_itr = my->_wallet.labeled_keys.get<by_label>().find(label); auto key_itr = my->_wallet.labeled_keys.get<by_label>().find(label);
if( key_itr != my->_wallet.labeled_keys.get<by_label>().end() ) if( key_itr != my->_wallet.labeled_keys.get<by_label>().end() )
@ -5911,13 +5929,15 @@ vesting_balance_object_with_info::vesting_balance_object_with_info( const vestin
} } // graphene::wallet } } // graphene::wallet
void fc::to_variant(const account_multi_index_type& accts, fc::variant& vo) namespace fc {
{ void to_variant( const account_multi_index_type& accts, variant& vo, uint32_t max_depth )
vo = vector<account_object>(accts.begin(), accts.end()); {
} to_variant( std::vector<account_object>(accts.begin(), accts.end()), vo, max_depth );
}
void fc::from_variant(const fc::variant& var, account_multi_index_type& vo) void from_variant( const variant& var, account_multi_index_type& vo, uint32_t max_depth )
{ {
const vector<account_object>& v = var.as<vector<account_object>>(); const std::vector<account_object>& v = var.as<std::vector<account_object>>( max_depth );
vo = account_multi_index_type(v.begin(), v.end()); vo = account_multi_index_type(v.begin(), v.end());
}
} }

View file

@ -37,7 +37,7 @@ namespace graphene { namespace member_enumerator {
struct class_processor struct class_processor
{ {
class_processor( std::map< std::string, std::vector< std::string > >& r ) : result(r) {} explicit class_processor( std::map< std::string, std::vector< std::string > >& r ) : result(r) {}
template< typename T > template< typename T >
void process_class( const T* dummy ); void process_class( const T* dummy );
@ -84,7 +84,7 @@ struct member_visitor
struct static_variant_visitor struct static_variant_visitor
{ {
static_variant_visitor( class_processor* p ) : proc(p) {} explicit static_variant_visitor( class_processor* p ) : proc(p) {}
typedef void result_type; typedef void result_type;
@ -215,13 +215,12 @@ int main( int argc, char** argv )
{ {
std::map< std::string, std::vector< std::string > > result; std::map< std::string, std::vector< std::string > > result;
graphene::member_enumerator::class_processor::process_class<signed_block>(result); graphene::member_enumerator::class_processor::process_class<signed_block>(result);
//graphene::member_enumerator::process_class<transfer_operation>(result);
fc::mutable_variant_object mvo; fc::mutable_variant_object mvo;
for( const std::pair< std::string, std::vector< std::string > >& e : result ) for( const std::pair< std::string, std::vector< std::string > >& e : result )
{ {
variant v; variant v;
to_variant( e.second, v ); to_variant( e.second, v , 1);
mvo.set( e.first, v ); mvo.set( e.first, v );
} }

View file

@ -37,6 +37,7 @@
#include <fc/smart_ref_impl.hpp> #include <fc/smart_ref_impl.hpp>
#include <graphene/app/api.hpp> #include <graphene/app/api.hpp>
#include <graphene/chain/config.hpp>
#include <graphene/chain/protocol/protocol.hpp> #include <graphene/chain/protocol/protocol.hpp>
#include <graphene/egenesis/egenesis.hpp> #include <graphene/egenesis/egenesis.hpp>
#include <graphene/utilities/key_conversion.hpp> #include <graphene/utilities/key_conversion.hpp>
@ -108,8 +109,8 @@ int main( int argc, char** argv )
std::cout << "Logging RPC to file: " << (data_dir / ac.filename).preferred_string() << "\n"; std::cout << "Logging RPC to file: " << (data_dir / ac.filename).preferred_string() << "\n";
cfg.appenders.push_back(fc::appender_config( "default", "console", fc::variant(fc::console_appender::config()))); cfg.appenders.push_back(fc::appender_config( "default", "console", fc::variant(fc::console_appender::config(), 20)));
cfg.appenders.push_back(fc::appender_config( "rpc", "file", fc::variant(ac))); cfg.appenders.push_back(fc::appender_config( "rpc", "file", fc::variant(ac, 5)));
cfg.loggers = { fc::logger_config("default"), fc::logger_config( "rpc") }; cfg.loggers = { fc::logger_config("default"), fc::logger_config( "rpc") };
cfg.loggers.front().level = fc::log_level::info; cfg.loggers.front().level = fc::log_level::info;
@ -117,8 +118,6 @@ int main( int argc, char** argv )
cfg.loggers.back().level = fc::log_level::debug; cfg.loggers.back().level = fc::log_level::debug;
cfg.loggers.back().appenders = {"rpc"}; cfg.loggers.back().appenders = {"rpc"};
//fc::configure_logging( cfg );
fc::ecc::private_key committee_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key"))); fc::ecc::private_key committee_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")));
idump( (key_to_wif( committee_private_key ) ) ); idump( (key_to_wif( committee_private_key ) ) );
@ -139,7 +138,7 @@ int main( int argc, char** argv )
fc::path wallet_file( options.count("wallet-file") ? options.at("wallet-file").as<string>() : "wallet.json"); fc::path wallet_file( options.count("wallet-file") ? options.at("wallet-file").as<string>() : "wallet.json");
if( fc::exists( wallet_file ) ) if( fc::exists( wallet_file ) )
{ {
wdata = fc::json::from_file( wallet_file ).as<wallet_data>(); wdata = fc::json::from_file( wallet_file ).as<wallet_data>( GRAPHENE_MAX_NESTED_OBJECTS );
if( options.count("chain-id") ) if( options.count("chain-id") )
{ {
// the --chain-id on the CLI must match the chain ID embedded in the wallet file // the --chain-id on the CLI must match the chain ID embedded in the wallet file
@ -175,12 +174,11 @@ int main( int argc, char** argv )
fc::http::websocket_client client; fc::http::websocket_client client;
idump((wdata.ws_server)); idump((wdata.ws_server));
auto con = client.connect( wdata.ws_server ); auto con = client.connect( wdata.ws_server );
auto apic = std::make_shared<fc::rpc::websocket_api_connection>(*con); auto apic = std::make_shared<fc::rpc::websocket_api_connection>(*con, GRAPHENE_MAX_NESTED_OBJECTS);
auto remote_api = apic->get_remote_api< login_api >(1); auto remote_api = apic->get_remote_api< login_api >(1);
edump((wdata.ws_user)(wdata.ws_password) ); edump((wdata.ws_user)(wdata.ws_password) );
// TODO: Error message here FC_ASSERT( remote_api->login( wdata.ws_user, wdata.ws_password ), "Failed to log in to API server" );
FC_ASSERT( remote_api->login( wdata.ws_user, wdata.ws_password ) );
auto wapiptr = std::make_shared<wallet_api>( wdata, remote_api ); auto wapiptr = std::make_shared<wallet_api>( wdata, remote_api );
wapiptr->set_wallet_filename( wallet_file.generic_string() ); wapiptr->set_wallet_filename( wallet_file.generic_string() );
@ -188,11 +186,11 @@ int main( int argc, char** argv )
fc::api<wallet_api> wapi(wapiptr); fc::api<wallet_api> wapi(wapiptr);
auto wallet_cli = std::make_shared<fc::rpc::cli>(); auto wallet_cli = std::make_shared<fc::rpc::cli>( GRAPHENE_MAX_NESTED_OBJECTS );
for( auto& name_formatter : wapiptr->get_result_formatters() ) for( auto& name_formatter : wapiptr->get_result_formatters() )
wallet_cli->format_result( name_formatter.first, name_formatter.second ); wallet_cli->format_result( name_formatter.first, name_formatter.second );
boost::signals2::scoped_connection closed_connection(con->closed.connect([=]{ boost::signals2::scoped_connection closed_connection(con->closed.connect([wallet_cli]{
cerr << "Server has disconnected us.\n"; cerr << "Server has disconnected us.\n";
wallet_cli->stop(); wallet_cli->stop();
})); }));
@ -212,10 +210,10 @@ int main( int argc, char** argv )
auto _websocket_server = std::make_shared<fc::http::websocket_server>(); auto _websocket_server = std::make_shared<fc::http::websocket_server>();
if( options.count("rpc-endpoint") ) if( options.count("rpc-endpoint") )
{ {
_websocket_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){ _websocket_server->on_connection([&wapi]( const fc::http::websocket_connection_ptr& c ){
std::cout << "here... \n"; std::cout << "here... \n";
wlog("." ); wlog("." );
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(*c); auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(*c, GRAPHENE_MAX_NESTED_OBJECTS);
wsc->register_api(wapi); wsc->register_api(wapi);
c->set_session_data( wsc ); c->set_session_data( wsc );
}); });
@ -231,8 +229,8 @@ int main( int argc, char** argv )
auto _websocket_tls_server = std::make_shared<fc::http::websocket_tls_server>(cert_pem); auto _websocket_tls_server = std::make_shared<fc::http::websocket_tls_server>(cert_pem);
if( options.count("rpc-tls-endpoint") ) if( options.count("rpc-tls-endpoint") )
{ {
_websocket_tls_server->on_connection([&]( const fc::http::websocket_connection_ptr& c ){ _websocket_tls_server->on_connection([&wapi]( const fc::http::websocket_connection_ptr& c ){
auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(*c); auto wsc = std::make_shared<fc::rpc::websocket_api_connection>(*c, GRAPHENE_MAX_NESTED_OBJECTS);
wsc->register_api(wapi); wsc->register_api(wapi);
c->set_session_data( wsc ); c->set_session_data( wsc );
}); });
@ -250,10 +248,10 @@ int main( int argc, char** argv )
// due to implementation, on_request() must come AFTER listen() // due to implementation, on_request() must come AFTER listen()
// //
_http_server->on_request( _http_server->on_request(
[&]( const fc::http::request& req, const fc::http::server::response& resp ) [&wapi]( const fc::http::request& req, const fc::http::server::response& resp )
{ {
std::shared_ptr< fc::rpc::http_api_connection > conn = std::shared_ptr< fc::rpc::http_api_connection > conn =
std::make_shared< fc::rpc::http_api_connection>(); std::make_shared< fc::rpc::http_api_connection >( GRAPHENE_MAX_NESTED_OBJECTS );
conn->register_api( wapi ); conn->register_api( wapi );
conn->on_request( req, resp ); conn->on_request( req, resp );
} ); } );

View file

@ -246,8 +246,8 @@ fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::pat
console_appender_config.level_colors.emplace_back( console_appender_config.level_colors.emplace_back(
fc::console_appender::level_color(fc::log_level::error, fc::console_appender::level_color(fc::log_level::error,
fc::console_appender::color::cyan)); fc::console_appender::color::cyan));
console_appender_config.stream = fc::variant(stream_name).as<fc::console_appender::stream::type>(); console_appender_config.stream = fc::variant(stream_name, 1).as<fc::console_appender::stream::type>(1);
logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config))); logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
found_logging_config = true; found_logging_config = true;
} }
else if (boost::starts_with(section_name, file_appender_section_prefix)) else if (boost::starts_with(section_name, file_appender_section_prefix))
@ -266,7 +266,7 @@ fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::pat
file_appender_config.rotate = true; file_appender_config.rotate = true;
file_appender_config.rotation_interval = fc::hours(1); file_appender_config.rotation_interval = fc::hours(1);
file_appender_config.rotation_limit = fc::days(1); file_appender_config.rotation_limit = fc::days(1);
logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config))); logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
found_logging_config = true; found_logging_config = true;
} }
else if (boost::starts_with(section_name, logger_section_prefix)) else if (boost::starts_with(section_name, logger_section_prefix))
@ -275,7 +275,7 @@ fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::pat
std::string level_string = section_tree.get<std::string>("level"); std::string level_string = section_tree.get<std::string>("level");
std::string appenders_string = section_tree.get<std::string>("appenders"); std::string appenders_string = section_tree.get<std::string>("appenders");
fc::logger_config logger_config(logger_name); fc::logger_config logger_config(logger_name);
logger_config.level = fc::variant(level_string).as<fc::log_level>(); logger_config.level = fc::variant(level_string, 1).as<fc::log_level>(1);
boost::split(logger_config.appenders, appenders_string, boost::split(logger_config.appenders, appenders_string,
boost::is_any_of(" ,"), boost::is_any_of(" ,"),
boost::token_compress_on); boost::token_compress_on);

View file

@ -110,7 +110,7 @@ int main( int argc, char** argv )
std::cerr << "update_genesis: Reading genesis from file " << genesis_json_filename.preferred_string() << "\n"; std::cerr << "update_genesis: Reading genesis from file " << genesis_json_filename.preferred_string() << "\n";
std::string genesis_json; std::string genesis_json;
read_file_contents( genesis_json_filename, genesis_json ); read_file_contents( genesis_json_filename, genesis_json );
genesis = fc::json::from_string( genesis_json ).as< genesis_state_type >(); genesis = fc::json::from_string( genesis_json ).as< genesis_state_type >(20);
} }
else else
{ {
@ -120,8 +120,8 @@ int main( int argc, char** argv )
if (!options.count("nop")) if (!options.count("nop"))
{ {
std::string dev_key_prefix = options["dev-key-prefix"].as<std::string>(); const std::string dev_key_prefix = options["dev-key-prefix"].as<std::string>();
auto get_dev_key = [&]( std::string prefix, uint32_t i ) -> public_key_type auto get_dev_key = [&dev_key_prefix]( std::string prefix, uint32_t i ) -> public_key_type
{ {
return fc::ecc::private_key::regenerate( fc::sha256::hash( dev_key_prefix + prefix + std::to_string(i) ) ).get_public_key(); return fc::ecc::private_key::regenerate( fc::sha256::hash( dev_key_prefix + prefix + std::to_string(i) ) ).get_public_key();
}; };

View file

@ -70,9 +70,9 @@ int main( int argc, char** argv )
bool comma = false; bool comma = false;
auto show_key = [&]( const fc::ecc::private_key& priv_key ) auto show_key = [&comma]( const fc::ecc::private_key& priv_key )
{ {
fc::mutable_variant_object mvo; fc::limited_mutable_variant_object mvo(5);
graphene::chain::public_key_type pub_key = priv_key.get_public_key(); graphene::chain::public_key_type pub_key = priv_key.get_public_key();
mvo( "private_key", graphene::utilities::key_to_wif( priv_key ) ) mvo( "private_key", graphene::utilities::key_to_wif( priv_key ) )
( "public_key", std::string( pub_key ) ) ( "public_key", std::string( pub_key ) )
@ -80,7 +80,7 @@ int main( int argc, char** argv )
; ;
if( comma ) if( comma )
std::cout << ",\n"; std::cout << ",\n";
std::cout << fc::json::to_string( mvo ); std::cout << fc::json::to_string( fc::mutable_variant_object(mvo) );
comma = true; comma = true;
}; };
@ -90,7 +90,7 @@ int main( int argc, char** argv )
{ {
std::string arg = argv[i]; std::string arg = argv[i];
std::string prefix; std::string prefix;
int lep = -1, rep; int lep = -1, rep = -1;
auto dash_pos = arg.rfind('-'); auto dash_pos = arg.rfind('-');
if( dash_pos != string::npos ) if( dash_pos != string::npos )
{ {
@ -104,7 +104,6 @@ int main( int argc, char** argv )
rep = std::stoi( rhs.substr( colon_pos+1 ) ); rep = std::stoi( rhs.substr( colon_pos+1 ) );
} }
} }
vector< fc::ecc::private_key > keys;
if( lep >= 0 ) if( lep >= 0 )
{ {
for( int k=lep; k<rep; k++ ) for( int k=lep; k<rep; k++ )

View file

@ -292,8 +292,8 @@ fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::pat
console_appender_config.level_colors.emplace_back( console_appender_config.level_colors.emplace_back(
fc::console_appender::level_color(fc::log_level::error, fc::console_appender::level_color(fc::log_level::error,
fc::console_appender::color::cyan)); fc::console_appender::color::cyan));
console_appender_config.stream = fc::variant(stream_name).as<fc::console_appender::stream::type>(); console_appender_config.stream = fc::variant(stream_name).as<fc::console_appender::stream::type>(GRAPHENE_MAX_NESTED_OBJECTS);
logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config))); logging_config.appenders.push_back(fc::appender_config(console_appender_name, "console", fc::variant(console_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
found_logging_config = true; found_logging_config = true;
} }
else if (boost::starts_with(section_name, file_appender_section_prefix)) else if (boost::starts_with(section_name, file_appender_section_prefix))
@ -312,7 +312,7 @@ fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::pat
file_appender_config.rotate = true; file_appender_config.rotate = true;
file_appender_config.rotation_interval = fc::hours(1); file_appender_config.rotation_interval = fc::hours(1);
file_appender_config.rotation_limit = fc::days(1); file_appender_config.rotation_limit = fc::days(1);
logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config))); logging_config.appenders.push_back(fc::appender_config(file_appender_name, "file", fc::variant(file_appender_config, GRAPHENE_MAX_NESTED_OBJECTS)));
found_logging_config = true; found_logging_config = true;
} }
else if (boost::starts_with(section_name, logger_section_prefix)) else if (boost::starts_with(section_name, logger_section_prefix))
@ -321,7 +321,7 @@ fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::pat
std::string level_string = section_tree.get<std::string>("level"); std::string level_string = section_tree.get<std::string>("level");
std::string appenders_string = section_tree.get<std::string>("appenders"); std::string appenders_string = section_tree.get<std::string>("appenders");
fc::logger_config logger_config(logger_name); fc::logger_config logger_config(logger_name);
logger_config.level = fc::variant(level_string).as<fc::log_level>(); logger_config.level = fc::variant(level_string).as<fc::log_level>(5);
boost::split(logger_config.appenders, appenders_string, boost::split(logger_config.appenders, appenders_string,
boost::is_any_of(" ,"), boost::is_any_of(" ,"),
boost::token_compress_on); boost::token_compress_on);

View file

@ -102,7 +102,7 @@ int main( int argc, char** argv )
std::cerr << "embed_genesis: Reading genesis from file " << genesis_json_filename.preferred_string() << "\n"; std::cerr << "embed_genesis: Reading genesis from file " << genesis_json_filename.preferred_string() << "\n";
std::string genesis_json; std::string genesis_json;
read_file_contents( genesis_json_filename, genesis_json ); read_file_contents( genesis_json_filename, genesis_json );
genesis = fc::json::from_string( genesis_json ).as< genesis_state_type >(); genesis = fc::json::from_string( genesis_json ).as< genesis_state_type >(20);
} }
else else
genesis = graphene::app::detail::create_example_genesis(); genesis = graphene::app::detail::create_example_genesis();
@ -119,7 +119,6 @@ int main( int argc, char** argv )
uint32_t num_blocks = options["num-blocks"].as<uint32_t>(); uint32_t num_blocks = options["num-blocks"].as<uint32_t>();
uint32_t miss_rate = options["miss-rate"].as<uint32_t>(); uint32_t miss_rate = options["miss-rate"].as<uint32_t>();
fc::ecc::private_key init_account_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")) );
fc::ecc::private_key nathan_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan"))); fc::ecc::private_key nathan_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
database db; database db;

View file

@ -64,8 +64,8 @@ BOOST_AUTO_TEST_CASE( serialization_json_test )
op.to = account_id_type(2); op.to = account_id_type(2);
op.amount = asset(100); op.amount = asset(100);
trx.operations.push_back( op ); trx.operations.push_back( op );
fc::variant packed(trx); fc::variant packed(trx, GRAPHENE_MAX_NESTED_OBJECTS);
signed_transaction unpacked = packed.as<signed_transaction>(); signed_transaction unpacked = packed.as<signed_transaction>( GRAPHENE_MAX_NESTED_OBJECTS );
unpacked.validate(); unpacked.validate();
BOOST_CHECK( digest(trx) == digest(unpacked) ); BOOST_CHECK( digest(trx) == digest(unpacked) );
} catch (fc::exception& e) { } catch (fc::exception& e) {