Implement FBA fee routing for STEALTH #563
This commit is contained in:
parent
1f910e765d
commit
5dd56bd824
19 changed files with 472 additions and 8 deletions
|
|
@ -348,6 +348,8 @@ namespace graphene { namespace app {
|
||||||
break;
|
break;
|
||||||
case impl_buyback_object_type:
|
case impl_buyback_object_type:
|
||||||
break;
|
break;
|
||||||
|
case impl_fba_accumulator_object_type:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,11 @@ struct get_impacted_account_visitor
|
||||||
_impacted.insert( op.account );
|
_impacted.insert( op.account );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()( const fba_distribute_operation& op )
|
||||||
|
{
|
||||||
|
_impacted.insert( op.account_id );
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
void operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ add_library( graphene_chain
|
||||||
|
|
||||||
account_object.cpp
|
account_object.cpp
|
||||||
asset_object.cpp
|
asset_object.cpp
|
||||||
|
fba_object.cpp
|
||||||
proposal_object.cpp
|
proposal_object.cpp
|
||||||
vesting_balance_object.cpp
|
vesting_balance_object.cpp
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -260,14 +260,28 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
|
||||||
database& d = db();
|
database& d = db();
|
||||||
bool sa_before, sa_after;
|
bool sa_before, sa_after;
|
||||||
d.modify( *acnt, [&](account_object& a){
|
d.modify( *acnt, [&](account_object& a){
|
||||||
if( o.owner ) a.owner = *o.owner;
|
if( o.owner )
|
||||||
if( o.active ) a.active = *o.active;
|
{
|
||||||
|
a.owner = *o.owner;
|
||||||
|
a.top_n_control_flags = 0;
|
||||||
|
}
|
||||||
|
if( o.active )
|
||||||
|
{
|
||||||
|
a.active = *o.active;
|
||||||
|
a.top_n_control_flags = 0;
|
||||||
|
}
|
||||||
if( o.new_options ) a.options = *o.new_options;
|
if( o.new_options ) a.options = *o.new_options;
|
||||||
sa_before = a.has_special_authority();
|
sa_before = a.has_special_authority();
|
||||||
if( o.extensions.value.owner_special_authority.valid() )
|
if( o.extensions.value.owner_special_authority.valid() )
|
||||||
|
{
|
||||||
a.owner_special_authority = *(o.extensions.value.owner_special_authority);
|
a.owner_special_authority = *(o.extensions.value.owner_special_authority);
|
||||||
|
a.top_n_control_flags = 0;
|
||||||
|
}
|
||||||
if( o.extensions.value.active_special_authority.valid() )
|
if( o.extensions.value.active_special_authority.valid() )
|
||||||
|
{
|
||||||
a.active_special_authority = *(o.extensions.value.active_special_authority);
|
a.active_special_authority = *(o.extensions.value.active_special_authority);
|
||||||
|
a.top_n_control_flags = 0;
|
||||||
|
}
|
||||||
sa_after = a.has_special_authority();
|
sa_after = a.has_special_authority();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@
|
||||||
#include <graphene/chain/confidential_evaluator.hpp>
|
#include <graphene/chain/confidential_evaluator.hpp>
|
||||||
#include <graphene/chain/confidential_object.hpp>
|
#include <graphene/chain/confidential_object.hpp>
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
|
#include <graphene/chain/fba_accumulator_id.hpp>
|
||||||
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
@ -67,6 +69,13 @@ void_result transfer_to_blind_evaluator::do_apply( const transfer_to_blind_opera
|
||||||
return void_result();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||||
|
|
||||||
|
void transfer_to_blind_evaluator::pay_fee()
|
||||||
|
{
|
||||||
|
if( db().head_block_time() >= HARDFORK_563_TIME )
|
||||||
|
pay_fba_fee( fba_accumulator_id_transfer_to_blind );
|
||||||
|
else
|
||||||
|
generic_evaluator::pay_fee();
|
||||||
|
}
|
||||||
|
|
||||||
void_result transfer_from_blind_evaluator::do_evaluate( const transfer_from_blind_operation& o )
|
void_result transfer_from_blind_evaluator::do_evaluate( const transfer_from_blind_operation& o )
|
||||||
{ try {
|
{ try {
|
||||||
|
|
@ -104,9 +113,13 @@ void_result transfer_from_blind_evaluator::do_apply( const transfer_from_blind_o
|
||||||
return void_result();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||||
|
|
||||||
|
void transfer_from_blind_evaluator::pay_fee()
|
||||||
|
{
|
||||||
|
if( db().head_block_time() >= HARDFORK_563_TIME )
|
||||||
|
pay_fba_fee( fba_accumulator_id_transfer_from_blind );
|
||||||
|
else
|
||||||
|
generic_evaluator::pay_fee();
|
||||||
|
}
|
||||||
|
|
||||||
void_result blind_transfer_evaluator::do_evaluate( const blind_transfer_operation& o )
|
void_result blind_transfer_evaluator::do_evaluate( const blind_transfer_operation& o )
|
||||||
{ try {
|
{ try {
|
||||||
|
|
@ -157,5 +170,12 @@ void_result blind_transfer_evaluator::do_apply( const blind_transfer_operation&
|
||||||
return void_result();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||||
|
|
||||||
|
void blind_transfer_evaluator::pay_fee()
|
||||||
|
{
|
||||||
|
if( db().head_block_time() >= HARDFORK_563_TIME )
|
||||||
|
pay_fba_fee( fba_accumulator_id_blind_transfer );
|
||||||
|
else
|
||||||
|
generic_evaluator::pay_fee();
|
||||||
|
}
|
||||||
|
|
||||||
} } // graphene::chain
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
|
#include <graphene/chain/fba_accumulator_id.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/account_object.hpp>
|
#include <graphene/chain/account_object.hpp>
|
||||||
#include <graphene/chain/asset_object.hpp>
|
#include <graphene/chain/asset_object.hpp>
|
||||||
|
|
@ -33,6 +34,7 @@
|
||||||
#include <graphene/chain/chain_property_object.hpp>
|
#include <graphene/chain/chain_property_object.hpp>
|
||||||
#include <graphene/chain/committee_member_object.hpp>
|
#include <graphene/chain/committee_member_object.hpp>
|
||||||
#include <graphene/chain/confidential_object.hpp>
|
#include <graphene/chain/confidential_object.hpp>
|
||||||
|
#include <graphene/chain/fba_object.hpp>
|
||||||
#include <graphene/chain/global_property_object.hpp>
|
#include <graphene/chain/global_property_object.hpp>
|
||||||
#include <graphene/chain/market_object.hpp>
|
#include <graphene/chain/market_object.hpp>
|
||||||
#include <graphene/chain/operation_history_object.hpp>
|
#include <graphene/chain/operation_history_object.hpp>
|
||||||
|
|
@ -212,6 +214,8 @@ void database::initialize_indexes()
|
||||||
add_index< primary_index<simple_index<budget_record_object > > >();
|
add_index< primary_index<simple_index<budget_record_object > > >();
|
||||||
add_index< primary_index< special_authority_index > >();
|
add_index< primary_index< special_authority_index > >();
|
||||||
add_index< primary_index< buyback_index > >();
|
add_index< primary_index< buyback_index > >();
|
||||||
|
|
||||||
|
add_index< primary_index< simple_index< fba_accumulator_object > > >();
|
||||||
}
|
}
|
||||||
|
|
||||||
void database::init_genesis(const genesis_state_type& genesis_state)
|
void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
|
|
@ -664,6 +668,36 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
wso.current_shuffled_witnesses.push_back( wid );
|
wso.current_shuffled_witnesses.push_back( wid );
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create FBA counters
|
||||||
|
create<fba_accumulator_object>([&]( fba_accumulator_object& acc )
|
||||||
|
{
|
||||||
|
FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_transfer_to_blind ) );
|
||||||
|
acc.accumulated_fba_fees = 0;
|
||||||
|
#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET
|
||||||
|
acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET;
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
create<fba_accumulator_object>([&]( fba_accumulator_object& acc )
|
||||||
|
{
|
||||||
|
FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_blind_transfer ) );
|
||||||
|
acc.accumulated_fba_fees = 0;
|
||||||
|
#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET
|
||||||
|
acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET;
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
create<fba_accumulator_object>([&]( fba_accumulator_object& acc )
|
||||||
|
{
|
||||||
|
FC_ASSERT( acc.id == fba_accumulator_id_type( fba_accumulator_id_transfer_from_blind ) );
|
||||||
|
acc.accumulated_fba_fees = 0;
|
||||||
|
#ifdef GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET
|
||||||
|
acc.designated_asset = GRAPHENE_FBA_STEALTH_DESIGNATED_ASSET;
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
FC_ASSERT( get_index<fba_accumulator_object>().get_next_id() == fba_accumulator_id_type( fba_accumulator_id_count ) );
|
||||||
|
|
||||||
debug_dump();
|
debug_dump();
|
||||||
|
|
||||||
_undo_db.enable();
|
_undo_db.enable();
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include <fc/uint128.hpp>
|
#include <fc/uint128.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
|
#include <graphene/chain/fba_accumulator_id.hpp>
|
||||||
#include <graphene/chain/hardfork.hpp>
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
|
||||||
#include <graphene/chain/account_object.hpp>
|
#include <graphene/chain/account_object.hpp>
|
||||||
|
|
@ -36,6 +37,7 @@
|
||||||
#include <graphene/chain/buyback_object.hpp>
|
#include <graphene/chain/buyback_object.hpp>
|
||||||
#include <graphene/chain/chain_property_object.hpp>
|
#include <graphene/chain/chain_property_object.hpp>
|
||||||
#include <graphene/chain/committee_member_object.hpp>
|
#include <graphene/chain/committee_member_object.hpp>
|
||||||
|
#include <graphene/chain/fba_object.hpp>
|
||||||
#include <graphene/chain/global_property_object.hpp>
|
#include <graphene/chain/global_property_object.hpp>
|
||||||
#include <graphene/chain/market_object.hpp>
|
#include <graphene/chain/market_object.hpp>
|
||||||
#include <graphene/chain/special_authority_object.hpp>
|
#include <graphene/chain/special_authority_object.hpp>
|
||||||
|
|
@ -519,11 +521,100 @@ void update_top_n_authorities( database& db )
|
||||||
db.modify( acct, [&]( account_object& a )
|
db.modify( acct, [&]( account_object& a )
|
||||||
{
|
{
|
||||||
vc.finish( is_owner ? a.owner : a.active );
|
vc.finish( is_owner ? a.owner : a.active );
|
||||||
|
if( !vc.is_empty() )
|
||||||
|
a.top_n_control_flags |= (is_owner ? account_object::top_n_control_owner : account_object::top_n_control_active);
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void split_fba_balance(
|
||||||
|
database& db,
|
||||||
|
uint64_t fba_id,
|
||||||
|
uint16_t network_pct,
|
||||||
|
uint16_t designated_asset_buyback_pct,
|
||||||
|
uint16_t designated_asset_issuer_pct
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FC_ASSERT( uint32_t(network_pct) + uint32_t(designated_asset_buyback_pct) + uint32_t(designated_asset_issuer_pct) == GRAPHENE_100_PERCENT );
|
||||||
|
const fba_accumulator_object& fba = fba_accumulator_id_type( fba_id )(db);
|
||||||
|
if( fba.accumulated_fba_fees == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
const asset_object& core = asset_id_type(0)(db);
|
||||||
|
const asset_dynamic_data_object& core_dd = core.dynamic_asset_data_id(db);
|
||||||
|
|
||||||
|
if( !fba.is_configured(db) )
|
||||||
|
{
|
||||||
|
ilog( "${n} core given to network at block ${b} due to non-configured FBA", ("n", fba.accumulated_fba_fees)("b", db.head_block_time()) );
|
||||||
|
db.modify( core_dd, [&]( asset_dynamic_data_object& _core_dd )
|
||||||
|
{
|
||||||
|
_core_dd.current_supply -= fba.accumulated_fba_fees;
|
||||||
|
} );
|
||||||
|
db.modify( fba, [&]( fba_accumulator_object& _fba )
|
||||||
|
{
|
||||||
|
_fba.accumulated_fba_fees = 0;
|
||||||
|
} );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fc::uint128_t buyback_amount_128 = fba.accumulated_fba_fees.value;
|
||||||
|
buyback_amount_128 *= designated_asset_buyback_pct;
|
||||||
|
buyback_amount_128 /= GRAPHENE_100_PERCENT;
|
||||||
|
share_type buyback_amount = buyback_amount_128.to_uint64();
|
||||||
|
|
||||||
|
fc::uint128_t issuer_amount_128 = fba.accumulated_fba_fees.value;
|
||||||
|
issuer_amount_128 *= designated_asset_issuer_pct;
|
||||||
|
issuer_amount_128 /= GRAPHENE_100_PERCENT;
|
||||||
|
share_type issuer_amount = issuer_amount_128.to_uint64();
|
||||||
|
|
||||||
|
// this assert should never fail
|
||||||
|
FC_ASSERT( buyback_amount + issuer_amount <= fba.accumulated_fba_fees );
|
||||||
|
|
||||||
|
share_type network_amount = fba.accumulated_fba_fees - (buyback_amount + issuer_amount);
|
||||||
|
|
||||||
|
const asset_object& designated_asset = (*fba.designated_asset)(db);
|
||||||
|
|
||||||
|
if( network_amount != 0 )
|
||||||
|
{
|
||||||
|
db.modify( core_dd, [&]( asset_dynamic_data_object& _core_dd )
|
||||||
|
{
|
||||||
|
_core_dd.current_supply -= network_amount;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
fba_distribute_operation vop;
|
||||||
|
vop.account_id = *designated_asset.buyback_account;
|
||||||
|
vop.fba_id = fba.id;
|
||||||
|
vop.amount = buyback_amount;
|
||||||
|
if( vop.amount != 0 )
|
||||||
|
{
|
||||||
|
db.adjust_balance( *designated_asset.buyback_account, asset(buyback_amount) );
|
||||||
|
db.push_applied_operation(vop);
|
||||||
|
}
|
||||||
|
|
||||||
|
vop.account_id = designated_asset.issuer;
|
||||||
|
vop.fba_id = fba.id;
|
||||||
|
vop.amount = issuer_amount;
|
||||||
|
if( vop.amount != 0 )
|
||||||
|
{
|
||||||
|
db.adjust_balance( designated_asset.issuer, asset(issuer_amount) );
|
||||||
|
db.push_applied_operation(vop);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.modify( fba, [&]( fba_accumulator_object& _fba )
|
||||||
|
{
|
||||||
|
_fba.accumulated_fba_fees = 0;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void distribute_fba_balances( database& db )
|
||||||
|
{
|
||||||
|
split_fba_balance( db, fba_accumulator_id_transfer_to_blind , 20*GRAPHENE_1_PERCENT, 60*GRAPHENE_1_PERCENT, 20*GRAPHENE_1_PERCENT );
|
||||||
|
split_fba_balance( db, fba_accumulator_id_blind_transfer , 20*GRAPHENE_1_PERCENT, 60*GRAPHENE_1_PERCENT, 20*GRAPHENE_1_PERCENT );
|
||||||
|
split_fba_balance( db, fba_accumulator_id_transfer_from_blind, 20*GRAPHENE_1_PERCENT, 60*GRAPHENE_1_PERCENT, 20*GRAPHENE_1_PERCENT );
|
||||||
|
}
|
||||||
|
|
||||||
void create_buyback_orders( database& db )
|
void create_buyback_orders( database& db )
|
||||||
{
|
{
|
||||||
const auto& bbo_idx = db.get_index_type< buyback_index >().indices().get<by_id>();
|
const auto& bbo_idx = db.get_index_type< buyback_index >().indices().get<by_id>();
|
||||||
|
|
@ -604,6 +695,7 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
||||||
{
|
{
|
||||||
const auto& gpo = get_global_properties();
|
const auto& gpo = get_global_properties();
|
||||||
|
|
||||||
|
distribute_fba_balances(*this);
|
||||||
create_buyback_orders(*this);
|
create_buyback_orders(*this);
|
||||||
|
|
||||||
struct vote_tally_helper {
|
struct vote_tally_helper {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include <graphene/chain/asset_object.hpp>
|
#include <graphene/chain/asset_object.hpp>
|
||||||
#include <graphene/chain/account_object.hpp>
|
#include <graphene/chain/account_object.hpp>
|
||||||
|
#include <graphene/chain/fba_object.hpp>
|
||||||
#include <graphene/chain/committee_member_object.hpp>
|
#include <graphene/chain/committee_member_object.hpp>
|
||||||
#include <graphene/chain/market_evaluator.hpp>
|
#include <graphene/chain/market_evaluator.hpp>
|
||||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||||
|
|
@ -103,4 +104,18 @@ database& generic_evaluator::db()const { return trx_state->db(); }
|
||||||
}
|
}
|
||||||
} FC_CAPTURE_AND_RETHROW() }
|
} FC_CAPTURE_AND_RETHROW() }
|
||||||
|
|
||||||
|
void generic_evaluator::pay_fba_fee( uint64_t fba_id )
|
||||||
|
{
|
||||||
|
database& d = db();
|
||||||
|
const fba_accumulator_object& fba = d.get< fba_accumulator_object >( fba_accumulator_id_type( fba_id ) );
|
||||||
|
if( !fba.is_configured(d) )
|
||||||
|
{
|
||||||
|
generic_evaluator::pay_fee();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d.modify( fba, [&]( fba_accumulator_object& _fba )
|
||||||
|
{
|
||||||
|
_fba.accumulated_fba_fees += core_fee_paid;
|
||||||
|
} );
|
||||||
|
}
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
103
libraries/chain/fba_object.cpp
Normal file
103
libraries/chain/fba_object.cpp
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Cryptonomex, Inc., 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/chain/database.hpp>
|
||||||
|
#include <graphene/chain/evaluator.hpp>
|
||||||
|
#include <graphene/chain/fba_object.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
bool fba_accumulator_object::is_configured( const database& db )const
|
||||||
|
{
|
||||||
|
if( !designated_asset.valid() )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because designated asset was not configured", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const asset_object* dasset = db.find(*designated_asset);
|
||||||
|
if( dasset == nullptr )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: designated asset does not exist", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( dasset->is_market_issued() )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: FBA is a BitAsset", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t allowed_flags = charge_market_fee;
|
||||||
|
|
||||||
|
// check enabled issuer_permissions bits is subset of allowed_flags bits
|
||||||
|
if( (dasset->options.issuer_permissions & allowed_flags) != dasset->options.issuer_permissions )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: Disallowed permissions enabled", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check enabled issuer_permissions bits is subset of allowed_flags bits
|
||||||
|
if( (dasset->options.flags & allowed_flags) != dasset->options.flags )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: Disallowed flags enabled", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !dasset->buyback_account.valid() )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: designated asset does not have a buyback account", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const account_object& issuer_acct = dasset->issuer(db);
|
||||||
|
|
||||||
|
if( issuer_acct.owner_special_authority.which() != special_authority::tag< top_holders_special_authority >::value )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: designated asset issuer has not set owner top_n control", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( issuer_acct.active_special_authority.which() != special_authority::tag< top_holders_special_authority >::value )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: designated asset issuer has not set active top_n control", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( issuer_acct.owner_special_authority.get< top_holders_special_authority >().asset != *designated_asset )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: designated asset issuer's top_n_control is not set to designated asset", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( issuer_acct.active_special_authority.get< top_holders_special_authority >().asset != *designated_asset )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because of FBA misconfiguration: designated asset issuer's top_n_control is not set to designated asset", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( issuer_acct.top_n_control_flags != (account_object::top_n_control_owner | account_object::top_n_control_active) )
|
||||||
|
{
|
||||||
|
ilog( "FBA fee in block ${b} not paid because designated asset's top_n control has not yet activated (wait until next maintenance interval)", ("b", db.head_block_num()) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} }
|
||||||
4
libraries/chain/hardfork.d/563.hf
Normal file
4
libraries/chain/hardfork.d/563.hf
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
// #563 Stealth fee routing
|
||||||
|
#ifndef HARDFORK_563_TIME
|
||||||
|
#define HARDFORK_563_TIME (fc::time_point_sec( 1455127200 ))
|
||||||
|
#endif
|
||||||
|
|
@ -208,6 +208,14 @@ namespace graphene { namespace chain {
|
||||||
special_authority owner_special_authority = no_special_authority();
|
special_authority owner_special_authority = no_special_authority();
|
||||||
special_authority active_special_authority = no_special_authority();
|
special_authority active_special_authority = no_special_authority();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This flag is set when the top_n logic sets both authorities,
|
||||||
|
* and gets reset when authority or special_authority is set.
|
||||||
|
*/
|
||||||
|
uint8_t top_n_control_flags = 0;
|
||||||
|
static const uint8_t top_n_control_owner = 1;
|
||||||
|
static const uint8_t top_n_control_active = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a set of assets which the account is allowed to have.
|
* This is a set of assets which the account is allowed to have.
|
||||||
* This is utilized to restrict buyback accounts to the assets that trade in their markets.
|
* This is utilized to restrict buyback accounts to the assets that trade in their markets.
|
||||||
|
|
@ -365,6 +373,7 @@ FC_REFLECT_DERIVED( graphene::chain::account_object,
|
||||||
(whitelisting_accounts)(blacklisted_accounts)
|
(whitelisting_accounts)(blacklisted_accounts)
|
||||||
(cashback_vb)
|
(cashback_vb)
|
||||||
(owner_special_authority)(active_special_authority)
|
(owner_special_authority)(active_special_authority)
|
||||||
|
(top_n_control_flags)
|
||||||
(allowed_assets)
|
(allowed_assets)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ class transfer_to_blind_evaluator : public evaluator<transfer_to_blind_evaluator
|
||||||
|
|
||||||
void_result do_evaluate( const transfer_to_blind_operation& o );
|
void_result do_evaluate( const transfer_to_blind_operation& o );
|
||||||
void_result do_apply( const transfer_to_blind_operation& o ) ;
|
void_result do_apply( const transfer_to_blind_operation& o ) ;
|
||||||
|
|
||||||
|
virtual void pay_fee() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class transfer_from_blind_evaluator : public evaluator<transfer_from_blind_evaluator>
|
class transfer_from_blind_evaluator : public evaluator<transfer_from_blind_evaluator>
|
||||||
|
|
@ -46,6 +48,8 @@ class transfer_from_blind_evaluator : public evaluator<transfer_from_blind_evalu
|
||||||
|
|
||||||
void_result do_evaluate( const transfer_from_blind_operation& o );
|
void_result do_evaluate( const transfer_from_blind_operation& o );
|
||||||
void_result do_apply( const transfer_from_blind_operation& o ) ;
|
void_result do_apply( const transfer_from_blind_operation& o ) ;
|
||||||
|
|
||||||
|
virtual void pay_fee() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class blind_transfer_evaluator : public evaluator<blind_transfer_evaluator>
|
class blind_transfer_evaluator : public evaluator<blind_transfer_evaluator>
|
||||||
|
|
@ -55,6 +59,8 @@ class blind_transfer_evaluator : public evaluator<blind_transfer_evaluator>
|
||||||
|
|
||||||
void_result do_evaluate( const blind_transfer_operation& o );
|
void_result do_evaluate( const blind_transfer_operation& o );
|
||||||
void_result do_apply( const blind_transfer_operation& o ) ;
|
void_result do_apply( const blind_transfer_operation& o ) ;
|
||||||
|
|
||||||
|
virtual void pay_fee() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} } // namespace graphene::chain
|
} } // namespace graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,11 @@ namespace graphene { namespace chain {
|
||||||
|
|
||||||
object_id_type get_relative_id( object_id_type rel_id )const;
|
object_id_type get_relative_id( object_id_type rel_id )const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pay_fee() for FBA subclass should simply call this method
|
||||||
|
*/
|
||||||
|
void pay_fba_fee( uint64_t fba_id );
|
||||||
|
|
||||||
asset fee_from_account;
|
asset fee_from_account;
|
||||||
share_type core_fee_paid;
|
share_type core_fee_paid;
|
||||||
const account_object* fee_paying_account = nullptr;
|
const account_object* fee_paying_account = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Cryptonomex, Inc., 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.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object will be created at genesis for each of these FBA accumulators.
|
||||||
|
*/
|
||||||
|
enum graphene_fba_accumulator_id_enum
|
||||||
|
{
|
||||||
|
fba_accumulator_id_transfer_to_blind = 0,
|
||||||
|
fba_accumulator_id_blind_transfer,
|
||||||
|
fba_accumulator_id_transfer_from_blind,
|
||||||
|
fba_accumulator_id_count
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
52
libraries/chain/include/graphene/chain/fba_object.hpp
Normal file
52
libraries/chain/include/graphene/chain/fba_object.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Cryptonomex, Inc., 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.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <graphene/chain/protocol/types.hpp>
|
||||||
|
#include <graphene/db/object.hpp>
|
||||||
|
#include <graphene/db/generic_index.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
class database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fba_accumulator_object accumulates fees to be paid out via buyback or other FBA mechanism.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class fba_accumulator_object : public graphene::db::abstract_object< fba_accumulator_object >
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const uint8_t space_id = implementation_ids;
|
||||||
|
static const uint8_t type_id = impl_fba_accumulator_object_type;
|
||||||
|
|
||||||
|
share_type accumulated_fba_fees;
|
||||||
|
optional< asset_id_type > designated_asset;
|
||||||
|
|
||||||
|
bool is_configured( const database& db )const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} } // graphene::chain
|
||||||
|
|
||||||
|
FC_REFLECT_DERIVED( graphene::chain::fba_accumulator_object, (graphene::db::object), (accumulated_fba_fees)(designated_asset) )
|
||||||
47
libraries/chain/include/graphene/chain/protocol/fba.hpp
Normal file
47
libraries/chain/include/graphene/chain/protocol/fba.hpp
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Cryptonomex, Inc., 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.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <graphene/chain/protocol/base.hpp>
|
||||||
|
|
||||||
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
struct fba_distribute_operation : public base_operation
|
||||||
|
{
|
||||||
|
struct fee_parameters_type {};
|
||||||
|
|
||||||
|
asset fee; // always zero
|
||||||
|
account_id_type account_id;
|
||||||
|
fba_accumulator_id_type fba_id;
|
||||||
|
share_type amount;
|
||||||
|
|
||||||
|
account_id_type fee_payer()const { return account_id; }
|
||||||
|
void validate()const { FC_ASSERT( false ); }
|
||||||
|
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::chain::fba_distribute_operation::fee_parameters_type, )
|
||||||
|
|
||||||
|
FC_REFLECT( graphene::chain::fba_distribute_operation, (fee)(account_id)(fba_id)(amount) )
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
#include <graphene/chain/protocol/balance.hpp>
|
#include <graphene/chain/protocol/balance.hpp>
|
||||||
#include <graphene/chain/protocol/custom.hpp>
|
#include <graphene/chain/protocol/custom.hpp>
|
||||||
#include <graphene/chain/protocol/committee_member.hpp>
|
#include <graphene/chain/protocol/committee_member.hpp>
|
||||||
|
#include <graphene/chain/protocol/confidential.hpp>
|
||||||
|
#include <graphene/chain/protocol/fba.hpp>
|
||||||
#include <graphene/chain/protocol/market.hpp>
|
#include <graphene/chain/protocol/market.hpp>
|
||||||
#include <graphene/chain/protocol/proposal.hpp>
|
#include <graphene/chain/protocol/proposal.hpp>
|
||||||
#include <graphene/chain/protocol/transfer.hpp>
|
#include <graphene/chain/protocol/transfer.hpp>
|
||||||
|
|
@ -36,7 +38,6 @@
|
||||||
#include <graphene/chain/protocol/withdraw_permission.hpp>
|
#include <graphene/chain/protocol/withdraw_permission.hpp>
|
||||||
#include <graphene/chain/protocol/witness.hpp>
|
#include <graphene/chain/protocol/witness.hpp>
|
||||||
#include <graphene/chain/protocol/worker.hpp>
|
#include <graphene/chain/protocol/worker.hpp>
|
||||||
#include <graphene/chain/protocol/confidential.hpp>
|
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
namespace graphene { namespace chain {
|
||||||
|
|
||||||
|
|
@ -89,7 +90,8 @@ namespace graphene { namespace chain {
|
||||||
blind_transfer_operation,
|
blind_transfer_operation,
|
||||||
transfer_from_blind_operation,
|
transfer_from_blind_operation,
|
||||||
asset_settle_cancel_operation, // VIRTUAL
|
asset_settle_cancel_operation, // VIRTUAL
|
||||||
asset_claim_fees_operation
|
asset_claim_fees_operation,
|
||||||
|
fba_distribute_operation // VIRTUAL
|
||||||
> operation;
|
> operation;
|
||||||
|
|
||||||
/// @} // operations group
|
/// @} // operations group
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,8 @@ namespace graphene { namespace chain {
|
||||||
impl_witness_schedule_object_type,
|
impl_witness_schedule_object_type,
|
||||||
impl_budget_record_object_type,
|
impl_budget_record_object_type,
|
||||||
impl_special_authority_object_type,
|
impl_special_authority_object_type,
|
||||||
impl_buyback_object_type
|
impl_buyback_object_type,
|
||||||
|
impl_fba_accumulator_object_type
|
||||||
};
|
};
|
||||||
|
|
||||||
//typedef fc::unsigned_int object_id_type;
|
//typedef fc::unsigned_int object_id_type;
|
||||||
|
|
@ -205,6 +206,7 @@ namespace graphene { namespace chain {
|
||||||
class budget_record_object;
|
class budget_record_object;
|
||||||
class special_authority_object;
|
class special_authority_object;
|
||||||
class buyback_object;
|
class buyback_object;
|
||||||
|
class fba_accumulator_object;
|
||||||
|
|
||||||
typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type;
|
typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type;
|
||||||
typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type;
|
typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type;
|
||||||
|
|
@ -224,6 +226,7 @@ namespace graphene { namespace chain {
|
||||||
typedef object_id< implementation_ids, impl_blinded_balance_object_type, blinded_balance_object > blinded_balance_id_type;
|
typedef object_id< implementation_ids, impl_blinded_balance_object_type, blinded_balance_object > blinded_balance_id_type;
|
||||||
typedef object_id< implementation_ids, impl_special_authority_object_type, special_authority_object > special_authority_id_type;
|
typedef object_id< implementation_ids, impl_special_authority_object_type, special_authority_object > special_authority_id_type;
|
||||||
typedef object_id< implementation_ids, impl_buyback_object_type, buyback_object > buyback_id_type;
|
typedef object_id< implementation_ids, impl_buyback_object_type, buyback_object > buyback_id_type;
|
||||||
|
typedef object_id< implementation_ids, impl_fba_accumulator_object_type, fba_accumulator_object > fba_accumulator_id_type;
|
||||||
|
|
||||||
typedef fc::array<char, GRAPHENE_MAX_ASSET_SYMBOL_LENGTH> symbol_type;
|
typedef fc::array<char, GRAPHENE_MAX_ASSET_SYMBOL_LENGTH> symbol_type;
|
||||||
typedef fc::ripemd160 block_id_type;
|
typedef fc::ripemd160 block_id_type;
|
||||||
|
|
@ -355,6 +358,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
||||||
(impl_budget_record_object_type)
|
(impl_budget_record_object_type)
|
||||||
(impl_special_authority_object_type)
|
(impl_special_authority_object_type)
|
||||||
(impl_buyback_object_type)
|
(impl_buyback_object_type)
|
||||||
|
(impl_fba_accumulator_object_type)
|
||||||
)
|
)
|
||||||
|
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::share_type )
|
FC_REFLECT_TYPENAME( graphene::chain::share_type )
|
||||||
|
|
@ -384,6 +388,9 @@ FC_REFLECT_TYPENAME( graphene::chain::block_summary_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::account_transaction_history_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::account_transaction_history_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::budget_record_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::budget_record_id_type )
|
||||||
FC_REFLECT_TYPENAME( graphene::chain::special_authority_id_type )
|
FC_REFLECT_TYPENAME( graphene::chain::special_authority_id_type )
|
||||||
|
FC_REFLECT_TYPENAME( graphene::chain::buyback_id_type )
|
||||||
|
FC_REFLECT_TYPENAME( graphene::chain::fba_accumulator_id_type )
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::void_t, )
|
FC_REFLECT( graphene::chain::void_t, )
|
||||||
|
|
||||||
FC_REFLECT_ENUM( graphene::chain::asset_issuer_permission_flags,
|
FC_REFLECT_ENUM( graphene::chain::asset_issuer_permission_flags,
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,11 @@ struct vote_counter
|
||||||
out_auth = auth;
|
out_auth = auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_empty()const
|
||||||
|
{
|
||||||
|
return (total_votes == 0);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t last_votes = std::numeric_limits<uint64_t>::max();
|
uint64_t last_votes = std::numeric_limits<uint64_t>::max();
|
||||||
uint64_t total_votes = 0;
|
uint64_t total_votes = 0;
|
||||||
int8_t bitshift = -1;
|
int8_t bitshift = -1;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue