Refactored chain library
- remove circular dependency with fee_schedule - unitiy build db_* as database.cpp - move protocol definitions in separate directory - combined some objects/evaluators - combined limit/call evaluator/objects into market_evaluator.*
This commit is contained in:
parent
90e04d0290
commit
baf5531238
103 changed files with 3440 additions and 3648 deletions
|
|
@ -2,19 +2,28 @@ file(GLOB HEADERS "include/graphene/chain/*.hpp")
|
|||
|
||||
## SORT .cpp by most likely to change / break compile
|
||||
add_library( graphene_chain
|
||||
types.cpp
|
||||
type_id.cpp
|
||||
protocol/types.cpp
|
||||
protocol/address.cpp
|
||||
protocol/asset.cpp
|
||||
protocol/account.cpp
|
||||
protocol/transfer.cpp
|
||||
protocol/delegate.cpp
|
||||
protocol/witness.cpp
|
||||
protocol/market.cpp
|
||||
protocol/proposal.cpp
|
||||
protocol/withdraw_permission.cpp
|
||||
protocol/asset_ops.cpp
|
||||
protocol/memo.cpp
|
||||
protocol/worker.cpp
|
||||
protocol/custom.cpp
|
||||
protocol/operations.cpp
|
||||
protocol/transaction.cpp
|
||||
protocol/block.cpp
|
||||
|
||||
address.cpp
|
||||
pts_address.cpp
|
||||
asset.cpp
|
||||
predicate.cpp
|
||||
|
||||
operations.cpp
|
||||
|
||||
evaluator.cpp
|
||||
balance_evaluator.cpp
|
||||
global_parameters_evaluator.cpp
|
||||
account_evaluator.cpp
|
||||
assert_evaluator.cpp
|
||||
witness_evaluator.cpp
|
||||
|
|
@ -22,8 +31,7 @@ add_library( graphene_chain
|
|||
asset_evaluator.cpp
|
||||
transfer_evaluator.cpp
|
||||
proposal_evaluator.cpp
|
||||
call_order_evaluator.cpp
|
||||
limit_order_evaluator.cpp
|
||||
market_evaluator.cpp
|
||||
vesting_balance_evaluator.cpp
|
||||
withdraw_permission_evaluator.cpp
|
||||
worker_evaluator.cpp
|
||||
|
|
@ -32,25 +40,23 @@ add_library( graphene_chain
|
|||
asset_object.cpp
|
||||
proposal_object.cpp
|
||||
vesting_balance_object.cpp
|
||||
worker_object.cpp
|
||||
|
||||
transaction.cpp
|
||||
block.cpp
|
||||
|
||||
transaction_evaluation_state.cpp
|
||||
fork_database.cpp
|
||||
block_database.cpp
|
||||
|
||||
db_balance.cpp
|
||||
db_block.cpp
|
||||
db_debug.cpp
|
||||
db_getter.cpp
|
||||
db_init.cpp
|
||||
db_maint.cpp
|
||||
db_management.cpp
|
||||
db_market.cpp
|
||||
db_update.cpp
|
||||
db_witness_schedule.cpp
|
||||
database.cpp
|
||||
|
||||
# db_balance.cpp
|
||||
# db_block.cpp
|
||||
# db_debug.cpp
|
||||
# db_getter.cpp
|
||||
# db_init.cpp
|
||||
# db_maint.cpp
|
||||
# db_management.cpp
|
||||
# db_market.cpp
|
||||
# db_update.cpp
|
||||
# db_witness_schedule.cpp
|
||||
|
||||
${HEADERS}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -87,11 +87,14 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
|
|||
db().modify(dynamic_properties, [](dynamic_global_property_object& p) {
|
||||
++p.accounts_registered_this_interval;
|
||||
});
|
||||
|
||||
/** TODO: update fee scaling for account creation...
|
||||
if( dynamic_properties.accounts_registered_this_interval %
|
||||
global_properties.parameters.accounts_per_fee_scale == 0 )
|
||||
db().modify(global_properties, [&dynamic_properties](global_property_object& p) {
|
||||
p.parameters.current_fees.account_create_fee <<= p.parameters.account_fee_scale_bitshifts;
|
||||
});
|
||||
*/
|
||||
|
||||
return new_acnt_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW((o)) }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include <graphene/chain/assert_evaluator.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/predicate.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
|
@ -26,15 +25,18 @@ namespace graphene { namespace chain {
|
|||
|
||||
struct predicate_evaluator
|
||||
{
|
||||
typedef bool result_type;
|
||||
typedef void result_type;
|
||||
const database& db;
|
||||
|
||||
predicate_evaluator( const database& d ):db(d){}
|
||||
|
||||
template< typename T >
|
||||
bool operator()( const T& p )const
|
||||
void operator()( const account_name_eq_lit_predicate& p )const
|
||||
{
|
||||
return p.evaluate( db );
|
||||
FC_ASSERT( p.account_id(db).name == p.name );
|
||||
}
|
||||
void operator()( const asset_symbol_eq_lit_predicate& p )const
|
||||
{
|
||||
FC_ASSERT( p.asset_id(db).symbol == p.symbol );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -47,20 +49,11 @@ void_result assert_evaluator::do_evaluate( const assert_operation& o )
|
|||
if( skip & database::skip_assert_evaluation )
|
||||
return void_result();
|
||||
|
||||
for( const vector<char>& pdata : o.predicates )
|
||||
for( const auto& p : o.predicates )
|
||||
{
|
||||
fc::datastream<const char*> ds( pdata.data(), pdata.size() );
|
||||
predicate p;
|
||||
//
|
||||
// FC_ASSERT deep in the bowels of static_variant implementation
|
||||
// will trip if we get a predicate which isn't in our code's
|
||||
// static_variant. This is desired behavior.
|
||||
//
|
||||
fc::raw::unpack( ds, p );
|
||||
|
||||
FC_ASSERT( p.which() >= 0 );
|
||||
FC_ASSERT( unsigned(p.which()) < max_predicate_opcode );
|
||||
FC_ASSERT( p.visit( predicate_evaluator( _db ) ) );
|
||||
p.visit( predicate_evaluator( _db ) );
|
||||
}
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include <graphene/chain/asset_evaluator.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/call_order_object.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
|
@ -42,8 +42,7 @@ void_result asset_create_evaluator::do_evaluate( const asset_create_operation& o
|
|||
auto asset_symbol_itr = asset_indx.find( op.symbol );
|
||||
FC_ASSERT( asset_symbol_itr == asset_indx.end() );
|
||||
|
||||
core_fee_paid -= op.calculate_fee(d.current_fee_schedule()).value/2;
|
||||
assert( core_fee_paid >= 0 );
|
||||
core_fee_paid -= core_fee_paid.value/2;
|
||||
|
||||
if( op.bitasset_options )
|
||||
{
|
||||
|
|
@ -76,7 +75,7 @@ object_id_type asset_create_evaluator::do_apply( const asset_create_operation& o
|
|||
const asset_dynamic_data_object& dyn_asset =
|
||||
db().create<asset_dynamic_data_object>( [&]( asset_dynamic_data_object& a ) {
|
||||
a.current_supply = 0;
|
||||
a.fee_pool = op.calculate_fee(db().current_fee_schedule()).value / 2;
|
||||
a.fee_pool = core_fee_paid; //op.calculate_fee(db().current_fee_schedule()).value / 2;
|
||||
});
|
||||
|
||||
asset_bitasset_data_id_type bit_asset_id;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
*/
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
|
|
@ -83,40 +82,7 @@ void graphene::chain::asset_bitasset_data_object::update_median_feeds(time_point
|
|||
current_feed = median_feed;
|
||||
}
|
||||
|
||||
void asset_object::asset_options::validate()const
|
||||
{
|
||||
FC_ASSERT( max_supply > 0 );
|
||||
FC_ASSERT( max_supply <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
FC_ASSERT( market_fee_percent <= GRAPHENE_100_PERCENT );
|
||||
FC_ASSERT( max_market_fee >= 0 && max_market_fee <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
// There must be no high bits in permissions whose meaning is not known.
|
||||
FC_ASSERT( !(issuer_permissions & ~ASSET_ISSUER_PERMISSION_MASK) );
|
||||
// There must be no high bits in flags which are not also high in permissions.
|
||||
FC_ASSERT( !(flags & ~issuer_permissions ) );
|
||||
// The global_settle flag may never be set (this is a permission only)
|
||||
FC_ASSERT( !(flags & global_settle) );
|
||||
core_exchange_rate.validate();
|
||||
FC_ASSERT( core_exchange_rate.base.asset_id.instance.value == 0 ||
|
||||
core_exchange_rate.quote.asset_id.instance.value == 0 );
|
||||
|
||||
if(!whitelist_authorities.empty() || !blacklist_authorities.empty())
|
||||
FC_ASSERT( flags & white_list );
|
||||
for( auto item : whitelist_markets )
|
||||
{
|
||||
FC_ASSERT( blacklist_markets.find(item) == blacklist_markets.end() );
|
||||
}
|
||||
for( auto item : blacklist_markets )
|
||||
{
|
||||
FC_ASSERT( whitelist_markets.find(item) == whitelist_markets.end() );
|
||||
}
|
||||
}
|
||||
|
||||
void asset_object::bitasset_options::validate() const
|
||||
{
|
||||
FC_ASSERT(minimum_feeds > 0);
|
||||
FC_ASSERT(force_settlement_offset_percent <= GRAPHENE_100_PERCENT);
|
||||
FC_ASSERT(maximum_force_settlement_volume <= GRAPHENE_100_PERCENT);
|
||||
}
|
||||
|
||||
asset asset_object::amount_from_string(string amount_string) const
|
||||
{ try {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/block_database.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
11
libraries/chain/database.cpp
Normal file
11
libraries/chain/database.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/// This file combines these sources to perform a partial unity build
|
||||
#include "db_balance.cpp"
|
||||
#include "db_block.cpp"
|
||||
#include "db_debug.cpp"
|
||||
#include "db_getter.cpp"
|
||||
#include "db_init.cpp"
|
||||
#include "db_maint.cpp"
|
||||
#include "db_management.cpp"
|
||||
#include "db_market.cpp"
|
||||
#include "db_update.cpp"
|
||||
#include "db_witness_schedule.cpp"
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/transaction_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@
|
|||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <graphene/chain/call_order_object.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const dynamic_global_property_object&database::get_dynamic_global_properties() c
|
|||
return get( dynamic_global_property_id_type() );
|
||||
}
|
||||
|
||||
const fee_schedule_type& database::current_fee_schedule()const
|
||||
const fee_schedule& database::current_fee_schedule()const
|
||||
{
|
||||
return get_global_properties().parameters.current_fees;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,25 +24,20 @@
|
|||
#include <graphene/chain/delegate_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/balance_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/call_order_object.hpp>
|
||||
#include <graphene/chain/transaction_object.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/witness_schedule_object.hpp>
|
||||
#include <graphene/chain/worker_object.hpp>
|
||||
|
||||
#include <graphene/chain/account_evaluator.hpp>
|
||||
#include <graphene/chain/asset_evaluator.hpp>
|
||||
#include <graphene/chain/assert_evaluator.hpp>
|
||||
#include <graphene/chain/custom_evaluator.hpp>
|
||||
#include <graphene/chain/delegate_evaluator.hpp>
|
||||
#include <graphene/chain/global_parameters_evaluator.hpp>
|
||||
#include <graphene/chain/limit_order_evaluator.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/proposal_evaluator.hpp>
|
||||
#include <graphene/chain/call_order_evaluator.hpp>
|
||||
#include <graphene/chain/transfer_evaluator.hpp>
|
||||
#include <graphene/chain/vesting_balance_evaluator.hpp>
|
||||
#include <graphene/chain/withdraw_permission_evaluator.hpp>
|
||||
|
|
@ -50,6 +45,8 @@
|
|||
#include <graphene/chain/worker_evaluator.hpp>
|
||||
#include <graphene/chain/balance_evaluator.hpp>
|
||||
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
#include <fc/uint128.hpp>
|
||||
#include <fc/crypto/digest.hpp>
|
||||
|
||||
|
|
@ -57,6 +54,64 @@
|
|||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
// C++ requires that static class variables declared and initialized
|
||||
// in headers must also have a definition in a single source file,
|
||||
// else linker errors will occur [1].
|
||||
//
|
||||
// The purpose of this source file is to collect such definitions in
|
||||
// a single place.
|
||||
//
|
||||
// [1] http://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char
|
||||
|
||||
const uint8_t account_object::space_id;
|
||||
const uint8_t account_object::type_id;
|
||||
|
||||
const uint8_t asset_object::space_id;
|
||||
const uint8_t asset_object::type_id;
|
||||
|
||||
const uint8_t block_summary_object::space_id;
|
||||
const uint8_t block_summary_object::type_id;
|
||||
|
||||
const uint8_t call_order_object::space_id;
|
||||
const uint8_t call_order_object::type_id;
|
||||
|
||||
const uint8_t delegate_object::space_id;
|
||||
const uint8_t delegate_object::type_id;
|
||||
|
||||
const uint8_t force_settlement_object::space_id;
|
||||
const uint8_t force_settlement_object::type_id;
|
||||
|
||||
const uint8_t global_property_object::space_id;
|
||||
const uint8_t global_property_object::type_id;
|
||||
|
||||
const uint8_t limit_order_object::space_id;
|
||||
const uint8_t limit_order_object::type_id;
|
||||
|
||||
const uint8_t operation_history_object::space_id;
|
||||
const uint8_t operation_history_object::type_id;
|
||||
|
||||
const uint8_t proposal_object::space_id;
|
||||
const uint8_t proposal_object::type_id;
|
||||
|
||||
const uint8_t transaction_object::space_id;
|
||||
const uint8_t transaction_object::type_id;
|
||||
|
||||
const uint8_t vesting_balance_object::space_id;
|
||||
const uint8_t vesting_balance_object::type_id;
|
||||
|
||||
const uint8_t withdraw_permission_object::space_id;
|
||||
const uint8_t withdraw_permission_object::type_id;
|
||||
|
||||
const uint8_t witness_object::space_id;
|
||||
const uint8_t witness_object::type_id;
|
||||
|
||||
const uint8_t witness_schedule_object::space_id;
|
||||
const uint8_t witness_schedule_object::type_id;
|
||||
|
||||
const uint8_t worker_object::space_id;
|
||||
const uint8_t worker_object::type_id;
|
||||
|
||||
|
||||
void database::initialize_evaluators()
|
||||
{
|
||||
_operation_evaluators.resize(255);
|
||||
|
|
@ -65,6 +120,7 @@ void database::initialize_evaluators()
|
|||
register_evaluator<account_upgrade_evaluator>();
|
||||
register_evaluator<account_whitelist_evaluator>();
|
||||
register_evaluator<delegate_create_evaluator>();
|
||||
register_evaluator<delegate_update_global_parameters_evaluator>();
|
||||
register_evaluator<custom_evaluator>();
|
||||
register_evaluator<asset_create_evaluator>();
|
||||
register_evaluator<asset_issue_evaluator>();
|
||||
|
|
@ -85,7 +141,6 @@ void database::initialize_evaluators()
|
|||
register_evaluator<proposal_create_evaluator>();
|
||||
register_evaluator<proposal_update_evaluator>();
|
||||
register_evaluator<proposal_delete_evaluator>();
|
||||
register_evaluator<global_parameters_update_evaluator>();
|
||||
register_evaluator<witness_create_evaluator>();
|
||||
register_evaluator<witness_withdraw_pay_evaluator>();
|
||||
register_evaluator<vesting_balance_create_evaluator>();
|
||||
|
|
@ -242,7 +297,7 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
|||
p.parameters = genesis_state.initial_parameters;
|
||||
// Set fees to zero initially, so that genesis initialization needs not pay them
|
||||
// We'll fix it at the end of the function
|
||||
p.parameters.current_fees.set_all_fees(0);
|
||||
p.parameters.current_fees->set_all_fees(0);
|
||||
|
||||
});
|
||||
create<dynamic_global_property_object>( [&](dynamic_global_property_object& p) {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/witness_schedule_object.hpp>
|
||||
#include <graphene/chain/worker_object.hpp>
|
||||
#include <graphene/chain/worker_evaluator.hpp>
|
||||
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
|
|
@ -59,6 +59,25 @@ void database::perform_account_maintenance(std::tuple<Types...> helpers)
|
|||
detail::for_each(helpers, a, detail::gen_seq<sizeof...(Types)>());
|
||||
}
|
||||
|
||||
/// @brief A visitor for @ref worker_type which calls pay_worker on the worker within
|
||||
struct worker_pay_visitor
|
||||
{
|
||||
private:
|
||||
share_type pay;
|
||||
database& db;
|
||||
|
||||
public:
|
||||
worker_pay_visitor(share_type pay, database& db)
|
||||
: pay(pay), db(db) {}
|
||||
|
||||
typedef void result_type;
|
||||
template<typename W>
|
||||
void operator()(W& worker)const
|
||||
{
|
||||
worker.pay_worker(pay, db);
|
||||
}
|
||||
};
|
||||
|
||||
void database::pay_workers( share_type& budget )
|
||||
{
|
||||
// ilog("Processing payroll! Available budget is ${b}", ("b", budget));
|
||||
|
|
@ -436,9 +455,12 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
|
||||
modify(gpo, [this](global_property_object& p) {
|
||||
// Remove scaling of account registration fee
|
||||
/*
|
||||
/// TODO reimplement this
|
||||
const auto& dgpo = get_dynamic_global_properties();
|
||||
p.parameters.current_fees.account_create_fee >>= p.parameters.account_fee_scale_bitshifts *
|
||||
(dgpo.accounts_registered_this_interval / p.parameters.accounts_per_fee_scale);
|
||||
*/
|
||||
|
||||
if( p.pending_parameters )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <graphene/chain/database.hpp>
|
||||
|
||||
#include <graphene/chain/operation_history_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@
|
|||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <graphene/chain/call_order_object.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
|
|
@ -248,7 +247,7 @@ bool database::fill_order( const limit_order_object& order, const asset& pays, c
|
|||
pay_order( seller, receives - issuer_fees, pays );
|
||||
|
||||
assert( pays.asset_id != receives.asset_id );
|
||||
push_applied_operation( fill_order_operation{ order.id, order.seller, pays, receives, issuer_fees } );
|
||||
push_applied_operation( fill_order_operation( order.id, order.seller, pays, receives, issuer_fees ) );
|
||||
|
||||
if( pays == order.amount_for_sale() )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@
|
|||
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/call_order_object.hpp>
|
||||
#include <graphene/chain/transaction_object.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/withdraw_permission_object.hpp>
|
||||
#include <graphene/chain/witness_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#include <graphene/chain/delegate_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <graphene/chain/transaction_evaluation_state.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -43,4 +45,22 @@ object_id_type delegate_create_evaluator::do_apply( const delegate_create_operat
|
|||
return new_del_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
|
||||
|
||||
void_result delegate_update_global_parameters_evaluator::do_evaluate(const delegate_update_global_parameters_operation& o)
|
||||
{ try {
|
||||
FC_ASSERT(trx_state->_is_proposed_trx);
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
void_result delegate_update_global_parameters_evaluator::do_apply(const delegate_update_global_parameters_operation& o)
|
||||
{ try {
|
||||
db().modify(db().get_global_properties(), [&o](global_property_object& p) {
|
||||
p.pending_parameters = o.new_parameters;
|
||||
});
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/delegate_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <graphene/chain/call_order_object.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
|
|
@ -85,9 +85,7 @@ database& generic_evaluator::db()const { return trx_state->db(); }
|
|||
flat_set<account_id_type> owner_auths;
|
||||
vector<authority> other_auths;
|
||||
|
||||
operation_get_required_active_authorities( op, active_auths );
|
||||
operation_get_required_owner_authorities( op, owner_auths );
|
||||
operation_get_required_authorities( op, other_auths );
|
||||
operation_get_required_authorities( op, active_auths, owner_auths, other_auths );
|
||||
|
||||
for( auto id : active_auths )
|
||||
FC_ASSERT(verify_authority(id(db()), authority::active) ||
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/global_parameters_evaluator.hpp>
|
||||
#include <graphene/chain/transaction_evaluation_state.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void_result global_parameters_update_evaluator::do_evaluate(const global_parameters_update_operation& o)
|
||||
{ try {
|
||||
FC_ASSERT(trx_state->_is_proposed_trx);
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
void_result global_parameters_update_evaluator::do_apply(const global_parameters_update_operation& o)
|
||||
{ try {
|
||||
db().modify(db().get_global_properties(), [&o](global_property_object& p) {
|
||||
p.pending_parameters = o.new_parameters;
|
||||
});
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -16,14 +16,12 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
class database;
|
||||
class database;
|
||||
|
||||
/**
|
||||
* @class account_statistics_object
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/asset_ops.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/db/flat_index.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
|
|
@ -116,86 +116,8 @@ namespace graphene { namespace chain {
|
|||
/// ID of the account which issued this asset.
|
||||
account_id_type issuer;
|
||||
|
||||
/**
|
||||
* @brief The asset_options struct contains options available on all assets in the network
|
||||
*
|
||||
* @note Changes to this struct will break protocol compatibility
|
||||
*/
|
||||
struct asset_options {
|
||||
/// The maximum supply of this asset which may exist at any given time. This can be as large as
|
||||
/// GRAPHENE_MAX_SHARE_SUPPLY
|
||||
share_type max_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
/// When this asset is traded on the markets, this percentage of the total traded will be exacted and paid
|
||||
/// to the issuer. This is a fixed point value, representing hundredths of a percent, i.e. a value of 100
|
||||
/// in this field means a 1% fee is charged on market trades of this asset.
|
||||
uint16_t market_fee_percent = 0;
|
||||
/// Market fees calculated as @ref market_fee_percent of the traded volume are capped to this value
|
||||
share_type max_market_fee = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
asset_options options;
|
||||
|
||||
/// The flags which the issuer has permission to update. See @ref asset_issuer_permission_flags
|
||||
uint16_t issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
|
||||
/// The currently active flags on this permission. See @ref asset_issuer_permission_flags
|
||||
uint16_t flags = 0;
|
||||
|
||||
/// When a non-core asset is used to pay a fee, the blockchain must convert that asset to core asset in
|
||||
/// order to accept the fee. If this asset's fee pool is funded, the chain will automatically deposite fees
|
||||
/// in this asset to its accumulated fees, and withdraw from the fee pool the same amount as converted at
|
||||
/// the core exchange rate.
|
||||
price core_exchange_rate;
|
||||
|
||||
/// A set of accounts which maintain whitelists to consult for this asset. If enforce_white_list() returns
|
||||
/// true, an account may only send, receive, trade, etc. in this asset if one of these accounts appears in
|
||||
/// its account_object::whitelisting_accounts field.
|
||||
flat_set<account_id_type> whitelist_authorities;
|
||||
/// A set of accounts which maintain blacklists to consult for this asset. If enforce_white_list() returns
|
||||
/// true, an account may only send, receive, trade, etc. in this asset if none of these accounts appears in
|
||||
/// its account_object::blacklisting_accounts field. If the account is blacklisted, it may not transact in
|
||||
/// this asset even if it is also whitelisted.
|
||||
flat_set<account_id_type> blacklist_authorities;
|
||||
|
||||
/** defines the assets that this asset may be traded against in the market */
|
||||
flat_set<asset_id_type> whitelist_markets;
|
||||
/** defines the assets that this asset may not be traded against in the market, must not overlap whitelist */
|
||||
flat_set<asset_id_type> blacklist_markets;
|
||||
|
||||
/**
|
||||
* data that describes the meaning/purpose of this asset, fee will be charged proportional to
|
||||
* size of description.
|
||||
*/
|
||||
string description;
|
||||
|
||||
/// Perform internal consistency checks.
|
||||
/// @throws fc::exception if any check fails
|
||||
void validate()const;
|
||||
} options;
|
||||
/**
|
||||
* @brief The bitasset_options struct contains configurable options available only to BitAssets.
|
||||
*
|
||||
* @note Changes to this struct will break protocol compatibility
|
||||
*/
|
||||
struct bitasset_options {
|
||||
/// Time before a price feed expires
|
||||
uint32_t feed_lifetime_sec = GRAPHENE_DEFAULT_PRICE_FEED_LIFETIME;
|
||||
/// Minimum number of unexpired feeds required to extract a median feed from
|
||||
uint8_t minimum_feeds = 1;
|
||||
/// This is the delay between the time a long requests settlement and the chain evaluates the settlement
|
||||
uint32_t force_settlement_delay_sec = GRAPHENE_DEFAULT_FORCE_SETTLEMENT_DELAY;
|
||||
/// This is the percent to adjust the feed price in the short's favor in the event of a forced settlement
|
||||
uint16_t force_settlement_offset_percent = GRAPHENE_DEFAULT_FORCE_SETTLEMENT_OFFSET;
|
||||
/// Force settlement volume can be limited such that only a certain percentage of the total existing supply
|
||||
/// of the asset may be force-settled within any given chain maintenance interval. This field stores the
|
||||
/// percentage of the current supply which may be force settled within the current maintenance interval. If
|
||||
/// force settlements come due in an interval in which the maximum volume has already been settled, the new
|
||||
/// settlements will be enqueued and processed at the beginning of the next maintenance interval.
|
||||
uint16_t maximum_force_settlement_volume = GRAPHENE_DEFAULT_FORCE_SETTLEMENT_MAX_VOLUME;
|
||||
/// This speicifies which asset type is used to collateralize short sales
|
||||
/// This field may only be updated if the current supply of the asset is zero.
|
||||
asset_id_type short_backing_asset;
|
||||
|
||||
/// Perform internal consistency checks.
|
||||
/// @throws fc::exception if any check fails
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/// Current supply, fee pool, and collected fees are stored in a separate object as they change frequently.
|
||||
asset_dynamic_data_id_type dynamic_asset_data_id;
|
||||
|
|
@ -243,7 +165,7 @@ namespace graphene { namespace chain {
|
|||
static const uint8_t type_id = impl_asset_bitasset_data_type;
|
||||
|
||||
/// The tunable options for BitAssets are stored in this field.
|
||||
asset_object::bitasset_options options;
|
||||
bitasset_options options;
|
||||
|
||||
/// Feeds published for this asset. If issuer is not genesis, the keys in this map are the feed publishing
|
||||
/// accounts; otherwise, the feed publishers are the currently active delegates and witnesses and this map
|
||||
|
|
@ -325,28 +247,6 @@ FC_REFLECT_DERIVED( graphene::chain::asset_bitasset_data_object, (graphene::db::
|
|||
(settlement_fund)
|
||||
)
|
||||
|
||||
FC_REFLECT( graphene::chain::asset_object::asset_options,
|
||||
(max_supply)
|
||||
(market_fee_percent)
|
||||
(max_market_fee)
|
||||
(issuer_permissions)
|
||||
(flags)
|
||||
(core_exchange_rate)
|
||||
(whitelist_authorities)
|
||||
(blacklist_authorities)
|
||||
(whitelist_markets)
|
||||
(blacklist_markets)
|
||||
(description)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::asset_object::bitasset_options,
|
||||
(feed_lifetime_sec)
|
||||
(minimum_feeds)
|
||||
(force_settlement_delay_sec)
|
||||
(force_settlement_offset_percent)
|
||||
(maximum_force_settlement_volume)
|
||||
(short_backing_asset)
|
||||
)
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::asset_object,
|
||||
(graphene::db::annotated_object<graphene::chain::asset_object>),
|
||||
(symbol)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/transaction.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/transaction.hpp>
|
||||
#include <graphene/chain/balance_object.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include <graphene/chain/block.hpp>
|
||||
#include <graphene/chain/protocol/block.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
class block_database
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class call_order_update_evaluator : public evaluator<call_order_update_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef call_order_update_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const call_order_update_operation& o );
|
||||
void_result do_apply( const call_order_update_operation& o );
|
||||
|
||||
bool _closing_order = false;
|
||||
const asset_object* _debt_asset = nullptr;
|
||||
const account_object* _paying_account = nullptr;
|
||||
const call_order_object* _order = nullptr;
|
||||
const asset_bitasset_data_object* _bitasset_data = nullptr;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/block.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/chain/protocol/block.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/node_property_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
|
|
@ -227,7 +226,7 @@ namespace graphene { namespace chain {
|
|||
const global_property_object& get_global_properties()const;
|
||||
const dynamic_global_property_object& get_dynamic_global_properties()const;
|
||||
const node_property_object& get_node_properties()const;
|
||||
const fee_schedule_type& current_fee_schedule()const;
|
||||
const fee_schedule& current_fee_schedule()const;
|
||||
|
||||
time_point_sec head_block_time()const;
|
||||
uint32_t head_block_num()const;
|
||||
|
|
|
|||
|
|
@ -30,4 +30,14 @@ namespace graphene { namespace chain {
|
|||
object_id_type do_apply( const delegate_create_operation& o );
|
||||
};
|
||||
|
||||
class delegate_update_global_parameters_evaluator : public evaluator<delegate_update_global_parameters_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef delegate_update_global_parameters_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const delegate_update_global_parameters_operation& o );
|
||||
void_result do_apply( const delegate_update_global_parameters_operation& o );
|
||||
};
|
||||
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -194,7 +193,7 @@ namespace graphene { namespace chain {
|
|||
const auto& op = o.get<typename DerivedEvaluator::operation_type>();
|
||||
|
||||
prepare_fee(op.fee_payer(), op.fee);
|
||||
FC_ASSERT( core_fee_paid >= op.calculate_fee(db().current_fee_schedule()) );
|
||||
FC_ASSERT( core_fee_paid >= db().current_fee_schedule().calculate_fee( op ).amount );
|
||||
|
||||
return eval->do_evaluate(op);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/block.hpp>
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/protocol/block.hpp>
|
||||
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class global_parameters_update_evaluator : public evaluator<global_parameters_update_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef global_parameters_update_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const global_parameters_update_operation& o );
|
||||
void_result do_apply( const global_parameters_update_operation& o );
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -16,10 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/chain_parameters.hpp>
|
||||
#include <graphene/chain/protocol/chain_parameters.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
|
|||
|
|
@ -22,31 +22,5 @@
|
|||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class limit_order_create_evaluator : public evaluator<limit_order_create_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef limit_order_create_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const limit_order_create_operation& o );
|
||||
object_id_type do_apply( const limit_order_create_operation& o );
|
||||
|
||||
asset calculate_market_fee( const asset_object* aobj, const asset& trade_amount );
|
||||
|
||||
const limit_order_create_operation* _op = nullptr;
|
||||
const account_object* _seller = nullptr;
|
||||
const asset_object* _sell_asset = nullptr;
|
||||
const asset_object* _receive_asset = nullptr;
|
||||
};
|
||||
|
||||
class limit_order_cancel_evaluator : public evaluator<limit_order_cancel_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef limit_order_cancel_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const limit_order_cancel_operation& o );
|
||||
asset do_apply( const limit_order_cancel_operation& o );
|
||||
|
||||
const limit_order_object* _order;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
|
|||
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
||||
/**
|
||||
* @brief an offer to sell a amount of a asset at a specified exchange rate by a certain time
|
||||
* @ingroup object
|
||||
* @ingroup protocol
|
||||
* @ingroup market
|
||||
*
|
||||
* This limit_order_objects are indexed by @ref expiration and is automatically deleted on the first block after expiration.
|
||||
*/
|
||||
class limit_order_object : public abstract_object<limit_order_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = limit_order_object_type;
|
||||
|
||||
time_point_sec expiration;
|
||||
account_id_type seller;
|
||||
share_type for_sale; ///< asset id is sell_price.base.asset_id
|
||||
price sell_price;
|
||||
|
||||
asset amount_for_sale()const { return asset( for_sale, sell_price.base.asset_id ); }
|
||||
asset amount_to_receive()const { return amount_for_sale() * sell_price; }
|
||||
};
|
||||
|
||||
struct by_id;
|
||||
struct by_price;
|
||||
struct by_expiration;
|
||||
typedef multi_index_container<
|
||||
limit_order_object,
|
||||
indexed_by<
|
||||
hashed_unique< tag<by_id>,
|
||||
member< object, object_id_type, &object::id > >,
|
||||
ordered_non_unique< tag<by_expiration>, member< limit_order_object, time_point_sec, &limit_order_object::expiration> >,
|
||||
ordered_unique< tag<by_price>,
|
||||
composite_key< limit_order_object,
|
||||
member< limit_order_object, price, &limit_order_object::sell_price>,
|
||||
member< object, object_id_type, &object::id>
|
||||
>,
|
||||
composite_key_compare< std::greater<price>, std::less<object_id_type> >
|
||||
>
|
||||
>
|
||||
> limit_order_multi_index_type;
|
||||
|
||||
typedef generic_index<limit_order_object, limit_order_multi_index_type> limit_order_index;
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::limit_order_object,
|
||||
(graphene::db::object),
|
||||
(expiration)(seller)(for_sale)(sell_price)
|
||||
)
|
||||
|
||||
|
|
@ -1,30 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* Copyright (c) 2015, Cryptonomex, Inc. All rights reserved. */
|
||||
#pragma once
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <boost/multi_index/composite_key.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
||||
using namespace graphene::db;
|
||||
|
||||
/**
|
||||
* @brief an offer to sell a amount of a asset at a specified exchange rate by a certain time
|
||||
* @ingroup object
|
||||
* @ingroup protocol
|
||||
* @ingroup market
|
||||
*
|
||||
* This limit_order_objects are indexed by @ref expiration and is automatically deleted on the first block after expiration.
|
||||
*/
|
||||
class limit_order_object : public abstract_object<limit_order_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = limit_order_object_type;
|
||||
|
||||
time_point_sec expiration;
|
||||
account_id_type seller;
|
||||
share_type for_sale; ///< asset id is sell_price.base.asset_id
|
||||
price sell_price;
|
||||
|
||||
asset amount_for_sale()const { return asset( for_sale, sell_price.base.asset_id ); }
|
||||
asset amount_to_receive()const { return amount_for_sale() * sell_price; }
|
||||
};
|
||||
|
||||
struct by_id;
|
||||
struct by_price;
|
||||
struct by_expiration;
|
||||
typedef multi_index_container<
|
||||
limit_order_object,
|
||||
indexed_by<
|
||||
hashed_unique< tag<by_id>,
|
||||
member< object, object_id_type, &object::id > >,
|
||||
ordered_non_unique< tag<by_expiration>, member< limit_order_object, time_point_sec, &limit_order_object::expiration> >,
|
||||
ordered_unique< tag<by_price>,
|
||||
composite_key< limit_order_object,
|
||||
member< limit_order_object, price, &limit_order_object::sell_price>,
|
||||
member< object, object_id_type, &object::id>
|
||||
>,
|
||||
composite_key_compare< std::greater<price>, std::less<object_id_type> >
|
||||
>
|
||||
>
|
||||
> limit_order_multi_index_type;
|
||||
|
||||
typedef generic_index<limit_order_object, limit_order_multi_index_type> limit_order_index;
|
||||
|
||||
/**
|
||||
* @class call_order_object
|
||||
|
|
@ -121,8 +147,58 @@ namespace graphene { namespace chain {
|
|||
|
||||
typedef generic_index<call_order_object, call_order_multi_index_type> call_order_index;
|
||||
typedef generic_index<force_settlement_object, force_settlement_object_multi_index_type> force_settlement_index;
|
||||
|
||||
|
||||
|
||||
|
||||
class limit_order_create_evaluator : public evaluator<limit_order_create_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef limit_order_create_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const limit_order_create_operation& o );
|
||||
object_id_type do_apply( const limit_order_create_operation& o );
|
||||
|
||||
asset calculate_market_fee( const asset_object* aobj, const asset& trade_amount );
|
||||
|
||||
const limit_order_create_operation* _op = nullptr;
|
||||
const account_object* _seller = nullptr;
|
||||
const asset_object* _sell_asset = nullptr;
|
||||
const asset_object* _receive_asset = nullptr;
|
||||
};
|
||||
|
||||
class limit_order_cancel_evaluator : public evaluator<limit_order_cancel_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef limit_order_cancel_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const limit_order_cancel_operation& o );
|
||||
asset do_apply( const limit_order_cancel_operation& o );
|
||||
|
||||
const limit_order_object* _order;
|
||||
};
|
||||
|
||||
class call_order_update_evaluator : public evaluator<call_order_update_evaluator>
|
||||
{
|
||||
public:
|
||||
typedef call_order_update_operation operation_type;
|
||||
|
||||
void_result do_evaluate( const call_order_update_operation& o );
|
||||
void_result do_apply( const call_order_update_operation& o );
|
||||
|
||||
bool _closing_order = false;
|
||||
const asset_object* _debt_asset = nullptr;
|
||||
const account_object* _paying_account = nullptr;
|
||||
const call_order_object* _order = nullptr;
|
||||
const asset_bitasset_data_object* _bitasset_data = nullptr;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::limit_order_object,
|
||||
(graphene::db::object),
|
||||
(expiration)(seller)(for_sale)(sell_price)
|
||||
)
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::call_order_object, (graphene::db::object),
|
||||
(borrower)(collateral)(debt)(call_price) )
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/types.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class database;
|
||||
|
||||
namespace pred {
|
||||
|
||||
/**
|
||||
* Used to verify that account_id->name is equal to the given string literal.
|
||||
*/
|
||||
struct account_name_eq_lit
|
||||
{
|
||||
account_id_type account_id;
|
||||
string name;
|
||||
|
||||
/**
|
||||
* Perform state-independent checks. Verify
|
||||
* account_name is a valid account name.
|
||||
*/
|
||||
bool validate()const;
|
||||
|
||||
/**
|
||||
* Evaluate the predicate.
|
||||
*/
|
||||
bool evaluate( const database& db )const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to verify that asset_id->symbol is equal to the given string literal.
|
||||
*/
|
||||
struct asset_symbol_eq_lit
|
||||
{
|
||||
asset_id_type asset_id;
|
||||
string symbol;
|
||||
|
||||
/**
|
||||
* Perform state independent checks. Verify symbol is a
|
||||
* valid asset symbol.
|
||||
*/
|
||||
bool validate()const;
|
||||
|
||||
/**
|
||||
* Evaluate the predicate.
|
||||
*/
|
||||
bool evaluate( const database& db )const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* When defining predicates do not make the protocol dependent upon
|
||||
* implementation details.
|
||||
*/
|
||||
typedef static_variant<
|
||||
pred::account_name_eq_lit,
|
||||
pred::asset_symbol_eq_lit
|
||||
> predicate;
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT( graphene::chain::pred::account_name_eq_lit, (account_id)(name) )
|
||||
FC_REFLECT( graphene::chain::pred::asset_symbol_eq_lit, (asset_id)(symbol) )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::predicate )
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/transaction_evaluation_state.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/transaction.hpp>
|
||||
#include <graphene/chain/protocol/transaction.hpp>
|
||||
#include <graphene/chain/transaction_evaluation_state.hpp>
|
||||
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
|
|
|||
10
libraries/chain/include/graphene/chain/protocol/README.md
Normal file
10
libraries/chain/include/graphene/chain/protocol/README.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
Protocol Definition
|
||||
--------------------
|
||||
|
||||
The classes declared in these headers provide the complete definition of the
|
||||
Graphene protocol and are organized according to feature. Nothing in this
|
||||
directory should depend upon anything other than fc or other types defined
|
||||
in the protocol directory.
|
||||
|
||||
To be more specific, implementation details such as the objects defined in
|
||||
the object database should not be required here.
|
||||
224
libraries/chain/include/graphene/chain/protocol/account.hpp
Normal file
224
libraries/chain/include/graphene/chain/protocol/account.hpp
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
bool is_valid_name( const string& s );
|
||||
bool is_cheap_name( const string& n );
|
||||
|
||||
/// These are the fields which can be updated by the active authority.
|
||||
struct account_options
|
||||
{
|
||||
/// The memo key is the key this account will typically use to encrypt/sign transaction memos and other non-
|
||||
/// validated account activities. This field is here to prevent confusion if the active authority has zero or
|
||||
/// multiple keys in it.
|
||||
public_key_type memo_key;
|
||||
/// If this field is set to an account ID other than 0, this account's votes will be ignored and its stake
|
||||
/// will be counted as voting for the referenced account's selected votes instead.
|
||||
account_id_type voting_account;
|
||||
|
||||
/// The number of active witnesses this account votes the blockchain should appoint
|
||||
/// Must not exceed the actual number of witnesses voted for in @ref votes
|
||||
uint16_t num_witness = 0;
|
||||
/// The number of active committee members this account votes the blockchain should appoint
|
||||
/// Must not exceed the actual number of committee members voted for in @ref votes
|
||||
uint16_t num_committee = 0;
|
||||
/// This is the list of vote IDs this account votes for. The weight of these votes is determined by this
|
||||
/// account's balance of core asset.
|
||||
flat_set<vote_id_type> votes;
|
||||
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*/
|
||||
struct account_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t basic_fee = 5*GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to register the cheapest non-free account
|
||||
uint64_t premium_fee = 2000*GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to register the cheapest non-free account
|
||||
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
/// This account pays the fee. Must be a lifetime member.
|
||||
account_id_type registrar;
|
||||
|
||||
/// This account receives a portion of the fee split between registrar and referrer. Must be a member.
|
||||
account_id_type referrer;
|
||||
/// Of the fee split between registrar and referrer, this percentage goes to the referrer. The rest goes to the
|
||||
/// registrar.
|
||||
uint16_t referrer_percent = 0;
|
||||
|
||||
string name;
|
||||
authority owner;
|
||||
authority active;
|
||||
|
||||
account_options options;
|
||||
|
||||
account_id_type fee_payer()const { return registrar; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& )const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
* @brief Update an existing account
|
||||
*
|
||||
* This operation is used to update an existing account. It can be used to update the authorities, or adjust the options on the account.
|
||||
* See @ref account_object::options_type for the options which may be updated.
|
||||
*/
|
||||
struct account_update_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
share_type fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
/// The account to update
|
||||
account_id_type account;
|
||||
|
||||
/// New owner authority. If set, this operation requires owner authority to execute.
|
||||
optional<authority> owner;
|
||||
/// New active authority. If set, this operation requires owner authority to execute: TODO: why?
|
||||
optional<authority> active;
|
||||
|
||||
/// New account options
|
||||
optional<account_options> new_options;
|
||||
|
||||
account_id_type fee_payer()const { return account; }
|
||||
void validate()const;
|
||||
share_type calculate_fee( const fee_parameters_type& k )const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief This operation is used to whitelist and blacklist accounts, primarily for transacting in whitelisted assets
|
||||
* @ingroup operations
|
||||
*
|
||||
* Accounts can freely specify opinions about other accounts, in the form of either whitelisting or blacklisting
|
||||
* them. This information is used in chain validation only to determine whether an account is authorized to transact
|
||||
* in an asset type which enforces a whitelist, but third parties can use this information for other uses as well,
|
||||
* as long as it does not conflict with the use of whitelisted assets.
|
||||
*
|
||||
* An asset which enforces a whitelist specifies a list of accounts to maintain its whitelist, and a list of
|
||||
* accounts to maintain its blacklist. In order for a given account A to hold and transact in a whitelisted asset S,
|
||||
* A must be whitelisted by at least one of S's whitelist_authorities and blacklisted by none of S's
|
||||
* blacklist_authorities. If A receives a balance of S, and is later removed from the whitelist(s) which allowed it
|
||||
* to hold S, or added to any blacklist S specifies as authoritative, A's balance of S will be frozen until A's
|
||||
* authorization is reinstated.
|
||||
*
|
||||
* This operation requires authorizing_account's signature, but not account_to_list's. The fee is paid by
|
||||
* authorizing_account.
|
||||
*/
|
||||
struct account_whitelist_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { share_type fee = 300000; };
|
||||
enum account_listing {
|
||||
no_listing = 0x0, ///< No opinion is specified about this account
|
||||
white_listed = 0x1, ///< This account is whitelisted, but not blacklisted
|
||||
black_listed = 0x2, ///< This account is blacklisted, but not whitelisted
|
||||
white_and_black_listed = white_listed | black_listed ///< This account is both whitelisted and blacklisted
|
||||
};
|
||||
|
||||
/// Paid by authorizing_account
|
||||
asset fee;
|
||||
/// The account which is specifying an opinion of another account
|
||||
account_id_type authorizing_account;
|
||||
/// The account being opined about
|
||||
account_id_type account_to_list;
|
||||
/// The new white and blacklist status of account_to_list, as determined by authorizing_account
|
||||
/// This is a bitfield using values defined in the account_listing enum
|
||||
uint8_t new_listing;
|
||||
|
||||
account_id_type fee_payer()const { return authorizing_account; }
|
||||
void validate()const { FC_ASSERT( fee.amount >= 0 ); FC_ASSERT(new_listing < 0x4); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Manage an account's membership status
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation is used to upgrade an account to a member, or renew its subscription. If an account which is an
|
||||
* unexpired annual subscription member publishes this operation with @ref upgrade_to_lifetime_member set to false,
|
||||
* the account's membership expiration date will be pushed backward one year. If a basic account publishes it with
|
||||
* @ref upgrade_to_lifetime_member set to false, the account will be upgraded to a subscription member with an
|
||||
* expiration date one year after the processing time of this operation.
|
||||
*
|
||||
* Any account may use this operation to become a lifetime member by setting @ref upgrade_to_lifetime_member to
|
||||
* true. Once an account has become a lifetime member, it may not use this operation anymore.
|
||||
*/
|
||||
struct account_upgrade_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t membership_annual_fee = 2000 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint64_t membership_lifetime_fee = 10000 * GRAPHENE_BLOCKCHAIN_PRECISION; ///< the cost to upgrade to a lifetime member
|
||||
};
|
||||
|
||||
asset fee;
|
||||
/// The account to upgrade; must not already be a lifetime member
|
||||
account_id_type account_to_upgrade;
|
||||
/// If true, the account will be upgraded to a lifetime member; otherwise, it will add a year to the subscription
|
||||
bool upgrade_to_lifetime_member = false;
|
||||
|
||||
account_id_type fee_payer()const { return account_to_upgrade; }
|
||||
void validate()const;
|
||||
share_type calculate_fee( const fee_parameters_type& k )const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief transfers the account to another account while clearing the white list
|
||||
* @ingroup operations
|
||||
*
|
||||
* In theory an account can be transferred by simply updating the authorities, but that kind
|
||||
* of transfer lacks semantic meaning and is more often done to rotate keys without transferring
|
||||
* ownership. This operation is used to indicate the legal transfer of title to this account and
|
||||
* a break in the operation history.
|
||||
*
|
||||
* The account_id's owner/active/voting/memo authority should be set to new_owner
|
||||
*
|
||||
* This operation will clear the account's whitelist statuses, but not the blacklist statuses.
|
||||
*/
|
||||
struct account_transfer_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type account_id;
|
||||
account_id_type new_owner;
|
||||
|
||||
account_id_type fee_payer()const { return account_id; }
|
||||
void validate()const;
|
||||
|
||||
};
|
||||
|
||||
} }
|
||||
FC_REFLECT(graphene::chain::account_options, (memo_key)(voting_account)(num_witness)(num_committee)(votes))
|
||||
FC_REFLECT_TYPENAME( graphene::chain::account_whitelist_operation::account_listing)
|
||||
FC_REFLECT_ENUM( graphene::chain::account_whitelist_operation::account_listing,
|
||||
(no_listing)(white_listed)(black_listed)(white_and_black_listed))
|
||||
|
||||
FC_REFLECT( graphene::chain::account_create_operation,
|
||||
(fee)(registrar)
|
||||
(referrer)(referrer_percent)
|
||||
(name)(owner)(active)(options)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::account_update_operation,
|
||||
(fee)(account)(owner)(active)(new_options)
|
||||
)
|
||||
|
||||
FC_REFLECT( graphene::chain::account_upgrade_operation,
|
||||
(fee)(account_to_upgrade)(upgrade_to_lifetime_member) )
|
||||
|
||||
FC_REFLECT( graphene::chain::account_whitelist_operation, (fee)(authorizing_account)(account_to_list)(new_listing))
|
||||
|
||||
FC_REFLECT( graphene::chain::account_create_operation::fee_parameters_type, (basic_fee)(premium_fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::account_whitelist_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::account_update_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::account_upgrade_operation::fee_parameters_type, (membership_annual_fee)(membership_lifetime_fee) )
|
||||
FC_REFLECT( graphene::chain::account_transfer_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::account_transfer_operation, (fee)(account_id)(new_owner) )
|
||||
73
libraries/chain/include/graphene/chain/protocol/assert.hpp
Normal file
73
libraries/chain/include/graphene/chain/protocol/assert.hpp
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* Used to verify that account_id->name is equal to the given string literal.
|
||||
*/
|
||||
struct account_name_eq_lit_predicate
|
||||
{
|
||||
account_id_type account_id;
|
||||
string name;
|
||||
|
||||
/**
|
||||
* Perform state-independent checks. Verify
|
||||
* account_name is a valid account name.
|
||||
*/
|
||||
bool validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to verify that asset_id->symbol is equal to the given string literal.
|
||||
*/
|
||||
struct asset_symbol_eq_lit_predicate
|
||||
{
|
||||
asset_id_type asset_id;
|
||||
string symbol;
|
||||
|
||||
/**
|
||||
* Perform state independent checks. Verify symbol is a
|
||||
* valid asset symbol.
|
||||
*/
|
||||
bool validate()const;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* When defining predicates do not make the protocol dependent upon
|
||||
* implementation details.
|
||||
*/
|
||||
typedef static_variant<
|
||||
account_name_eq_lit_predicate,
|
||||
asset_symbol_eq_lit_predicate
|
||||
> predicate;
|
||||
|
||||
|
||||
/**
|
||||
* @brief assert that some conditions are true.
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation performs no changes to the database state, but can but used to verify
|
||||
* pre or post conditions for other operations.
|
||||
*/
|
||||
struct assert_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { share_type fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type fee_paying_account;
|
||||
vector<predicate> predicates;
|
||||
flat_set<account_id_type> required_auths;
|
||||
|
||||
account_id_type fee_payer()const { return fee_paying_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::assert_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::account_name_eq_lit_predicate, (account_id)(name) )
|
||||
FC_REFLECT( graphene::chain::asset_symbol_eq_lit_predicate, (asset_id)(symbol) )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::predicate )
|
||||
FC_REFLECT( graphene::chain::assert_operation, (fee)(fee_paying_account)(predicates)(required_auths) )
|
||||
|
|
@ -16,8 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/config.hpp>
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/protocol/config.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
444
libraries/chain/include/graphene/chain/protocol/asset_ops.hpp
Normal file
444
libraries/chain/include/graphene/chain/protocol/asset_ops.hpp
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/memo.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
bool is_valid_symbol( const string& symbol );
|
||||
|
||||
/**
|
||||
* @brief The asset_options struct contains options available on all assets in the network
|
||||
*
|
||||
* @note Changes to this struct will break protocol compatibility
|
||||
*/
|
||||
struct asset_options {
|
||||
/// The maximum supply of this asset which may exist at any given time. This can be as large as
|
||||
/// GRAPHENE_MAX_SHARE_SUPPLY
|
||||
share_type max_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
/// When this asset is traded on the markets, this percentage of the total traded will be exacted and paid
|
||||
/// to the issuer. This is a fixed point value, representing hundredths of a percent, i.e. a value of 100
|
||||
/// in this field means a 1% fee is charged on market trades of this asset.
|
||||
uint16_t market_fee_percent = 0;
|
||||
/// Market fees calculated as @ref market_fee_percent of the traded volume are capped to this value
|
||||
share_type max_market_fee = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
|
||||
/// The flags which the issuer has permission to update. See @ref asset_issuer_permission_flags
|
||||
uint16_t issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
|
||||
/// The currently active flags on this permission. See @ref asset_issuer_permission_flags
|
||||
uint16_t flags = 0;
|
||||
|
||||
/// When a non-core asset is used to pay a fee, the blockchain must convert that asset to core asset in
|
||||
/// order to accept the fee. If this asset's fee pool is funded, the chain will automatically deposite fees
|
||||
/// in this asset to its accumulated fees, and withdraw from the fee pool the same amount as converted at
|
||||
/// the core exchange rate.
|
||||
price core_exchange_rate;
|
||||
|
||||
/// A set of accounts which maintain whitelists to consult for this asset. If enforce_white_list() returns
|
||||
/// true, an account may only send, receive, trade, etc. in this asset if one of these accounts appears in
|
||||
/// its account_object::whitelisting_accounts field.
|
||||
flat_set<account_id_type> whitelist_authorities;
|
||||
/// A set of accounts which maintain blacklists to consult for this asset. If enforce_white_list() returns
|
||||
/// true, an account may only send, receive, trade, etc. in this asset if none of these accounts appears in
|
||||
/// its account_object::blacklisting_accounts field. If the account is blacklisted, it may not transact in
|
||||
/// this asset even if it is also whitelisted.
|
||||
flat_set<account_id_type> blacklist_authorities;
|
||||
|
||||
/** defines the assets that this asset may be traded against in the market */
|
||||
flat_set<asset_id_type> whitelist_markets;
|
||||
/** defines the assets that this asset may not be traded against in the market, must not overlap whitelist */
|
||||
flat_set<asset_id_type> blacklist_markets;
|
||||
|
||||
/**
|
||||
* data that describes the meaning/purpose of this asset, fee will be charged proportional to
|
||||
* size of description.
|
||||
*/
|
||||
string description;
|
||||
|
||||
/// Perform internal consistency checks.
|
||||
/// @throws fc::exception if any check fails
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The bitasset_options struct contains configurable options available only to BitAssets.
|
||||
*
|
||||
* @note Changes to this struct will break protocol compatibility
|
||||
*/
|
||||
struct bitasset_options {
|
||||
/// Time before a price feed expires
|
||||
uint32_t feed_lifetime_sec = GRAPHENE_DEFAULT_PRICE_FEED_LIFETIME;
|
||||
/// Minimum number of unexpired feeds required to extract a median feed from
|
||||
uint8_t minimum_feeds = 1;
|
||||
/// This is the delay between the time a long requests settlement and the chain evaluates the settlement
|
||||
uint32_t force_settlement_delay_sec = GRAPHENE_DEFAULT_FORCE_SETTLEMENT_DELAY;
|
||||
/// This is the percent to adjust the feed price in the short's favor in the event of a forced settlement
|
||||
uint16_t force_settlement_offset_percent = GRAPHENE_DEFAULT_FORCE_SETTLEMENT_OFFSET;
|
||||
/// Force settlement volume can be limited such that only a certain percentage of the total existing supply
|
||||
/// of the asset may be force-settled within any given chain maintenance interval. This field stores the
|
||||
/// percentage of the current supply which may be force settled within the current maintenance interval. If
|
||||
/// force settlements come due in an interval in which the maximum volume has already been settled, the new
|
||||
/// settlements will be enqueued and processed at the beginning of the next maintenance interval.
|
||||
uint16_t maximum_force_settlement_volume = GRAPHENE_DEFAULT_FORCE_SETTLEMENT_MAX_VOLUME;
|
||||
/// This speicifies which asset type is used to collateralize short sales
|
||||
/// This field may only be updated if the current supply of the asset is zero.
|
||||
asset_id_type short_backing_asset;
|
||||
|
||||
/// Perform internal consistency checks.
|
||||
/// @throws fc::exception if any check fails
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*/
|
||||
struct asset_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t symbol3 = 500000 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint64_t symbol4 = 300000 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint64_t long_symbol = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10; /// only required for large memos.
|
||||
};
|
||||
|
||||
asset fee;
|
||||
/// This account must sign and pay the fee for this operation. Later, this account may update the asset
|
||||
account_id_type issuer;
|
||||
/// The ticker symbol of this asset
|
||||
string symbol;
|
||||
/// Number of digits to the right of decimal point, must be less than or equal to 12
|
||||
uint8_t precision = 0;
|
||||
|
||||
/// Options common to all assets.
|
||||
///
|
||||
/// @note common_options.core_exchange_rate technically needs to store the asset ID of this new asset. Since this
|
||||
/// ID is not known at the time this operation is created, create this price as though the new asset has instance
|
||||
/// ID 1, and the chain will overwrite it with the new asset's ID.
|
||||
asset_options common_options;
|
||||
/// Options only available for BitAssets. MUST be non-null if and only if the @ref market_issued flag is set in
|
||||
/// common_options.flags
|
||||
optional<bitasset_options> bitasset_options;
|
||||
/// For BitAssets, set this to true if the asset implements a @ref prediction_market; false otherwise
|
||||
bool is_prediction_market = false;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
share_type calculate_fee( const fee_parameters_type& k )const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief allows global settling of bitassets (black swan or prediction markets)
|
||||
*
|
||||
* In order to use this operation, @ref asset_to_settle must have the global_settle flag set
|
||||
*
|
||||
* When this operation is executed all balances are converted into the backing asset at the
|
||||
* settle_price and all open margin positions are called at the settle price. If this asset is
|
||||
* used as backing for other bitassets, those bitassets will be force settled at their current
|
||||
* feed price.
|
||||
*/
|
||||
struct asset_global_settle_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type issuer; ///< must equal @ref asset_to_settle->issuer
|
||||
asset_id_type asset_to_settle;
|
||||
price settle_price;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Schedules a market-issued asset for automatic settlement
|
||||
* @ingroup operations
|
||||
*
|
||||
* Holders of market-issued assests may request a forced settlement for some amount of their asset. This means that
|
||||
* the specified sum will be locked by the chain and held for the settlement period, after which time the chain will
|
||||
* choose a margin posision holder and buy the settled asset using the margin's collateral. The price of this sale
|
||||
* will be based on the feed price for the market-issued asset being settled. The exact settlement price will be the
|
||||
* feed price at the time of settlement with an offset in favor of the margin position, where the offset is a
|
||||
* blockchain parameter set in the global_property_object.
|
||||
*
|
||||
* The fee is paid by @ref account, and @ref account must authorize this operation
|
||||
*/
|
||||
struct asset_settle_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
/** this fee should be high to encourage small settlement requests to
|
||||
* be performed on the market rather than via forced settlement.
|
||||
*
|
||||
* Note that in the event of a black swan or prediction market close out
|
||||
* everyone will have to pay this fee.
|
||||
*/
|
||||
uint64_t fee = 100 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
/// Account requesting the force settlement. This account pays the fee
|
||||
account_id_type account;
|
||||
/// Amount of asset to force settle. This must be a market-issued asset
|
||||
asset amount;
|
||||
|
||||
account_id_type fee_payer()const { return account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*/
|
||||
struct asset_fund_fee_pool_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee; ///< core asset
|
||||
account_id_type from_account;
|
||||
asset_id_type asset_id;
|
||||
share_type amount; ///< core asset
|
||||
|
||||
account_id_type fee_payer()const { return from_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Update options common to all assets
|
||||
* @ingroup operations
|
||||
*
|
||||
* There are a number of options which all assets in the network use. These options are enumerated in the @ref
|
||||
* asset_options struct. This operation is used to update these options for an existing asset.
|
||||
*
|
||||
* @note This operation cannot be used to update BitAsset-specific options. For these options, use @ref
|
||||
* asset_update_bitasset_operation instead.
|
||||
*
|
||||
* @pre @ref issuer SHALL be an existing account and MUST match asset_object::issuer on @ref asset_to_update
|
||||
* @pre @ref fee SHALL be nonnegative, and @ref issuer MUST have a sufficient balance to pay it
|
||||
* @pre @ref new_options SHALL be internally consistent, as verified by @ref validate()
|
||||
* @post @ref asset_to_update will have options matching those of new_options
|
||||
*/
|
||||
struct asset_update_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10;
|
||||
};
|
||||
|
||||
asset_update_operation(){}
|
||||
|
||||
/// Initializes the operation to apply changes to the provided asset, and copies old.options into @ref new_options
|
||||
/// TODO: operations should not depend upon data model objects, reverse the dependency
|
||||
// asset_update_operation(const asset_object& old);
|
||||
|
||||
asset fee;
|
||||
account_id_type issuer;
|
||||
asset_id_type asset_to_update;
|
||||
|
||||
/// If the asset is to be given a new issuer, specify his ID here.
|
||||
optional<account_id_type> new_issuer;
|
||||
asset_options new_options;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Update options specific to BitAssets
|
||||
* @ingroup operations
|
||||
*
|
||||
* BitAssets have some options which are not relevant to other asset types. This operation is used to update those
|
||||
* options an an existing BitAsset.
|
||||
*
|
||||
* @pre @ref issuer MUST be an existing account and MUST match asset_object::issuer on @ref asset_to_update
|
||||
* @pre @ref asset_to_update MUST be a BitAsset, i.e. @ref asset_object::is_market_issued() returns true
|
||||
* @pre @ref fee MUST be nonnegative, and @ref issuer MUST have a sufficient balance to pay it
|
||||
* @pre @ref new_options SHALL be internally consistent, as verified by @ref validate()
|
||||
* @post @ref asset_to_update will have BitAsset-specific options matching those of new_options
|
||||
*/
|
||||
struct asset_update_bitasset_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type issuer;
|
||||
asset_id_type asset_to_update;
|
||||
|
||||
bitasset_options new_options;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Update the set of feed-producing accounts for a BitAsset
|
||||
* @ingroup operations
|
||||
*
|
||||
* BitAssets have price feeds selected by taking the median values of recommendations from a set of feed producers.
|
||||
* This operation is used to specify which accounts may produce feeds for a given BitAsset.
|
||||
*
|
||||
* @pre @ref issuer MUST be an existing account, and MUST match asset_object::issuer on @ref asset_to_update
|
||||
* @pre @ref issuer MUST NOT be the genesis account
|
||||
* @pre @ref asset_to_update MUST be a BitAsset, i.e. @ref asset_object::is_market_issued() returns true
|
||||
* @pre @ref fee MUST be nonnegative, and @ref issuer MUST have a sufficient balance to pay it
|
||||
* @pre Cardinality of @ref new_feed_producers MUST NOT exceed @ref chain_parameters::maximum_asset_feed_publishers
|
||||
* @post @ref asset_to_update will have a set of feed producers matching @ref new_feed_producers
|
||||
* @post All valid feeds supplied by feed producers in @ref new_feed_producers, which were already feed producers
|
||||
* prior to execution of this operation, will be preserved
|
||||
*/
|
||||
struct asset_update_feed_producers_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 500 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type issuer;
|
||||
asset_id_type asset_to_update;
|
||||
|
||||
flat_set<account_id_type> new_feed_producers;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Publish price feeds for market-issued assets
|
||||
* @ingroup operations
|
||||
*
|
||||
* Price feed providers use this operation to publish their price feeds for market-issued assets. A price feed is
|
||||
* used to tune the market for a particular market-issued asset. For each value in the feed, the median across all
|
||||
* delegate feeds for that asset is calculated and the market for the asset is configured with the median of that
|
||||
* value.
|
||||
*
|
||||
* The feed in the operation contains three prices: a call price limit, a short price limit, and a settlement price.
|
||||
* The call limit price is structured as (collateral asset) / (debt asset) and the short limit price is structured
|
||||
* as (asset for sale) / (collateral asset). Note that the asset IDs are opposite to eachother, so if we're
|
||||
* publishing a feed for USD, the call limit price will be CORE/USD and the short limit price will be USD/CORE. The
|
||||
* settlement price may be flipped either direction, as long as it is a ratio between the market-issued asset and
|
||||
* its collateral.
|
||||
*/
|
||||
struct asset_publish_feed_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee; ///< paid for by publisher
|
||||
account_id_type publisher;
|
||||
asset_id_type asset_id; ///< asset for which the feed is published
|
||||
price_feed feed;
|
||||
|
||||
account_id_type fee_payer()const { return publisher; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*/
|
||||
struct asset_issue_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type issuer; ///< Must be asset_to_issue->asset_id->issuer
|
||||
asset asset_to_issue;
|
||||
account_id_type issue_to_account;
|
||||
|
||||
|
||||
/** user provided data encrypted to the memo key of the "to" account */
|
||||
optional<memo_data> memo;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief used to take an asset out of circulation, returning to the issuer
|
||||
* @ingroup operations
|
||||
*
|
||||
* @note You cannot burn market-issued assets.
|
||||
*/
|
||||
struct asset_reserve_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
asset amount_to_reserve;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
|
||||
} } // graphene::chain
|
||||
FC_REFLECT( graphene::chain::asset_options,
|
||||
(max_supply)
|
||||
(market_fee_percent)
|
||||
(max_market_fee)
|
||||
(issuer_permissions)
|
||||
(flags)
|
||||
(core_exchange_rate)
|
||||
(whitelist_authorities)
|
||||
(blacklist_authorities)
|
||||
(whitelist_markets)
|
||||
(blacklist_markets)
|
||||
(description)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::bitasset_options,
|
||||
(feed_lifetime_sec)
|
||||
(minimum_feeds)
|
||||
(force_settlement_delay_sec)
|
||||
(force_settlement_offset_percent)
|
||||
(maximum_force_settlement_volume)
|
||||
(short_backing_asset)
|
||||
)
|
||||
|
||||
|
||||
FC_REFLECT( graphene::chain::asset_create_operation::fee_parameters_type, (symbol3)(symbol4)(long_symbol)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::asset_global_settle_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::asset_settle_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::asset_fund_fee_pool_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::asset_update_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::asset_update_bitasset_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::asset_update_feed_producers_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::asset_publish_feed_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::asset_issue_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::asset_reserve_operation::fee_parameters_type, (fee) )
|
||||
|
||||
|
||||
FC_REFLECT( graphene::chain::asset_create_operation,
|
||||
(fee)
|
||||
(issuer)
|
||||
(symbol)
|
||||
(precision)
|
||||
(common_options)
|
||||
(bitasset_options)
|
||||
(is_prediction_market)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::asset_update_operation,
|
||||
(fee)
|
||||
(issuer)
|
||||
(asset_to_update)
|
||||
(new_issuer)
|
||||
(new_options)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::asset_update_bitasset_operation,
|
||||
(fee)
|
||||
(issuer)
|
||||
(asset_to_update)
|
||||
(new_options)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::asset_update_feed_producers_operation,
|
||||
(fee)(issuer)(asset_to_update)(new_feed_producers)
|
||||
)
|
||||
FC_REFLECT( graphene::chain::asset_publish_feed_operation,
|
||||
(fee)(publisher)(asset_id)(feed) )
|
||||
FC_REFLECT( graphene::chain::asset_settle_operation, (fee)(account)(amount) )
|
||||
FC_REFLECT( graphene::chain::asset_global_settle_operation, (fee)(issuer)(asset_to_settle)(settle_price) )
|
||||
FC_REFLECT( graphene::chain::asset_issue_operation,
|
||||
(fee)(issuer)(asset_to_issue)(issue_to_account)(memo) )
|
||||
FC_REFLECT( graphene::chain::asset_reserve_operation,
|
||||
(fee)(payer)(amount_to_reserve) )
|
||||
|
||||
FC_REFLECT( graphene::chain::asset_fund_fee_pool_operation, (fee)(from_account)(asset_id)(amount) );
|
||||
|
||||
|
|
@ -16,8 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <fc/io/varint.hpp>
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
32
libraries/chain/include/graphene/chain/protocol/balance.hpp
Normal file
32
libraries/chain/include/graphene/chain/protocol/balance.hpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @brief Claim a balance in a @ref balanc_object
|
||||
*
|
||||
* This operation is used to claim the balance in a given @ref balance_object. If the balance object contains a
|
||||
* vesting balance, @ref total_claimed must not exceed @ref balance_object::available at the time of evaluation. If
|
||||
* the object contains a non-vesting balance, @ref total_claimed must be the full balance of the object.
|
||||
*/
|
||||
struct balance_claim_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {};
|
||||
|
||||
asset fee;
|
||||
account_id_type deposit_to_account;
|
||||
balance_id_type balance_to_claim;
|
||||
public_key_type balance_owner_key;
|
||||
asset total_claimed;
|
||||
|
||||
account_id_type fee_payer()const { return deposit_to_account; }
|
||||
share_type calculate_fee(const fee_parameters_type& )const { return 0; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
}} // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::balance_claim_operation::fee_parameters_type, )
|
||||
FC_REFLECT( graphene::chain::balance_claim_operation,
|
||||
(fee)(deposit_to_account)(balance_to_claim)(balance_owner_key)(total_claimed) )
|
||||
83
libraries/chain/include/graphene/chain/protocol/base.hpp
Normal file
83
libraries/chain/include/graphene/chain/protocol/base.hpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/chain/protocol/authority.hpp>
|
||||
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @defgroup operations Operations
|
||||
* @ingroup transactions Transactions
|
||||
* @brief A set of valid comands for mutating the globally shared state.
|
||||
*
|
||||
* An operation can be thought of like a function that will modify the global
|
||||
* shared state of the blockchain. The members of each struct are like function
|
||||
* arguments and each operation can potentially generate a return value.
|
||||
*
|
||||
* Operations can be grouped into transactions (@ref transaction) to ensure that they occur
|
||||
* in a particular order and that all operations apply successfully or
|
||||
* no operations apply.
|
||||
*
|
||||
* Each operation is a fully defined state transition and can exist in a transaction on its own.
|
||||
*
|
||||
* @section operation_design_principles Design Principles
|
||||
*
|
||||
* Operations have been carefully designed to include all of the information necessary to
|
||||
* interpret them outside the context of the blockchain. This means that information about
|
||||
* current chain state is included in the operation even though it could be inferred from
|
||||
* a subset of the data. This makes the expected outcome of each operation well defined and
|
||||
* easily understood without access to chain state.
|
||||
*
|
||||
* @subsection balance_calculation Balance Calculation Principle
|
||||
*
|
||||
* We have stipulated that the current account balance may be entirely calculated from
|
||||
* just the subset of operations that are relevant to that account. There should be
|
||||
* no need to process the entire blockchain inorder to know your account's balance.
|
||||
*
|
||||
* @subsection fee_calculation Explicit Fee Principle
|
||||
*
|
||||
* Blockchain fees can change from time to time and it is important that a signed
|
||||
* transaction explicitly agree to the fees it will be paying. This aids with account
|
||||
* balance updates and ensures that the sender agreed to the fee prior to making the
|
||||
* transaction.
|
||||
*
|
||||
* @subsection defined_authority Explicit Authority
|
||||
*
|
||||
* Each operation shall contain enough information to know which accounts must authorize
|
||||
* the operation. This principle enables authority verification to occur in a centralized,
|
||||
* optimized, and parallel manner.
|
||||
*
|
||||
* @subsection relevancy_principle Explicit Relevant Accounts
|
||||
*
|
||||
* Each operation contains enough information to enumerate all accounts for which the
|
||||
* operation should apear in its account history. This principle enables us to easily
|
||||
* define and enforce the @balance_calculation. This is superset of the @ref defined_authority
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct void_result{};
|
||||
typedef fc::static_variant<void_result,object_id_type,asset> operation_result;
|
||||
|
||||
struct base_operation
|
||||
{
|
||||
template<typename T>
|
||||
share_type calculate_fee(const T& params)const
|
||||
{
|
||||
return params.fee;
|
||||
}
|
||||
void get_required_authorities( vector<authority>& )const{}
|
||||
void get_required_active_authorities( flat_set<account_id_type>& )const{}
|
||||
void get_required_owner_authorities( flat_set<account_id_type>& )const{}
|
||||
void get_impacted_accounts( flat_set<account_id_type>& )const{}
|
||||
void validate()const{}
|
||||
|
||||
static uint64_t calculate_data_fee( uint64_t bytes, uint64_t price_per_kbyte );
|
||||
};
|
||||
|
||||
///@}
|
||||
|
||||
} }
|
||||
FC_REFLECT_TYPENAME( graphene::chain::operation_result )
|
||||
FC_REFLECT( graphene::chain::void_result, )
|
||||
|
|
@ -16,8 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/transaction.hpp>
|
||||
#include <graphene/chain/protocol/transaction.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -16,14 +16,24 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/fee_schedule.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <fc/smart_ref_fwd.hpp>
|
||||
|
||||
namespace graphene { namespace chain { struct fee_schedule; } }
|
||||
/*
|
||||
namespace fc {
|
||||
template<typename Stream, typename T> inline void pack( Stream& s, const graphene::chain::fee_schedule& value );
|
||||
template<typename Stream, typename T> inline void unpack( Stream& s, graphene::chain::fee_schedule& value );
|
||||
} // namespace fc
|
||||
*/
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
typedef static_variant<> parameter_extension;
|
||||
struct chain_parameters
|
||||
{
|
||||
fee_schedule current_fees; ///< current schedule of fees
|
||||
/** using a smart ref breaks the circular dependency created between operations and the fee schedule */
|
||||
smart_ref<fee_schedule> current_fees; ///< current schedule of fees
|
||||
uint8_t block_interval = GRAPHENE_DEFAULT_BLOCK_INTERVAL; ///< interval in seconds between blocks
|
||||
uint32_t maintenance_interval = GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL; ///< interval in sections between blockchain maintenance events
|
||||
uint32_t genesis_proposal_review_period = GRAPHENE_DEFAULT_GENESIS_PROPOSAL_REVIEW_PERIOD_SEC; ///< minimum time in seconds that a proposed transaction requiring genesis authority may not be signed, prior to expiration
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/config.hpp>
|
||||
35
libraries/chain/include/graphene/chain/protocol/custom.hpp
Normal file
35
libraries/chain/include/graphene/chain/protocol/custom.hpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @brief provides a generic way to add higher level protocols on top of witness consensus
|
||||
* @ingroup operations
|
||||
*
|
||||
* There is no validation for this operation other than that required auths are valid and a fee
|
||||
* is paid that is appropriate for the data contained.
|
||||
*/
|
||||
struct custom_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type payer;
|
||||
flat_set<account_id_type> required_auths;
|
||||
uint16_t id;
|
||||
vector<char> data;
|
||||
|
||||
account_id_type fee_payer()const { return payer; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
|
||||
} } // namespace graphene::chain
|
||||
FC_REFLECT( graphene::chain::custom_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::custom_operation, (fee)(payer)(required_auths)(id)(data) )
|
||||
59
libraries/chain/include/graphene/chain/protocol/delegate.hpp
Normal file
59
libraries/chain/include/graphene/chain/protocol/delegate.hpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/chain_parameters.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @brief Create a delegate object, as a bid to hold a delegate seat on the network.
|
||||
* @ingroup operations
|
||||
*
|
||||
* Accounts which wish to become delegates may use this operation to create a delegate object which stakeholders may
|
||||
* vote on to approve its position as a delegate.
|
||||
*/
|
||||
struct delegate_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
/// The account which owns the delegate. This account pays the fee for this operation.
|
||||
account_id_type delegate_account;
|
||||
string url;
|
||||
|
||||
account_id_type fee_payer()const { return delegate_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Used by delegates to update the global parameters of the blockchain.
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation allows the delegates to update the global parameters on the blockchain. These control various
|
||||
* tunable aspects of the chain, including block and maintenance intervals, maximum data sizes, the fees charged by
|
||||
* the network, etc.
|
||||
*
|
||||
* This operation may only be used in a proposed transaction, and a proposed transaction which contains this
|
||||
* operation must have a review period specified in the current global parameters before it may be accepted.
|
||||
*/
|
||||
struct delegate_update_global_parameters_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
chain_parameters new_parameters;
|
||||
|
||||
account_id_type fee_payer()const { return account_id_type(); }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/// TODO: delegate_resign_operation : public base_operation
|
||||
|
||||
} } // graphene::chain
|
||||
FC_REFLECT( graphene::chain::delegate_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::delegate_update_global_parameters_operation::fee_parameters_type, (fee) )
|
||||
|
||||
|
||||
FC_REFLECT( graphene::chain::delegate_create_operation,
|
||||
(fee)(delegate_account)(url) )
|
||||
|
||||
FC_REFLECT( graphene::chain::delegate_update_global_parameters_operation, (fee)(new_parameters) );
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -27,6 +27,8 @@ namespace graphene { namespace chain {
|
|||
asset calculate_fee( const operation& op, const price& core_exchange_rate = price::unit_price() )const;
|
||||
void set_fee( operation& op, const price& core_exchange_rate = price::unit_price() )const;
|
||||
|
||||
void set_all_fees( uint64_t fee_amount );
|
||||
|
||||
/**
|
||||
* Validates all of the parameters are present and accounted for.
|
||||
*/
|
||||
|
|
@ -46,7 +48,3 @@ namespace graphene { namespace chain {
|
|||
FC_REFLECT_TYPENAME( graphene::chain::fee_parameters )
|
||||
FC_REFLECT( graphene::chain::fee_schedule, (parameters) )
|
||||
|
||||
|
||||
|
||||
|
||||
} }
|
||||
147
libraries/chain/include/graphene/chain/protocol/market.hpp
Normal file
147
libraries/chain/include/graphene/chain/protocol/market.hpp
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @class limit_order_create_operation
|
||||
* @brief instructs the blockchain to attempt to sell one asset for another
|
||||
* @ingroup operations
|
||||
*
|
||||
* The blockchain will atempt to sell amount_to_sell.asset_id for as
|
||||
* much min_to_receive.asset_id as possible. The fee will be paid by
|
||||
* the seller's account. Market fees will apply as specified by the
|
||||
* issuer of both the selling asset and the receiving asset as
|
||||
* a percentage of the amount exchanged.
|
||||
*
|
||||
* If either the selling asset or the receiving asset is white list
|
||||
* restricted, the order will only be created if the seller is on
|
||||
* the white list of the restricted asset type.
|
||||
*
|
||||
* Market orders are matched in the order they are included
|
||||
* in the block chain.
|
||||
*/
|
||||
struct limit_order_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 5 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type seller;
|
||||
asset amount_to_sell;
|
||||
asset min_to_receive;
|
||||
|
||||
/// The order will be removed from the books if not filled by expiration
|
||||
/// Upon expiration, all unsold asset will be returned to seller
|
||||
time_point_sec expiration = time_point_sec::maximum();
|
||||
|
||||
/// If this flag is set the entire order must be filled or the operation is rejected
|
||||
bool fill_or_kill = false;
|
||||
|
||||
pair<asset_id_type,asset_id_type> get_market()const
|
||||
{
|
||||
return amount_to_sell.asset_id < min_to_receive.asset_id ?
|
||||
std::make_pair(amount_to_sell.asset_id, min_to_receive.asset_id) :
|
||||
std::make_pair(min_to_receive.asset_id, amount_to_sell.asset_id);
|
||||
}
|
||||
account_id_type fee_payer()const { return seller; }
|
||||
void validate()const;
|
||||
price get_price()const { return amount_to_sell / min_to_receive; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
* Used to cancel an existing limit order. Both fee_pay_account and the
|
||||
* account to receive the proceeds must be the same as order->seller.
|
||||
*
|
||||
* @return the amount actually refunded
|
||||
*/
|
||||
struct limit_order_cancel_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
limit_order_id_type order;
|
||||
/** must be order->seller */
|
||||
account_id_type fee_paying_account;
|
||||
|
||||
account_id_type fee_payer()const { return fee_paying_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation can be used to add collateral, cover, and adjust the margin call price for a particular user.
|
||||
*
|
||||
* For prediction markets the collateral and debt must always be equal.
|
||||
*
|
||||
* This operation will fail if it would trigger a margin call that couldn't be filled. If the margin call hits
|
||||
* the call price limit then it will fail if the call price is above the settlement price.
|
||||
*
|
||||
* @note this operation can be used to force a market order using the collateral without requiring outside funds.
|
||||
*/
|
||||
struct call_order_update_operation : public base_operation
|
||||
{
|
||||
/** this is slightly more expensive than limit orders, this pricing impacts prediction markets */
|
||||
struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type funding_account; ///< pays fee, collateral, and cover
|
||||
asset delta_collateral; ///< the amount of collateral to add to the margin position
|
||||
asset delta_debt; ///< the amount of the debt to be paid off, may be negative to issue new debt
|
||||
|
||||
account_id_type fee_payer()const { return funding_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*
|
||||
* @note This is a virtual operation that is created while matching orders and
|
||||
* emitted for the purpose of accurately tracking account history, accelerating
|
||||
* a reindex.
|
||||
*/
|
||||
struct fill_order_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {};
|
||||
|
||||
fill_order_operation(){}
|
||||
fill_order_operation( object_id_type o, account_id_type a, asset p, asset r, asset f )
|
||||
:order_id(o),account_id(a),pays(p),receives(r),fee(f){}
|
||||
|
||||
object_id_type order_id;
|
||||
account_id_type account_id;
|
||||
asset pays;
|
||||
asset receives;
|
||||
asset fee; // paid by receiving account
|
||||
|
||||
|
||||
pair<asset_id_type,asset_id_type> get_market()const
|
||||
{
|
||||
return pays.asset_id < receives.asset_id ?
|
||||
std::make_pair( pays.asset_id, receives.asset_id ) :
|
||||
std::make_pair( receives.asset_id, pays.asset_id );
|
||||
}
|
||||
account_id_type fee_payer()const { return account_id; }
|
||||
void validate()const { FC_ASSERT( !"virtual operation" ); }
|
||||
|
||||
/// This is a virtual operation; there is no fee
|
||||
share_type calculate_fee(const fee_parameters_type& k)const { return 0; }
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::limit_order_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::limit_order_cancel_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::call_order_update_operation::fee_parameters_type, (fee) )
|
||||
/// THIS IS THE ONLY VIRTUAL OPERATION THUS FAR...
|
||||
FC_REFLECT( graphene::chain::fill_order_operation::fee_parameters_type, )
|
||||
|
||||
|
||||
FC_REFLECT( graphene::chain::limit_order_create_operation,(fee)(seller)(amount_to_sell)(min_to_receive)(expiration)(fill_or_kill))
|
||||
FC_REFLECT( graphene::chain::limit_order_cancel_operation,(fee)(fee_paying_account)(order) )
|
||||
FC_REFLECT( graphene::chain::call_order_update_operation, (fee)(funding_account)(delta_collateral)(delta_debt) )
|
||||
FC_REFLECT( graphene::chain::fill_order_operation, (fee)(order_id)(account_id)(pays)(receives) )
|
||||
68
libraries/chain/include/graphene/chain/protocol/memo.hpp
Normal file
68
libraries/chain/include/graphene/chain/protocol/memo.hpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @brief defines the keys used to derive the shared secret
|
||||
*
|
||||
* Because account authorities and keys can change at any time, each memo must
|
||||
* capture the specific keys used to derive the shared secret. In order to read
|
||||
* the cipher message you will need one of the two private keys.
|
||||
*
|
||||
* If @ref from == @ref to and @ref from == 0 then no encryption is used, the memo is public.
|
||||
* If @ref from == @ref to and @ref from != 0 then invalid memo data
|
||||
*
|
||||
*/
|
||||
struct memo_data
|
||||
{
|
||||
public_key_type from;
|
||||
public_key_type to;
|
||||
/**
|
||||
* 64 bit nonce format:
|
||||
* [ 8 bits | 56 bits ]
|
||||
* [ entropy | timestamp ]
|
||||
* Timestamp is number of microseconds since the epoch
|
||||
* Entropy is a byte taken from the hash of a new private key
|
||||
*
|
||||
* This format is not mandated or verified; it is chosen to ensure uniqueness of key-IV pairs only. This should
|
||||
* be unique with high probability as long as the generating host has a high-resolution clock OR a strong source
|
||||
* of entropy for generating private keys.
|
||||
*/
|
||||
uint64_t nonce;
|
||||
/**
|
||||
* This field contains the AES encrypted packed @ref memo_message
|
||||
*/
|
||||
vector<char> message;
|
||||
|
||||
/// @note custom_nonce is for debugging only; do not set to a nonzero value in production
|
||||
void set_message(const fc::ecc::private_key& priv,
|
||||
const fc::ecc::public_key& pub, const string& msg, uint64_t custom_nonce = 0);
|
||||
|
||||
std::string get_message(const fc::ecc::private_key& priv,
|
||||
const fc::ecc::public_key& pub)const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief defines a message and checksum to enable validation of successful decryption
|
||||
*
|
||||
* When encrypting/decrypting a checksum is required to determine whether or not
|
||||
* decryption was successful.
|
||||
*/
|
||||
struct memo_message
|
||||
{
|
||||
memo_message(){}
|
||||
memo_message( uint32_t checksum, const std::string& text )
|
||||
:checksum(checksum),text(text){}
|
||||
|
||||
uint32_t checksum = 0;
|
||||
std::string text;
|
||||
|
||||
string serialize() const;
|
||||
static memo_message deserialize(const string& serial);
|
||||
};
|
||||
|
||||
} } // namespace graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::memo_message, (checksum)(text) )
|
||||
FC_REFLECT( graphene::chain::memo_data, (from)(to)(nonce)(message) )
|
||||
117
libraries/chain/include/graphene/chain/protocol/operations.hpp
Normal file
117
libraries/chain/include/graphene/chain/protocol/operations.hpp
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/account.hpp>
|
||||
#include <graphene/chain/protocol/assert.hpp>
|
||||
#include <graphene/chain/protocol/asset_ops.hpp>
|
||||
#include <graphene/chain/protocol/balance.hpp>
|
||||
#include <graphene/chain/protocol/custom.hpp>
|
||||
#include <graphene/chain/protocol/delegate.hpp>
|
||||
#include <graphene/chain/protocol/market.hpp>
|
||||
#include <graphene/chain/protocol/proposal.hpp>
|
||||
#include <graphene/chain/protocol/transfer.hpp>
|
||||
#include <graphene/chain/protocol/vesting.hpp>
|
||||
#include <graphene/chain/protocol/withdraw_permission.hpp>
|
||||
#include <graphene/chain/protocol/witness.hpp>
|
||||
#include <graphene/chain/protocol/worker.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*
|
||||
* Defines the set of valid operations as a discriminated union type.
|
||||
*/
|
||||
typedef fc::static_variant<
|
||||
transfer_operation,
|
||||
limit_order_create_operation,
|
||||
limit_order_cancel_operation,
|
||||
call_order_update_operation,
|
||||
fill_order_operation,
|
||||
account_create_operation,
|
||||
account_update_operation,
|
||||
account_whitelist_operation,
|
||||
account_upgrade_operation,
|
||||
account_transfer_operation,
|
||||
asset_create_operation,
|
||||
asset_update_operation,
|
||||
asset_update_bitasset_operation,
|
||||
asset_update_feed_producers_operation,
|
||||
asset_issue_operation,
|
||||
asset_reserve_operation,
|
||||
asset_fund_fee_pool_operation,
|
||||
asset_settle_operation,
|
||||
asset_global_settle_operation,
|
||||
asset_publish_feed_operation,
|
||||
witness_create_operation,
|
||||
witness_withdraw_pay_operation,
|
||||
proposal_create_operation,
|
||||
proposal_update_operation,
|
||||
proposal_delete_operation,
|
||||
withdraw_permission_create_operation,
|
||||
withdraw_permission_update_operation,
|
||||
withdraw_permission_claim_operation,
|
||||
withdraw_permission_delete_operation,
|
||||
delegate_create_operation,
|
||||
delegate_update_global_parameters_operation,
|
||||
vesting_balance_create_operation,
|
||||
vesting_balance_withdraw_operation,
|
||||
worker_create_operation,
|
||||
custom_operation,
|
||||
assert_operation,
|
||||
balance_claim_operation,
|
||||
override_transfer_operation
|
||||
> operation;
|
||||
|
||||
/// @} // operations group
|
||||
|
||||
/**
|
||||
* Appends required authorites to the result vector. The authorities appended are not the
|
||||
* same as those returned by get_required_auth
|
||||
*
|
||||
* @return a set of required authorities for @ref op
|
||||
*/
|
||||
void operation_get_required_authorities( const operation& op,
|
||||
flat_set<account_id_type>& active,
|
||||
flat_set<account_id_type>& owner,
|
||||
vector<authority>& other );
|
||||
|
||||
void operation_get_impacted_accounts( const operation& op,
|
||||
flat_set<account_id_type>& accounts );
|
||||
|
||||
void operation_validate( const operation& op );
|
||||
|
||||
/**
|
||||
* Used to track the result of applying an operation and when it was applied.
|
||||
*
|
||||
* TODO: this doesn't belong here.
|
||||
*/
|
||||
struct applied_operation
|
||||
{
|
||||
operation op;
|
||||
operation_result result;
|
||||
uint32_t block_num;
|
||||
uint16_t transaction_num;
|
||||
uint16_t op_num;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief necessary to support nested operations inside the proposal_create_operation
|
||||
*/
|
||||
struct op_wrapper
|
||||
{
|
||||
public:
|
||||
op_wrapper(const operation& op = operation()):op(op){}
|
||||
operation op;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::operation )
|
||||
FC_REFLECT( graphene::chain::op_wrapper, (op) )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
145
libraries/chain/include/graphene/chain/protocol/proposal.hpp
Normal file
145
libraries/chain/include/graphene/chain/protocol/proposal.hpp
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
/**
|
||||
* @defgroup proposed_transactions The Graphene Transaction Proposal Protocol
|
||||
* @ingroup operations
|
||||
*
|
||||
* Graphene allows users to propose a transaction which requires approval of multiple accounts in order to execute.
|
||||
* The user proposes a transaction using proposal_create_operation, then signatory accounts use
|
||||
* proposal_update_operations to add or remove their approvals from this operation. When a sufficient number of
|
||||
* approvals have been granted, the operations in the proposal are used to create a virtual transaction which is
|
||||
* subsequently evaluated. Even if the transaction fails, the proposal will be kept until the expiration time, at
|
||||
* which point, if sufficient approval is granted, the transaction will be evaluated a final time. This allows
|
||||
* transactions which will not execute successfully until a given time to still be executed through the proposal
|
||||
* mechanism. The first time the proposed transaction succeeds, the proposal will be regarded as resolved, and all
|
||||
* future updates will be invalid.
|
||||
*
|
||||
* The proposal system allows for arbitrarily complex or recursively nested authorities. If a recursive authority
|
||||
* (i.e. an authority which requires approval of 'nested' authorities on other accounts) is required for a
|
||||
* proposal, then a second proposal can be used to grant the nested authority's approval. That is, a second
|
||||
* proposal can be created which, when sufficiently approved, adds the approval of a nested authority to the first
|
||||
* proposal. This multiple-proposal scheme can be used to acquire approval for an arbitrarily deep authority tree.
|
||||
*
|
||||
* Note that at any time, a proposal can be approved in a single transaction if sufficient signatures are available
|
||||
* on the proposal_update_operation, as long as the authority tree to approve the proposal does not exceed the
|
||||
* maximum recursion depth. In practice, however, it is easier to use proposals to acquire all approvals, as this
|
||||
* leverages on-chain notification of all relevant parties that their approval is required. Off-chain
|
||||
* multi-signature approval requires some off-chain mechanism for acquiring several signatures on a single
|
||||
* transaction. This off-chain synchronization can be avoided using proposals.
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* op_wrapper is used to get around the circular definition of operation and proposals that contain them.
|
||||
*/
|
||||
struct op_wrapper;
|
||||
/**
|
||||
* @brief The proposal_create_operation creates a transaction proposal, for use in multi-sig scenarios
|
||||
* @ingroup operations
|
||||
*
|
||||
* Creates a transaction proposal. The operations which compose the transaction are listed in order in proposed_ops,
|
||||
* and expiration_time specifies the time by which the proposal must be accepted or it will fail permanently. The
|
||||
* expiration_time cannot be farther in the future than the maximum expiration time set in the global properties
|
||||
* object.
|
||||
*/
|
||||
struct proposal_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10;
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type fee_paying_account;
|
||||
vector<op_wrapper> proposed_ops;
|
||||
time_point_sec expiration_time;
|
||||
optional<uint32_t> review_period_seconds;
|
||||
|
||||
/// Constructs a proposal_create_operation suitable for genesis proposals, with fee, expiration time and review
|
||||
/// period set appropriately.
|
||||
static proposal_create_operation genesis_proposal(const chain_parameters& param, fc::time_point_sec head_block_time );
|
||||
|
||||
account_id_type fee_payer()const { return fee_paying_account; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The proposal_update_operation updates an existing transaction proposal
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation allows accounts to add or revoke approval of a proposed transaction. Signatures sufficient to
|
||||
* satisfy the authority of each account in approvals are required on the transaction containing this operation.
|
||||
*
|
||||
* If an account with a multi-signature authority is listed in approvals_to_add or approvals_to_remove, either all
|
||||
* required signatures to satisfy that account's authority must be provided in the transaction containing this
|
||||
* operation, or a secondary proposal must be created which contains this operation.
|
||||
*
|
||||
* NOTE: If the proposal requires only an account's active authority, the account must not update adding its owner
|
||||
* authority's approval. This is considered an error. An owner approval may only be added if the proposal requires
|
||||
* the owner's authority.
|
||||
*
|
||||
* If an account's owner and active authority are both required, only the owner authority may approve. An attempt to
|
||||
* add or remove active authority approval to such a proposal will fail.
|
||||
*/
|
||||
struct proposal_update_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10;
|
||||
};
|
||||
|
||||
account_id_type fee_paying_account;
|
||||
asset fee;
|
||||
proposal_id_type proposal;
|
||||
flat_set<account_id_type> active_approvals_to_add;
|
||||
flat_set<account_id_type> active_approvals_to_remove;
|
||||
flat_set<account_id_type> owner_approvals_to_add;
|
||||
flat_set<account_id_type> owner_approvals_to_remove;
|
||||
flat_set<public_key_type> key_approvals_to_add;
|
||||
flat_set<public_key_type> key_approvals_to_remove;
|
||||
|
||||
account_id_type fee_payer()const { return fee_paying_account; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The proposal_delete_operation deletes an existing transaction proposal
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation allows the early veto of a proposed transaction. It may be used by any account which is a required
|
||||
* authority on the proposed transaction, when that account's holder feels the proposal is ill-advised and he decides
|
||||
* he will never approve of it and wishes to put an end to all discussion of the issue. Because he is a required
|
||||
* authority, he could simply refuse to add his approval, but this would leave the topic open for debate until the
|
||||
* proposal expires. Using this operation, he can prevent any further breath from being wasted on such an absurd
|
||||
* proposal.
|
||||
*/
|
||||
struct proposal_delete_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
account_id_type fee_paying_account;
|
||||
bool using_owner_authority = false;
|
||||
asset fee;
|
||||
proposal_id_type proposal;
|
||||
|
||||
account_id_type fee_payer()const { return fee_paying_account; }
|
||||
void validate()const;
|
||||
};
|
||||
///@}
|
||||
|
||||
}} // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::proposal_create_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::proposal_update_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::proposal_delete_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::proposal_create_operation, (fee)(fee_paying_account)(expiration_time)
|
||||
(proposed_ops)(review_period_seconds) )
|
||||
FC_REFLECT( graphene::chain::proposal_update_operation, (fee)(fee_paying_account)(proposal)
|
||||
(active_approvals_to_add)(active_approvals_to_remove)(owner_approvals_to_add)(owner_approvals_to_remove)
|
||||
(key_approvals_to_add)(key_approvals_to_remove) )
|
||||
FC_REFLECT( graphene::chain::proposal_delete_operation, (fee)(fee_paying_account)(using_owner_authority)(proposal) )
|
||||
|
||||
|
|
@ -16,8 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
83
libraries/chain/include/graphene/chain/protocol/transfer.hpp
Normal file
83
libraries/chain/include/graphene/chain/protocol/transfer.hpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/memo.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
*
|
||||
* @brief Transfers an amount of one asset from one account to another
|
||||
*
|
||||
* Fees are paid by the "from" account
|
||||
*
|
||||
* @pre amount.amount > 0
|
||||
* @pre fee.amount >= 0
|
||||
* @pre from != to
|
||||
* @post from account's balance will be reduced by fee and amount
|
||||
* @post to account's balance will be increased by amount
|
||||
* @return n/a
|
||||
*/
|
||||
struct transfer_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10; /// only required for large memos.
|
||||
};
|
||||
|
||||
asset fee;
|
||||
/// Account to transfer asset from
|
||||
account_id_type from;
|
||||
/// Account to transfer asset to
|
||||
account_id_type to;
|
||||
/// The amount of asset to transfer from @ref from to @ref to
|
||||
asset amount;
|
||||
|
||||
/// User provided data encrypted to the memo key of the "to" account
|
||||
optional<memo_data> memo;
|
||||
|
||||
account_id_type fee_payer()const { return from; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class override_transfer_operation
|
||||
* @brief Allows the issuer of an asset to transfer an asset from any account to any account if they have override_authority
|
||||
* @ingroup operations
|
||||
*
|
||||
* @pre amount.asset_id->issuer == issuer
|
||||
* @pre issuer != from because this is pointless, use a normal transfer operation
|
||||
*/
|
||||
struct override_transfer_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10; /// only required for large memos.
|
||||
};
|
||||
|
||||
asset fee;
|
||||
account_id_type issuer;
|
||||
/// Account to transfer asset from
|
||||
account_id_type from;
|
||||
/// Account to transfer asset to
|
||||
account_id_type to;
|
||||
/// The amount of asset to transfer from @ref from to @ref to
|
||||
asset amount;
|
||||
|
||||
/// User provided data encrypted to the memo key of the "to" account
|
||||
optional<memo_data> memo;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
}} // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::transfer_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::override_transfer_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
|
||||
FC_REFLECT( graphene::chain::override_transfer_operation, (fee)(issuer)(from)(to)(amount)(memo) )
|
||||
FC_REFLECT( graphene::chain::transfer_operation, (fee)(from)(to)(amount)(memo) )
|
||||
|
||||
|
|
@ -29,11 +29,14 @@
|
|||
#include <fc/string.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
#include <fc/static_variant.hpp>
|
||||
#include <fc/smart_ref_fwd.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <cstdint>
|
||||
#include <graphene/chain/address.hpp>
|
||||
#include <graphene/chain/protocol/address.hpp>
|
||||
#include <graphene/db/object_id.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
@ -53,6 +56,7 @@ namespace graphene { namespace chain {
|
|||
using std::tie;
|
||||
using std::make_pair;
|
||||
|
||||
using fc::smart_ref;
|
||||
using fc::variant_object;
|
||||
using fc::variant;
|
||||
using fc::enum_type;
|
||||
|
|
@ -349,8 +353,9 @@ namespace fc
|
|||
void to_variant( const graphene::chain::vote_id_type& var, fc::variant& vo );
|
||||
void from_variant( const fc::variant& var, graphene::chain::vote_id_type& vo );
|
||||
}
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::vote_id_type::vote_type )
|
||||
FC_REFLECT_TYPENAME( fc::flat_set<graphene::chain::vote_id_type> )
|
||||
|
||||
FC_REFLECT_ENUM( graphene::chain::vote_id_type::vote_type, (witness)(committee)(worker)(VOTE_TYPE_COUNT) )
|
||||
FC_REFLECT( graphene::chain::vote_id_type, (content) )
|
||||
|
||||
96
libraries/chain/include/graphene/chain/protocol/vesting.hpp
Normal file
96
libraries/chain/include/graphene/chain/protocol/vesting.hpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct linear_vesting_policy_initializer
|
||||
{
|
||||
/** while vesting begins on begin_timestamp, none may be claimed before vesting_cliff_seconds have passed */
|
||||
fc::time_point_sec begin_timestamp;
|
||||
uint32_t vesting_cliff_seconds = 0;
|
||||
uint32_t vesting_duration_seconds = 0;
|
||||
};
|
||||
|
||||
struct cdd_vesting_policy_initializer
|
||||
{
|
||||
/** while coindays may accrue over time, none may be claimed before the start_claim time */
|
||||
fc::time_point_sec start_claim;
|
||||
uint32_t vesting_seconds = 0;
|
||||
cdd_vesting_policy_initializer( uint32_t vest_sec = 0, fc::time_point_sec sc = fc::time_point_sec() ):start_claim(sc),vesting_seconds(vest_sec){}
|
||||
};
|
||||
|
||||
typedef fc::static_variant<linear_vesting_policy_initializer, cdd_vesting_policy_initializer> vesting_policy_initializer;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a vesting balance.
|
||||
* @ingroup operations
|
||||
*
|
||||
* The chain allows a user to create a vesting balance.
|
||||
* Normally, vesting balances are created automatically as part
|
||||
* of cashback and worker operations. This operation allows
|
||||
* vesting balances to be created manually as well.
|
||||
*
|
||||
* Manual creation of vesting balances can be used by a stakeholder
|
||||
* to publicly demonstrate that they are committed to the chain.
|
||||
* It can also be used as a building block to create transactions
|
||||
* that function like public debt. Finally, it is useful for
|
||||
* testing vesting balance functionality.
|
||||
*
|
||||
* @return ID of newly created vesting_balance_object
|
||||
*/
|
||||
struct vesting_balance_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type creator; ///< Who provides funds initially
|
||||
account_id_type owner; ///< Who is able to withdraw the balance
|
||||
asset amount;
|
||||
vesting_policy_initializer policy;
|
||||
|
||||
account_id_type fee_payer()const { return creator; }
|
||||
void validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Withdraw from a vesting balance.
|
||||
* @ingroup operations
|
||||
*
|
||||
* Withdrawal from a not-completely-mature vesting balance
|
||||
* will result in paying fees.
|
||||
*
|
||||
* @return Nothing
|
||||
*/
|
||||
struct vesting_balance_withdraw_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 20*GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
vesting_balance_id_type vesting_balance;
|
||||
account_id_type owner; ///< Must be vesting_balance.owner
|
||||
asset amount;
|
||||
|
||||
account_id_type fee_payer()const { return owner; }
|
||||
void validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
}
|
||||
};
|
||||
|
||||
}} // graphene::chain
|
||||
FC_REFLECT( graphene::chain::vesting_balance_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_withdraw_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::vesting_balance_create_operation, (fee)(creator)(owner)(amount)(policy) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_withdraw_operation, (fee)(vesting_balance)(owner)(amount) )
|
||||
|
||||
FC_REFLECT(graphene::chain::linear_vesting_policy_initializer, (begin_timestamp)(vesting_cliff_seconds)(vesting_duration_seconds) )
|
||||
FC_REFLECT(graphene::chain::cdd_vesting_policy_initializer, (start_claim)(vesting_seconds) )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::vesting_policy_initializer )
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/memo.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @brief Create a new withdrawal permission
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation creates a withdrawal permission, which allows some authorized account to withdraw from an
|
||||
* authorizing account. This operation is primarily useful for scheduling recurring payments.
|
||||
*
|
||||
* Withdrawal permissions define withdrawal periods, which is a span of time during which the authorized account may
|
||||
* make a withdrawal. Any number of withdrawals may be made so long as the total amount withdrawn per period does
|
||||
* not exceed the limit for any given period.
|
||||
*
|
||||
* Withdrawal permissions authorize only a specific pairing, i.e. a permission only authorizes one specified
|
||||
* authorized account to withdraw from one specified authorizing account. Withdrawals are limited and may not exceet
|
||||
* the withdrawal limit. The withdrawal must be made in the same asset as the limit; attempts with withdraw any
|
||||
* other asset type will be rejected.
|
||||
*
|
||||
* The fee for this operation is paid by withdraw_from_account, and this account is required to authorize this
|
||||
* operation.
|
||||
*/
|
||||
struct withdraw_permission_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
/// The account authorizing withdrawals from its balances
|
||||
account_id_type withdraw_from_account;
|
||||
/// The account authorized to make withdrawals from withdraw_from_account
|
||||
account_id_type authorized_account;
|
||||
/// The maximum amount authorized_account is allowed to withdraw in a given withdrawal period
|
||||
asset withdrawal_limit;
|
||||
/// Length of the withdrawal period in seconds
|
||||
uint32_t withdrawal_period_sec;
|
||||
/// The number of withdrawal periods this permission is valid for
|
||||
uint32_t periods_until_expiration;
|
||||
/// Time at which the first withdrawal period begins; must be in the future
|
||||
time_point_sec period_start_time;
|
||||
|
||||
account_id_type fee_payer()const { return withdraw_from_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Update an existing withdraw permission
|
||||
* @ingroup operations
|
||||
*
|
||||
* This oeration is used to update the settings for an existing withdrawal permission. The accounts to withdraw to
|
||||
* and from may never be updated. The fields which may be updated are the withdrawal limit (both amount and asset
|
||||
* type may be updated), the withdrawal period length, the remaining number of periods until expiration, and the
|
||||
* starting time of the new period.
|
||||
*
|
||||
* Fee is paid by withdraw_from_account, which is required to authorize this operation
|
||||
*/
|
||||
struct withdraw_permission_update_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
/// This account pays the fee. Must match permission_to_update->withdraw_from_account
|
||||
account_id_type withdraw_from_account;
|
||||
/// The account authorized to make withdrawals. Must match permission_to_update->authorized_account
|
||||
account_id_type authorized_account;
|
||||
/// ID of the permission which is being updated
|
||||
withdraw_permission_id_type permission_to_update;
|
||||
/// New maximum amount the withdrawer is allowed to charge per withdrawal period
|
||||
asset withdrawal_limit;
|
||||
/// New length of the period between withdrawals
|
||||
uint32_t withdrawal_period_sec;
|
||||
/// New beginning of the next withdrawal period; must be in the future
|
||||
time_point_sec period_start_time;
|
||||
/// The new number of withdrawal periods for which this permission will be valid
|
||||
uint32_t periods_until_expiration;
|
||||
|
||||
account_id_type fee_payer()const { return withdraw_from_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Withdraw from an account which has published a withdrawal permission
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation is used to withdraw from an account which has authorized such a withdrawal. It may be executed at
|
||||
* most once per withdrawal period for the given permission. On execution, amount_to_withdraw is transferred from
|
||||
* withdraw_from_account to withdraw_to_account, assuming amount_to_withdraw is within the withdrawal limit. The
|
||||
* withdrawal permission will be updated to note that the withdrawal for the current period has occurred, and
|
||||
* further withdrawals will not be permitted until the next withdrawal period, assuming the permission has not
|
||||
* expired. This operation may be executed at any time within the current withdrawal period.
|
||||
*
|
||||
* Fee is paid by withdraw_to_account, which is required to authorize this operation
|
||||
*/
|
||||
struct withdraw_permission_claim_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {
|
||||
uint64_t fee = 20*GRAPHENE_BLOCKCHAIN_PRECISION;
|
||||
uint32_t price_per_kbyte = 10;
|
||||
};
|
||||
|
||||
/// Paid by withdraw_to_account
|
||||
asset fee;
|
||||
/// ID of the permission authorizing this withdrawal
|
||||
withdraw_permission_id_type withdraw_permission;
|
||||
/// Must match withdraw_permission->withdraw_from_account
|
||||
account_id_type withdraw_from_account;
|
||||
/// Must match withdraw_permision->authorized_account
|
||||
account_id_type withdraw_to_account;
|
||||
/// Amount to withdraw. Must not exceed withdraw_permission->withdrawal_limit
|
||||
asset amount_to_withdraw;
|
||||
/// Memo for withdraw_from_account. Should generally be encrypted with withdraw_from_account->memo_key
|
||||
optional<memo_data> memo;
|
||||
|
||||
account_id_type fee_payer()const { return withdraw_to_account; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& k)const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Delete an existing withdrawal permission
|
||||
* @ingroup operations
|
||||
*
|
||||
* This operation cancels a withdrawal permission, thus preventing any future withdrawals using that permission.
|
||||
*
|
||||
* Fee is paid by withdraw_from_account, which is required to authorize this operation
|
||||
*/
|
||||
struct withdraw_permission_delete_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 0; };
|
||||
|
||||
asset fee;
|
||||
/// Must match withdrawal_permission->withdraw_from_account. This account pays the fee.
|
||||
account_id_type withdraw_from_account;
|
||||
/// The account previously authorized to make withdrawals. Must match withdrawal_permission->authorized_account
|
||||
account_id_type authorized_account;
|
||||
/// ID of the permission to be revoked.
|
||||
withdraw_permission_id_type withdrawal_permission;
|
||||
|
||||
account_id_type fee_payer()const { return withdraw_from_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
} } // graphene::chain
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_update_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_claim_operation::fee_parameters_type, (fee)(price_per_kbyte) )
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_delete_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_create_operation, (fee)(withdraw_from_account)(authorized_account)
|
||||
(withdrawal_limit)(withdrawal_period_sec)(periods_until_expiration)(period_start_time) )
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_update_operation, (fee)(withdraw_from_account)(authorized_account)
|
||||
(permission_to_update)(withdrawal_limit)(withdrawal_period_sec)(period_start_time)(periods_until_expiration) )
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_claim_operation, (fee)(withdraw_permission)(withdraw_from_account)(withdraw_to_account)(amount_to_withdraw)(memo) );
|
||||
FC_REFLECT( graphene::chain::withdraw_permission_delete_operation, (fee)(withdraw_from_account)(authorized_account)
|
||||
(withdrawal_permission) )
|
||||
|
||||
59
libraries/chain/include/graphene/chain/protocol/witness.hpp
Normal file
59
libraries/chain/include/graphene/chain/protocol/witness.hpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @brief Create a witness object, as a bid to hold a witness position on the network.
|
||||
* @ingroup operations
|
||||
*
|
||||
* Accounts which wish to become witnesses may use this operation to create a witness object which stakeholders may
|
||||
* vote on to approve its position as a witness.
|
||||
*/
|
||||
struct witness_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
/// The account which owns the delegate. This account pays the fee for this operation.
|
||||
account_id_type witness_account;
|
||||
string url;
|
||||
public_key_type block_signing_key;
|
||||
secret_hash_type initial_secret;
|
||||
|
||||
account_id_type fee_payer()const { return witness_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup operations
|
||||
* Used to move witness pay from accumulated_income to their account balance.
|
||||
*
|
||||
* TODO: remove this operation, send witness pay into a vesting balance object and
|
||||
* have the witness claim the funds from there.
|
||||
*/
|
||||
struct witness_withdraw_pay_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
/// The account to pay. Must match from_witness->witness_account. This account pays the fee for this operation.
|
||||
account_id_type to_account;
|
||||
witness_id_type from_witness;
|
||||
share_type amount;
|
||||
|
||||
account_id_type fee_payer()const { return to_account; }
|
||||
void validate()const;
|
||||
};
|
||||
|
||||
|
||||
/// TODO: witness_resign_operation : public base_operation
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::witness_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::witness_withdraw_pay_operation::fee_parameters_type, (fee) )
|
||||
|
||||
FC_REFLECT( graphene::chain::witness_create_operation, (fee)(witness_account)(url)(block_signing_key)(initial_secret) )
|
||||
FC_REFLECT( graphene::chain::witness_withdraw_pay_operation, (fee)(from_witness)(to_account)(amount) )
|
||||
82
libraries/chain/include/graphene/chain/protocol/worker.hpp
Normal file
82
libraries/chain/include/graphene/chain/protocol/worker.hpp
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @defgroup workers The Blockchain Worker System
|
||||
* @ingroup operations
|
||||
*
|
||||
* Graphene blockchains allow the creation of special "workers" which are elected positions paid by the blockchain
|
||||
* for services they provide. There may be several types of workers, and the semantics of how and when they are paid
|
||||
* are defined by the @ref worker_type_enum enumeration. All workers are elected by core stakeholder approval, by
|
||||
* voting for or against them.
|
||||
*
|
||||
* Workers are paid from the blockchain's daily budget if their total approval (votes for - votes against) is
|
||||
* positive, ordered from most positive approval to least, until the budget is exhausted. Payments are processed at
|
||||
* the blockchain maintenance interval. If a worker does not have positive approval during payment processing, or if
|
||||
* the chain's budget is exhausted before the worker is paid, that worker is simply not paid at that interval.
|
||||
* Payment is not prorated based on percentage of the interval the worker was approved. If the chain attempts to pay
|
||||
* a worker, but the budget is insufficient to cover its entire pay, the worker is paid the remaining budget funds,
|
||||
* even though this does not fulfill his total pay. The worker will not receive extra pay to make up the difference
|
||||
* later. Worker pay is placed in a vesting balance and vests over the number of days specified at the worker's
|
||||
* creation.
|
||||
*
|
||||
* Once created, a worker is immutable and will be kept by the blockchain forever.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
struct vesting_balance_worker_initializer
|
||||
{
|
||||
uint16_t pay_vesting_period_days = 0;
|
||||
};
|
||||
|
||||
struct burn_worker_initializer
|
||||
{};
|
||||
|
||||
struct refund_worker_initializer
|
||||
{};
|
||||
|
||||
|
||||
typedef static_variant<
|
||||
refund_worker_initializer,
|
||||
vesting_balance_worker_initializer,
|
||||
burn_worker_initializer > worker_initializer;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Create a new worker object
|
||||
* @ingroup operations
|
||||
*/
|
||||
struct worker_create_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type { uint64_t fee = 5000*GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type owner;
|
||||
time_point_sec work_begin_date;
|
||||
time_point_sec work_end_date;
|
||||
share_type daily_pay;
|
||||
string name;
|
||||
string url;
|
||||
/// This should be set to the initializer appropriate for the type of worker to be created.
|
||||
worker_initializer initializer;
|
||||
|
||||
account_id_type fee_payer()const { return owner; }
|
||||
void validate()const;
|
||||
};
|
||||
///@}
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT( graphene::chain::vesting_balance_worker_initializer, (pay_vesting_period_days) )
|
||||
FC_REFLECT( graphene::chain::burn_worker_initializer, )
|
||||
FC_REFLECT( graphene::chain::refund_worker_initializer, )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::worker_initializer )
|
||||
|
||||
FC_REFLECT( graphene::chain::worker_create_operation::fee_parameters_type, (fee) )
|
||||
FC_REFLECT( graphene::chain::worker_create_operation,
|
||||
(fee)(owner)(work_begin_date)(work_end_date)(daily_pay)(name)(url)(initializer) )
|
||||
|
||||
|
|
@ -16,9 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
class database;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#pragma once
|
||||
#include <fc/io/raw.hpp>
|
||||
|
||||
#include <graphene/chain/transaction.hpp>
|
||||
#include <graphene/chain/protocol/transaction.hpp>
|
||||
#include <graphene/db/index.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
|
|||
|
|
@ -17,14 +17,16 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
#include <fc/static_variant.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/authority.hpp>
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/chain/protocol/authority.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
// needed to serialize witness_scheduler
|
||||
#include <fc/container/deque.hpp>
|
||||
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/witness_scheduler.hpp>
|
||||
#include <graphene/chain/witness_scheduler_rng.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,121 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/evaluator.hpp>
|
||||
#include <graphene/chain/worker_object.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* @defgroup worker_types Implementations of the various worker types in the system
|
||||
*
|
||||
* The system has various worker types, which do different things with the money they are paid. These worker types
|
||||
* and their semantics are specified here.
|
||||
*
|
||||
* All worker types exist as a struct containing the data this worker needs to evaluate, as well as a method
|
||||
* pay_worker, which takes a pay amount and a non-const database reference, and applies the worker's specific pay
|
||||
* semantics to the worker_type struct and/or the database. Furthermore, all worker types have an initializer,
|
||||
* which is a struct containing the data needed to create that kind of worker.
|
||||
*
|
||||
* Each initializer type has a method, init, which takes a non-const database reference, a const reference to the
|
||||
* worker object being created, and a non-const reference to the specific *_worker_type object to initialize. The
|
||||
* init method creates any further objects, and initializes the worker_type object as necessary according to the
|
||||
* semantics of that particular worker type.
|
||||
*
|
||||
* To create a new worker type, define a my_new_worker_type struct with a pay_worker method which updates the
|
||||
* my_new_worker_type object and/or the database. Create a my_new_worker_type::initializer struct with an init
|
||||
* method and any data members necessary to create a new worker of this type. Reflect my_new_worker_type and
|
||||
* my_new_worker_type::initializer into FC's type system, and add them to @ref worker_type and @ref
|
||||
* worker_initializer respectively. Make sure the order of types in @ref worker_type and @ref worker_initializer
|
||||
* remains the same.
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief A worker who returns all of his pay to the reserve
|
||||
*
|
||||
* This worker type pays everything he receives back to the network's reserve funds pool.
|
||||
*/
|
||||
struct refund_worker_type
|
||||
{
|
||||
/// Record of how much this worker has burned in his lifetime
|
||||
share_type total_burned;
|
||||
|
||||
void pay_worker(share_type pay, database&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A worker who sends his pay to a vesting balance
|
||||
*
|
||||
* This worker type takes all of his pay and places it into a vesting balance
|
||||
*/
|
||||
struct vesting_balance_worker_type
|
||||
{
|
||||
/// The balance this worker pays into
|
||||
vesting_balance_id_type balance;
|
||||
|
||||
void pay_worker(share_type pay, database& db);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A worker who permanently destroys all of his pay
|
||||
*
|
||||
* This worker sends all pay he receives to the null account.
|
||||
*/
|
||||
struct burn_worker_type
|
||||
{
|
||||
/// Record of how much this worker has burned in his lifetime
|
||||
share_type total_burned;
|
||||
|
||||
void pay_worker(share_type pay, database&);
|
||||
};
|
||||
///@}
|
||||
|
||||
// The ordering of types in these two static variants MUST be the same.
|
||||
typedef static_variant<
|
||||
refund_worker_type,
|
||||
vesting_balance_worker_type,
|
||||
burn_worker_type
|
||||
> worker_type;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Worker object contains the details of a blockchain worker. See @ref workers for details.
|
||||
*/
|
||||
class worker_object : public abstract_object<worker_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = worker_object_type;
|
||||
|
||||
/// ID of the account which owns this worker
|
||||
account_id_type worker_account;
|
||||
/// Time at which this worker begins receiving pay, if elected
|
||||
time_point_sec work_begin_date;
|
||||
/// Time at which this worker will cease to receive pay. Worker will be deleted at this time
|
||||
time_point_sec work_end_date;
|
||||
/// Amount in CORE this worker will be paid each day
|
||||
share_type daily_pay;
|
||||
/// ID of this worker's pay balance
|
||||
worker_type worker;
|
||||
/// Human-readable name for the worker
|
||||
string name;
|
||||
/// URL to a web page representing this worker
|
||||
string url;
|
||||
|
||||
/// Voting ID which represents approval of this worker
|
||||
vote_id_type vote_for;
|
||||
/// Voting ID which represents disapproval of this worker
|
||||
vote_id_type vote_against;
|
||||
|
||||
bool is_active(fc::time_point_sec now)const {
|
||||
return now >= work_begin_date && now <= work_end_date;
|
||||
}
|
||||
share_type approving_stake(const vector<uint64_t>& stake_vote_tallies)const {
|
||||
return stake_vote_tallies[vote_for] - stake_vote_tallies[vote_against];
|
||||
}
|
||||
};
|
||||
|
||||
typedef flat_index<worker_object> worker_index;
|
||||
|
||||
|
||||
class worker_create_evaluator : public evaluator<worker_create_evaluator>
|
||||
{
|
||||
public:
|
||||
|
|
@ -31,3 +142,19 @@ namespace graphene { namespace chain {
|
|||
};
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::refund_worker_type, (total_burned) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_worker_type, (balance) )
|
||||
FC_REFLECT( graphene::chain::burn_worker_type, (total_burned) )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::worker_type )
|
||||
FC_REFLECT_DERIVED( graphene::chain::worker_object, (graphene::db::object),
|
||||
(worker_account)
|
||||
(work_begin_date)
|
||||
(work_end_date)
|
||||
(daily_pay)
|
||||
(worker)
|
||||
(vote_for)
|
||||
(vote_against)
|
||||
(name)
|
||||
(url)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
|
||||
#include <graphene/db/flat_index.hpp>
|
||||
|
||||
#include <fc/static_variant.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
using namespace graphene::db;
|
||||
class database;
|
||||
|
||||
/**
|
||||
* @defgroup worker_types Implementations of the various worker types in the system
|
||||
*
|
||||
* The system has various worker types, which do different things with the money they are paid. These worker types
|
||||
* and their semantics are specified here.
|
||||
*
|
||||
* All worker types exist as a struct containing the data this worker needs to evaluate, as well as a method
|
||||
* pay_worker, which takes a pay amount and a non-const database reference, and applies the worker's specific pay
|
||||
* semantics to the worker_type struct and/or the database. Furthermore, all worker types have an initializer,
|
||||
* which is a struct containing the data needed to create that kind of worker.
|
||||
*
|
||||
* Each initializer type has a method, init, which takes a non-const database reference, a const reference to the
|
||||
* worker object being created, and a non-const reference to the specific *_worker_type object to initialize. The
|
||||
* init method creates any further objects, and initializes the worker_type object as necessary according to the
|
||||
* semantics of that particular worker type.
|
||||
*
|
||||
* To create a new worker type, define a my_new_worker_type struct with a pay_worker method which updates the
|
||||
* my_new_worker_type object and/or the database. Create a my_new_worker_type::initializer struct with an init
|
||||
* method and any data members necessary to create a new worker of this type. Reflect my_new_worker_type and
|
||||
* my_new_worker_type::initializer into FC's type system, and add them to @ref worker_type and @ref
|
||||
* worker_initializer respectively. Make sure the order of types in @ref worker_type and @ref worker_initializer
|
||||
* remains the same.
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief A worker who returns all of his pay to the reserve
|
||||
*
|
||||
* This worker type pays everything he receives back to the network's reserve funds pool.
|
||||
*/
|
||||
struct refund_worker_type
|
||||
{
|
||||
/// Record of how much this worker has burned in his lifetime
|
||||
share_type total_burned;
|
||||
|
||||
void pay_worker(share_type pay, database&);
|
||||
|
||||
struct initializer
|
||||
{
|
||||
void init(database&, const worker_object&, refund_worker_type&)const
|
||||
{}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A worker who sends his pay to a vesting balance
|
||||
*
|
||||
* This worker type takes all of his pay and places it into a vesting balance
|
||||
*/
|
||||
struct vesting_balance_worker_type
|
||||
{
|
||||
/// The balance this worker pays into
|
||||
vesting_balance_id_type balance;
|
||||
|
||||
void pay_worker(share_type pay, database& db);
|
||||
|
||||
struct initializer
|
||||
{
|
||||
initializer(uint16_t vesting_period = 0)
|
||||
: pay_vesting_period_days(vesting_period) {}
|
||||
|
||||
void init(database& db, const worker_object& obj, vesting_balance_worker_type& worker)const;
|
||||
|
||||
uint16_t pay_vesting_period_days;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A worker who permanently destroys all of his pay
|
||||
*
|
||||
* This worker sends all pay he receives to the null account.
|
||||
*/
|
||||
struct burn_worker_type
|
||||
{
|
||||
/// Record of how much this worker has burned in his lifetime
|
||||
share_type total_burned;
|
||||
|
||||
void pay_worker(share_type pay, database&);
|
||||
|
||||
struct initializer
|
||||
{
|
||||
void init(database&, const worker_object&, burn_worker_type& worker)const
|
||||
{}
|
||||
};
|
||||
};
|
||||
///@}
|
||||
|
||||
// The ordering of types in these two static variants MUST be the same.
|
||||
typedef static_variant<
|
||||
refund_worker_type,
|
||||
vesting_balance_worker_type,
|
||||
burn_worker_type
|
||||
> worker_type;
|
||||
typedef static_variant<
|
||||
refund_worker_type::initializer,
|
||||
vesting_balance_worker_type::initializer,
|
||||
burn_worker_type::initializer
|
||||
> worker_initializer;
|
||||
|
||||
/// @brief A visitor for @ref worker_type which initializes the worker within
|
||||
struct worker_initialize_visitor
|
||||
{
|
||||
private:
|
||||
const worker_object& worker_obj;
|
||||
const worker_initializer& initializer;
|
||||
database& db;
|
||||
|
||||
public:
|
||||
worker_initialize_visitor(const worker_object& worker, const worker_initializer& initializer, database& db)
|
||||
: worker_obj(worker),initializer(initializer),db(db) {}
|
||||
|
||||
typedef void result_type;
|
||||
template<typename WorkerType>
|
||||
void operator()( WorkerType& worker)const
|
||||
{
|
||||
static_assert(worker_type::tag<WorkerType>::value ==
|
||||
worker_initializer::tag<typename WorkerType::initializer>::value,
|
||||
"Tag values for worker_type and worker_initializer do not match! "
|
||||
"Are the types in these static_variants in the same order?");
|
||||
initializer.get<typename WorkerType::initializer>().init(db, worker_obj, worker);
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief A visitor for @ref worker_type which calls pay_worker on the worker within
|
||||
struct worker_pay_visitor
|
||||
{
|
||||
private:
|
||||
share_type pay;
|
||||
database& db;
|
||||
|
||||
public:
|
||||
worker_pay_visitor(share_type pay, database& db)
|
||||
: pay(pay), db(db) {}
|
||||
|
||||
typedef void result_type;
|
||||
template<typename W>
|
||||
void operator()(W& worker)const
|
||||
{
|
||||
worker.pay_worker(pay, db);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Worker object contains the details of a blockchain worker. See @ref workers for details.
|
||||
*/
|
||||
class worker_object : public abstract_object<worker_object>
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = protocol_ids;
|
||||
static const uint8_t type_id = worker_object_type;
|
||||
|
||||
/// ID of the account which owns this worker
|
||||
account_id_type worker_account;
|
||||
/// Time at which this worker begins receiving pay, if elected
|
||||
time_point_sec work_begin_date;
|
||||
/// Time at which this worker will cease to receive pay. Worker will be deleted at this time
|
||||
time_point_sec work_end_date;
|
||||
/// Amount in CORE this worker will be paid each day
|
||||
share_type daily_pay;
|
||||
/// ID of this worker's pay balance
|
||||
worker_type worker;
|
||||
/// Human-readable name for the worker
|
||||
string name;
|
||||
/// URL to a web page representing this worker
|
||||
string url;
|
||||
|
||||
/// Voting ID which represents approval of this worker
|
||||
vote_id_type vote_for;
|
||||
/// Voting ID which represents disapproval of this worker
|
||||
vote_id_type vote_against;
|
||||
|
||||
bool is_active(fc::time_point_sec now)const {
|
||||
return now >= work_begin_date && now <= work_end_date;
|
||||
}
|
||||
share_type approving_stake(const vector<uint64_t>& stake_vote_tallies)const {
|
||||
return stake_vote_tallies[vote_for] - stake_vote_tallies[vote_against];
|
||||
}
|
||||
};
|
||||
|
||||
typedef flat_index<worker_object> worker_index;
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::refund_worker_type, (total_burned) )
|
||||
FC_REFLECT( graphene::chain::refund_worker_type::initializer, )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_worker_type, (balance) )
|
||||
FC_REFLECT( graphene::chain::vesting_balance_worker_type::initializer, (pay_vesting_period_days) )
|
||||
FC_REFLECT( graphene::chain::burn_worker_type, (total_burned) )
|
||||
FC_REFLECT( graphene::chain::burn_worker_type::initializer, )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::worker_type )
|
||||
FC_REFLECT_TYPENAME( graphene::chain::worker_initializer )
|
||||
FC_REFLECT_DERIVED( graphene::chain::worker_object, (graphene::db::object),
|
||||
(worker_account)
|
||||
(work_begin_date)
|
||||
(work_end_date)
|
||||
(daily_pay)
|
||||
(worker)
|
||||
(vote_for)
|
||||
(vote_against)
|
||||
(name)
|
||||
(url)
|
||||
)
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/limit_order_evaluator.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_operation& op)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
FC_ASSERT( op.expiration >= d.head_block_time() );
|
||||
|
||||
_seller = this->fee_paying_account;
|
||||
_sell_asset = &op.amount_to_sell.asset_id(d);
|
||||
_receive_asset = &op.min_to_receive.asset_id(d);
|
||||
|
||||
if( _sell_asset->options.whitelist_markets.size() )
|
||||
FC_ASSERT( _sell_asset->options.whitelist_markets.find(_receive_asset->id) != _sell_asset->options.whitelist_markets.end() );
|
||||
if( _sell_asset->options.blacklist_markets.size() )
|
||||
FC_ASSERT( _sell_asset->options.blacklist_markets.find(_receive_asset->id) == _sell_asset->options.blacklist_markets.end() );
|
||||
|
||||
if( _sell_asset->enforce_white_list() ) FC_ASSERT( _seller->is_authorized_asset( *_sell_asset ) );
|
||||
if( _receive_asset->enforce_white_list() ) FC_ASSERT( _seller->is_authorized_asset( *_receive_asset ) );
|
||||
|
||||
FC_ASSERT( d.get_balance( *_seller, *_sell_asset ) >= op.amount_to_sell, "insufficient balance",
|
||||
("balance",d.get_balance(*_seller,*_sell_asset))("amount_to_sell",op.amount_to_sell) );
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_operation& op)
|
||||
{ try {
|
||||
const auto& seller_stats = _seller->statistics(db());
|
||||
db().modify(seller_stats, [&](account_statistics_object& bal) {
|
||||
if( op.amount_to_sell.asset_id == asset_id_type() )
|
||||
{
|
||||
bal.total_core_in_orders += op.amount_to_sell.amount;
|
||||
}
|
||||
});
|
||||
|
||||
db().adjust_balance(op.seller, -op.amount_to_sell);
|
||||
|
||||
const auto& new_order_object = db().create<limit_order_object>([&](limit_order_object& obj){
|
||||
obj.seller = _seller->id;
|
||||
obj.for_sale = op.amount_to_sell.amount;
|
||||
obj.sell_price = op.get_price();
|
||||
obj.expiration = op.expiration;
|
||||
});
|
||||
limit_order_id_type order_id = new_order_object.id; // save this because we may remove the object by filling it
|
||||
bool filled = db().apply_order(new_order_object);
|
||||
|
||||
FC_ASSERT( !op.fill_or_kill || filled );
|
||||
|
||||
return order_id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
_order = &o.order(d);
|
||||
FC_ASSERT( _order->seller == o.fee_paying_account );
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
asset limit_order_cancel_evaluator::do_apply(const limit_order_cancel_operation& o)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
auto base_asset = _order->sell_price.base.asset_id;
|
||||
auto quote_asset = _order->sell_price.quote.asset_id;
|
||||
auto refunded = _order->amount_for_sale();
|
||||
|
||||
db().cancel_order(*_order, false /* don't create a virtual op*/);
|
||||
|
||||
// Possible optimization: order can be called by canceling a limit order iff the canceled order was at the top of the book.
|
||||
// Do I need to check calls in both assets?
|
||||
db().check_call_orders(base_asset(d));
|
||||
db().check_call_orders(quote_asset(d));
|
||||
|
||||
return refunded;
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -15,14 +15,88 @@
|
|||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/call_order_evaluator.hpp>
|
||||
#include <graphene/chain/market_evaluator.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/call_order_object.hpp>
|
||||
#include <graphene/chain/limit_order_object.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
void_result limit_order_create_evaluator::do_evaluate(const limit_order_create_operation& op)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
FC_ASSERT( op.expiration >= d.head_block_time() );
|
||||
|
||||
_seller = this->fee_paying_account;
|
||||
_sell_asset = &op.amount_to_sell.asset_id(d);
|
||||
_receive_asset = &op.min_to_receive.asset_id(d);
|
||||
|
||||
if( _sell_asset->options.whitelist_markets.size() )
|
||||
FC_ASSERT( _sell_asset->options.whitelist_markets.find(_receive_asset->id) != _sell_asset->options.whitelist_markets.end() );
|
||||
if( _sell_asset->options.blacklist_markets.size() )
|
||||
FC_ASSERT( _sell_asset->options.blacklist_markets.find(_receive_asset->id) == _sell_asset->options.blacklist_markets.end() );
|
||||
|
||||
if( _sell_asset->enforce_white_list() ) FC_ASSERT( _seller->is_authorized_asset( *_sell_asset ) );
|
||||
if( _receive_asset->enforce_white_list() ) FC_ASSERT( _seller->is_authorized_asset( *_receive_asset ) );
|
||||
|
||||
FC_ASSERT( d.get_balance( *_seller, *_sell_asset ) >= op.amount_to_sell, "insufficient balance",
|
||||
("balance",d.get_balance(*_seller,*_sell_asset))("amount_to_sell",op.amount_to_sell) );
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
object_id_type limit_order_create_evaluator::do_apply(const limit_order_create_operation& op)
|
||||
{ try {
|
||||
const auto& seller_stats = _seller->statistics(db());
|
||||
db().modify(seller_stats, [&](account_statistics_object& bal) {
|
||||
if( op.amount_to_sell.asset_id == asset_id_type() )
|
||||
{
|
||||
bal.total_core_in_orders += op.amount_to_sell.amount;
|
||||
}
|
||||
});
|
||||
|
||||
db().adjust_balance(op.seller, -op.amount_to_sell);
|
||||
|
||||
const auto& new_order_object = db().create<limit_order_object>([&](limit_order_object& obj){
|
||||
obj.seller = _seller->id;
|
||||
obj.for_sale = op.amount_to_sell.amount;
|
||||
obj.sell_price = op.get_price();
|
||||
obj.expiration = op.expiration;
|
||||
});
|
||||
limit_order_id_type order_id = new_order_object.id; // save this because we may remove the object by filling it
|
||||
bool filled = db().apply_order(new_order_object);
|
||||
|
||||
FC_ASSERT( !op.fill_or_kill || filled );
|
||||
|
||||
return order_id;
|
||||
} FC_CAPTURE_AND_RETHROW( (op) ) }
|
||||
|
||||
void_result limit_order_cancel_evaluator::do_evaluate(const limit_order_cancel_operation& o)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
_order = &o.order(d);
|
||||
FC_ASSERT( _order->seller == o.fee_paying_account );
|
||||
|
||||
return void_result();
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
asset limit_order_cancel_evaluator::do_apply(const limit_order_cancel_operation& o)
|
||||
{ try {
|
||||
database& d = db();
|
||||
|
||||
auto base_asset = _order->sell_price.base.asset_id;
|
||||
auto quote_asset = _order->sell_price.quote.asset_id;
|
||||
auto refunded = _order->amount_for_sale();
|
||||
|
||||
db().cancel_order(*_order, false /* don't create a virtual op*/);
|
||||
|
||||
// Possible optimization: order can be called by canceling a limit order iff the canceled order was at the top of the book.
|
||||
// Do I need to check calls in both assets?
|
||||
db().check_call_orders(base_asset(d));
|
||||
db().check_call_orders(quote_asset(d));
|
||||
|
||||
return refunded;
|
||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
||||
|
||||
void_result call_order_update_evaluator::do_evaluate(const call_order_update_operation& o)
|
||||
{ try {
|
||||
|
|
@ -1,965 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/operations.hpp>
|
||||
#include <graphene/chain/predicate.hpp>
|
||||
#include <fc/crypto/aes.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* Valid symbols can contain [A, Z], and '.'
|
||||
* They must start with [A, Z]
|
||||
* They must end with [A, Z]
|
||||
* They can contain a maximum of one '.'
|
||||
*/
|
||||
bool is_valid_symbol( const string& symbol )
|
||||
{
|
||||
if( symbol.size() < GRAPHENE_MIN_ASSET_SYMBOL_LENGTH )
|
||||
return false;
|
||||
|
||||
if( symbol.size() > GRAPHENE_MAX_ASSET_SYMBOL_LENGTH )
|
||||
return false;
|
||||
|
||||
if( !isalpha( symbol.front() ) )
|
||||
return false;
|
||||
|
||||
if( !isalpha( symbol.back() ) )
|
||||
return false;
|
||||
|
||||
bool dot_already_present = false;
|
||||
for( const auto c : symbol )
|
||||
{
|
||||
if( isalpha( c ) && isupper( c ) )
|
||||
continue;
|
||||
|
||||
if( c == '.' )
|
||||
{
|
||||
if( dot_already_present )
|
||||
return false;
|
||||
|
||||
dot_already_present = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Names must comply with the following grammar (RFC 1035):
|
||||
* <domain> ::= <subdomain> | " "
|
||||
* <subdomain> ::= <label> | <subdomain> "." <label>
|
||||
* <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
|
||||
* <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
||||
* <let-dig-hyp> ::= <let-dig> | "-"
|
||||
* <let-dig> ::= <letter> | <digit>
|
||||
*
|
||||
* Which is equivalent to the following:
|
||||
*
|
||||
* <domain> ::= <subdomain> | " "
|
||||
* <subdomain> ::= <label> ("." <label>)*
|
||||
* <label> ::= <letter> [ [ <let-dig-hyp>+ ] <let-dig> ]
|
||||
* <let-dig-hyp> ::= <let-dig> | "-"
|
||||
* <let-dig> ::= <letter> | <digit>
|
||||
*
|
||||
* I.e. a valid name consists of a dot-separated sequence
|
||||
* of one or more labels consisting of the following rules:
|
||||
*
|
||||
* - Each label is three characters or more
|
||||
* - Each label begins with a letter
|
||||
* - Each label ends with a letter or digit
|
||||
* - Each label contains only letters, digits or hyphens
|
||||
*
|
||||
* In addition we require the following:
|
||||
*
|
||||
* - All letters are lowercase
|
||||
* - Length is between (inclusive) GRAPHENE_MIN_ACCOUNT_NAME_LENGTH and GRAPHENE_MAX_ACCOUNT_NAME_LENGTH
|
||||
*/
|
||||
|
||||
bool is_valid_name( const string& name )
|
||||
{
|
||||
const size_t len = name.size();
|
||||
if( len < GRAPHENE_MIN_ACCOUNT_NAME_LENGTH )
|
||||
return false;
|
||||
|
||||
if( len > GRAPHENE_MAX_ACCOUNT_NAME_LENGTH )
|
||||
return false;
|
||||
|
||||
size_t begin = 0;
|
||||
while( true )
|
||||
{
|
||||
size_t end = name.find_first_of( '.', begin );
|
||||
if( end == std::string::npos )
|
||||
end = len;
|
||||
if( end - begin < 3 )
|
||||
return false;
|
||||
switch( name[begin] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch( name[end-1] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
for( size_t i=begin+1; i<end-1; i++ )
|
||||
{
|
||||
switch( name[i] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
case '-':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if( end == len )
|
||||
break;
|
||||
begin = end+1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_cheap_name( const string& n )
|
||||
{
|
||||
bool v = false;
|
||||
for( auto c : n )
|
||||
{
|
||||
if( c >= '0' && c <= '9' ) return true;
|
||||
if( c == '.' || c == '-' || c == '/' ) return true;
|
||||
switch( c )
|
||||
{
|
||||
case 'a':
|
||||
case 'e':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'y':
|
||||
v = true;
|
||||
}
|
||||
}
|
||||
if( !v )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
share_type account_create_operation::calculate_fee( const fee_schedule_type& schedule )const
|
||||
{
|
||||
auto core_fee_required = schedule.account_create_fee;
|
||||
|
||||
uint32_t s = name.size();
|
||||
if( is_cheap_name(name) )
|
||||
s = 8;
|
||||
|
||||
if( s >= 8 )
|
||||
core_fee_required = schedule.account_len8up_fee;
|
||||
else if( s == 7 )
|
||||
core_fee_required = schedule.account_len7_fee;
|
||||
else if( s == 6 )
|
||||
core_fee_required = schedule.account_len6_fee;
|
||||
else if( s == 5 )
|
||||
core_fee_required = schedule.account_len5_fee;
|
||||
else if( s == 4 )
|
||||
core_fee_required = schedule.account_len4_fee;
|
||||
else if( s == 3 )
|
||||
core_fee_required = schedule.account_len3_fee;
|
||||
else if( s <= 2 )
|
||||
core_fee_required = schedule.account_len2_fee;
|
||||
|
||||
// Authorities and vote lists can be arbitrarily large, so charge a data fee for big ones
|
||||
core_fee_required += schedule.total_data_fee(active, owner, options.votes);
|
||||
|
||||
return core_fee_required;
|
||||
}
|
||||
share_type account_update_operation::calculate_fee( const fee_schedule_type& schedule )const
|
||||
{
|
||||
auto core_fee_required = schedule.account_update_fee + schedule.total_data_fee(owner, active);
|
||||
if( new_options )
|
||||
core_fee_required += schedule.total_data_fee(new_options->votes);
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
void account_update_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( account != account_id_type() );
|
||||
FC_ASSERT( owner || active || new_options );
|
||||
if( owner )
|
||||
{
|
||||
FC_ASSERT( owner->num_auths() != 0 );
|
||||
FC_ASSERT( owner->address_auths.size() == 0 );
|
||||
}
|
||||
if( active )
|
||||
{
|
||||
FC_ASSERT( active->num_auths() != 0 );
|
||||
FC_ASSERT( active->address_auths.size() == 0 );
|
||||
}
|
||||
|
||||
if( new_options )
|
||||
new_options->validate();
|
||||
}
|
||||
|
||||
share_type asset_create_operation::calculate_fee(const fee_schedule_type& schedule)const
|
||||
{
|
||||
auto core_fee_required = schedule.asset_create_fee;
|
||||
|
||||
switch(symbol.size()) {
|
||||
case 3: core_fee_required += schedule.asset_len3_fee;
|
||||
break;
|
||||
case 4: core_fee_required += schedule.asset_len4_fee;
|
||||
break;
|
||||
case 5: core_fee_required += schedule.asset_len5_fee;
|
||||
break;
|
||||
case 6: core_fee_required += schedule.asset_len6_fee;
|
||||
break;
|
||||
default: core_fee_required += schedule.asset_len7up_fee;
|
||||
}
|
||||
|
||||
// common_options contains several lists and a string. Charge fees for its size
|
||||
core_fee_required += schedule.total_data_fee(common_options);
|
||||
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
share_type transfer_operation::calculate_fee( const fee_schedule_type& schedule )const
|
||||
{
|
||||
share_type core_fee_required = schedule.transfer_fee;
|
||||
if( memo )
|
||||
core_fee_required += schedule.total_data_fee(memo->message);
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
share_type override_transfer_operation::calculate_fee( const fee_schedule_type& schedule )const
|
||||
{
|
||||
share_type core_fee_required = schedule.transfer_fee;
|
||||
if( memo )
|
||||
core_fee_required += schedule.total_data_fee(memo->message);
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void account_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( is_valid_name( name ) );
|
||||
FC_ASSERT( referrer_percent <= GRAPHENE_100_PERCENT );
|
||||
FC_ASSERT( owner.num_auths() != 0 );
|
||||
FC_ASSERT( owner.address_auths.size() == 0 );
|
||||
// TODO: this asset causes many tests to fail, those tests should probably be updated
|
||||
//FC_ASSERT( active.num_auths() != 0 );
|
||||
FC_ASSERT( active.address_auths.size() == 0 );
|
||||
options.validate();
|
||||
}
|
||||
|
||||
|
||||
share_type asset_publish_feed_operation::calculate_fee( const fee_schedule_type& schedule )const
|
||||
{
|
||||
return schedule.publish_feed_fee;
|
||||
}
|
||||
|
||||
void asset_publish_feed_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
feed.validate();
|
||||
}
|
||||
|
||||
|
||||
void transfer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( from != to );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
}
|
||||
|
||||
void override_transfer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( from != to );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
FC_ASSERT( issuer != from );
|
||||
}
|
||||
|
||||
|
||||
void asset_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( is_valid_symbol(symbol) );
|
||||
common_options.validate();
|
||||
if( common_options.issuer_permissions & (disable_force_settle|global_settle) )
|
||||
FC_ASSERT( bitasset_options.valid() );
|
||||
if( is_prediction_market )
|
||||
{
|
||||
FC_ASSERT( bitasset_options.valid(), "Cannot have a User-Issued Asset implement a prediction market." );
|
||||
FC_ASSERT( common_options.issuer_permissions & global_settle );
|
||||
}
|
||||
if( bitasset_options ) bitasset_options->validate();
|
||||
|
||||
asset dummy = asset(1) * common_options.core_exchange_rate;
|
||||
FC_ASSERT(dummy.asset_id == asset_id_type(1));
|
||||
FC_ASSERT(precision <= 12);
|
||||
}
|
||||
|
||||
asset_update_operation::asset_update_operation(const asset_object& old)
|
||||
{
|
||||
issuer = old.issuer;
|
||||
asset_to_update = old.get_id();
|
||||
new_options = old.options;
|
||||
}
|
||||
|
||||
|
||||
void asset_update_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
if( new_issuer )
|
||||
FC_ASSERT(issuer != *new_issuer);
|
||||
new_options.validate();
|
||||
|
||||
asset dummy = asset(1, asset_to_update) * new_options.core_exchange_rate;
|
||||
FC_ASSERT(dummy.asset_id == asset_id_type());
|
||||
}
|
||||
|
||||
share_type asset_update_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
return k.asset_update_fee + k.total_data_fee(new_options);
|
||||
}
|
||||
|
||||
|
||||
void asset_reserve_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount_to_reserve.amount.value <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
FC_ASSERT( amount_to_reserve.amount.value > 0 );
|
||||
}
|
||||
|
||||
share_type asset_reserve_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
return k.asset_reserve_fee;
|
||||
}
|
||||
|
||||
|
||||
void asset_issue_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( asset_to_issue.amount.value <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
FC_ASSERT( asset_to_issue.amount.value > 0 );
|
||||
FC_ASSERT( asset_to_issue.asset_id != 0 );
|
||||
}
|
||||
|
||||
share_type asset_issue_operation::calculate_fee( const fee_schedule_type& k )const
|
||||
{
|
||||
return k.asset_issue_fee;
|
||||
}
|
||||
|
||||
share_type delegate_create_operation::calculate_fee( const fee_schedule_type& k )const
|
||||
{
|
||||
return k.delegate_create_fee + k.total_data_fee(url);
|
||||
}
|
||||
|
||||
|
||||
void delegate_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT(url.size() < GRAPHENE_MAX_URL_LENGTH );
|
||||
}
|
||||
|
||||
|
||||
void asset_fund_fee_pool_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( fee.asset_id == asset_id_type() );
|
||||
FC_ASSERT( amount > 0 );
|
||||
}
|
||||
|
||||
share_type asset_fund_fee_pool_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.asset_fund_fee_pool_fee;
|
||||
}
|
||||
|
||||
|
||||
void limit_order_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( amount_to_sell.asset_id != min_to_receive.asset_id );
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount_to_sell.amount > 0 );
|
||||
FC_ASSERT( min_to_receive.amount > 0 );
|
||||
}
|
||||
|
||||
share_type limit_order_create_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.limit_order_create_fee;
|
||||
}
|
||||
|
||||
|
||||
void limit_order_cancel_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
share_type limit_order_cancel_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.get_extended_fee(fee_schedule_type::limit_order_cancel_fee_id);
|
||||
}
|
||||
|
||||
|
||||
void call_order_update_operation::validate()const
|
||||
{ try {
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( delta_collateral.asset_id != delta_debt.asset_id );
|
||||
FC_ASSERT( delta_collateral.amount != 0 || delta_debt.amount != 0 );
|
||||
} FC_CAPTURE_AND_RETHROW((*this)) }
|
||||
|
||||
share_type call_order_update_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.call_order_fee;
|
||||
}
|
||||
|
||||
proposal_create_operation proposal_create_operation::genesis_proposal(const database& db)
|
||||
{
|
||||
auto global_params = db.get_global_properties().parameters;
|
||||
proposal_create_operation op = {account_id_type(), asset(), {},
|
||||
db.head_block_time() + global_params.maximum_proposal_lifetime,
|
||||
global_params.genesis_proposal_review_period};
|
||||
op.fee = op.calculate_fee(global_params.current_fees);
|
||||
return op;
|
||||
}
|
||||
|
||||
|
||||
void proposal_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( !proposed_ops.empty() );
|
||||
for( const auto& op : proposed_ops ) op.validate();
|
||||
}
|
||||
|
||||
share_type proposal_create_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.proposal_create_fee + k.total_data_fee(proposed_ops);
|
||||
}
|
||||
|
||||
|
||||
void proposal_update_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0);
|
||||
FC_ASSERT(!(active_approvals_to_add.empty() && active_approvals_to_remove.empty() &&
|
||||
owner_approvals_to_add.empty() && owner_approvals_to_remove.empty() &&
|
||||
key_approvals_to_add.empty() && key_approvals_to_remove.empty()));
|
||||
for( auto a : active_approvals_to_add )
|
||||
{
|
||||
FC_ASSERT(active_approvals_to_remove.find(a) == active_approvals_to_remove.end(),
|
||||
"Cannot add and remove approval at the same time.");
|
||||
}
|
||||
for( auto a : owner_approvals_to_add )
|
||||
{
|
||||
FC_ASSERT(owner_approvals_to_remove.find(a) == owner_approvals_to_remove.end(),
|
||||
"Cannot add and remove approval at the same time.");
|
||||
}
|
||||
for( auto a : key_approvals_to_add )
|
||||
{
|
||||
FC_ASSERT(key_approvals_to_remove.find(a) == key_approvals_to_remove.end(),
|
||||
"Cannot add and remove approval at the same time.");
|
||||
}
|
||||
}
|
||||
|
||||
share_type proposal_update_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.proposal_create_fee + k.total_data_fee(active_approvals_to_add,
|
||||
active_approvals_to_remove,
|
||||
owner_approvals_to_add,
|
||||
owner_approvals_to_remove,
|
||||
key_approvals_to_add,
|
||||
key_approvals_to_remove);
|
||||
}
|
||||
|
||||
share_type proposal_delete_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{ return k.get_extended_fee( fee_schedule_type::proposal_delete_fee_id ); }
|
||||
|
||||
void account_transfer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
|
||||
share_type account_transfer_operation::calculate_fee( const fee_schedule_type& k )const
|
||||
{
|
||||
return k.account_transfer_fee;
|
||||
}
|
||||
|
||||
|
||||
void proposal_delete_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
|
||||
void witness_withdraw_pay_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount >= 0 );
|
||||
}
|
||||
|
||||
share_type witness_withdraw_pay_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.witness_withdraw_pay_fee;
|
||||
}
|
||||
|
||||
|
||||
void global_parameters_update_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
new_parameters.validate();
|
||||
}
|
||||
|
||||
share_type global_parameters_update_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.global_parameters_update_fee;
|
||||
}
|
||||
|
||||
|
||||
void witness_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0);
|
||||
FC_ASSERT(url.size() < GRAPHENE_MAX_URL_LENGTH );
|
||||
}
|
||||
|
||||
share_type witness_create_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.witness_create_fee + k.total_data_fee(url);
|
||||
}
|
||||
|
||||
|
||||
void withdraw_permission_update_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( withdrawal_limit.amount > 0 );
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( withdrawal_period_sec > 0 );
|
||||
FC_ASSERT( withdraw_from_account != authorized_account );
|
||||
FC_ASSERT( periods_until_expiration > 0 );
|
||||
}
|
||||
|
||||
share_type withdraw_permission_update_operation::calculate_fee( const fee_schedule_type& schedule )const
|
||||
{
|
||||
return schedule.withdraw_permission_update_fee;
|
||||
}
|
||||
|
||||
void withdraw_permission_claim_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( withdraw_to_account != withdraw_from_account );
|
||||
FC_ASSERT( amount_to_withdraw.amount > 0 );
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
share_type withdraw_permission_claim_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
share_type core_fee_required = k.withdraw_permission_claim_fee;
|
||||
if( memo )
|
||||
core_fee_required += k.total_data_fee(memo->message);
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
|
||||
void withdraw_permission_delete_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( withdraw_from_account != authorized_account );
|
||||
}
|
||||
|
||||
share_type withdraw_permission_delete_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.get_extended_fee( fee_schedule_type::withdraw_permission_delete_fee_id );
|
||||
}
|
||||
|
||||
|
||||
void withdraw_permission_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( withdraw_from_account != authorized_account );
|
||||
FC_ASSERT( withdrawal_limit.amount > 0 );
|
||||
//TODO: better bounds checking on these values
|
||||
FC_ASSERT( withdrawal_period_sec > 0 );
|
||||
FC_ASSERT( periods_until_expiration > 0 );
|
||||
}
|
||||
|
||||
share_type withdraw_permission_create_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.withdraw_permission_create_fee;
|
||||
}
|
||||
|
||||
void asset_global_settle_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( asset_to_settle == settle_price.base.asset_id );
|
||||
}
|
||||
|
||||
share_type asset_global_settle_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
return k.asset_global_settle_fee;
|
||||
}
|
||||
|
||||
|
||||
void asset_settle_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount.amount >= 0 );
|
||||
}
|
||||
|
||||
share_type asset_settle_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.asset_settle_fee;
|
||||
}
|
||||
|
||||
|
||||
void asset_update_bitasset_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
new_options.validate();
|
||||
}
|
||||
|
||||
share_type asset_update_bitasset_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
return k.asset_update_fee;
|
||||
}
|
||||
|
||||
void asset_update_feed_producers_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
share_type asset_update_feed_producers_operation::calculate_fee(const fee_schedule_type &k) const
|
||||
{
|
||||
return k.asset_update_fee + k.total_data_fee(new_feed_producers);
|
||||
}
|
||||
|
||||
share_type vesting_balance_create_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
// We don't want to have custom inspection for each policy type; instead, charge a data fee for big ones
|
||||
return k.vesting_balance_create_fee + k.total_data_fee(policy);
|
||||
}
|
||||
|
||||
void vesting_balance_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
}
|
||||
|
||||
void vesting_balance_withdraw_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
}
|
||||
|
||||
share_type vesting_balance_withdraw_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
return k.vesting_balance_withdraw_fee;
|
||||
}
|
||||
|
||||
void memo_data::set_message(const fc::ecc::private_key& priv, const fc::ecc::public_key& pub,
|
||||
const string& msg, uint64_t custom_nonce)
|
||||
{
|
||||
if( from != public_key_type() )
|
||||
{
|
||||
if( custom_nonce == 0 )
|
||||
{
|
||||
uint64_t entropy = fc::sha224::hash(fc::ecc::private_key::generate())._hash[0];
|
||||
entropy <<= 32;
|
||||
entropy &= 0xff00000000000000;
|
||||
nonce = (fc::time_point::now().time_since_epoch().count() & 0x00ffffffffffffff) | entropy;
|
||||
} else
|
||||
nonce = custom_nonce;
|
||||
auto secret = priv.get_shared_secret(pub);
|
||||
auto nonce_plus_secret = fc::sha512::hash(fc::to_string(nonce) + secret.str());
|
||||
string text = memo_message(digest_type::hash(msg)._hash[0], msg).serialize();
|
||||
message = fc::aes_encrypt( nonce_plus_secret, vector<char>(text.begin(), text.end()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto text = memo_message(0, msg).serialize();
|
||||
message = vector<char>(text.begin(), text.end());
|
||||
}
|
||||
}
|
||||
|
||||
string memo_data::get_message(const fc::ecc::private_key& priv,
|
||||
const fc::ecc::public_key& pub)const
|
||||
{
|
||||
if( from != public_key_type() )
|
||||
{
|
||||
auto secret = priv.get_shared_secret(pub);
|
||||
auto nonce_plus_secret = fc::sha512::hash(fc::to_string(nonce) + secret.str());
|
||||
auto plain_text = fc::aes_decrypt( nonce_plus_secret, message );
|
||||
auto result = memo_message::deserialize(string(plain_text.begin(), plain_text.end()));
|
||||
FC_ASSERT( result.checksum == uint32_t(digest_type::hash(result.text)._hash[0]) );
|
||||
return result.text;
|
||||
}
|
||||
else
|
||||
{
|
||||
return memo_message::deserialize(string(message.begin(), message.end())).text;
|
||||
}
|
||||
}
|
||||
|
||||
void custom_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount > 0 );
|
||||
}
|
||||
share_type custom_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
return k.custom_operation_fee + k.total_data_fee(required_auths, data);
|
||||
}
|
||||
|
||||
void worker_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0);
|
||||
FC_ASSERT(work_end_date > work_begin_date);
|
||||
FC_ASSERT(daily_pay > 0);
|
||||
FC_ASSERT(daily_pay < GRAPHENE_MAX_SHARE_SUPPLY);
|
||||
FC_ASSERT(name.size() < GRAPHENE_MAX_WORKER_NAME_LENGTH );
|
||||
FC_ASSERT(url.size() < GRAPHENE_MAX_URL_LENGTH );
|
||||
}
|
||||
|
||||
share_type worker_create_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
// Charge data fees for excessively long name, URL, or large initializers
|
||||
return k.worker_create_fee + k.total_data_fee(name, url, initializer);
|
||||
}
|
||||
|
||||
string memo_message::serialize() const
|
||||
{
|
||||
auto serial_checksum = string(sizeof(checksum), ' ');
|
||||
(uint32_t&)(*serial_checksum.data()) = checksum;
|
||||
return serial_checksum + text;
|
||||
}
|
||||
|
||||
memo_message memo_message::deserialize(const string& serial)
|
||||
{
|
||||
memo_message result;
|
||||
FC_ASSERT( serial.size() >= sizeof(result.checksum) );
|
||||
result.checksum = ((uint32_t&)(*serial.data()));
|
||||
result.text = serial.substr(sizeof(result.checksum));
|
||||
return result;
|
||||
}
|
||||
|
||||
void account_upgrade_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
share_type account_upgrade_operation::calculate_fee(const fee_schedule_type& k) const
|
||||
{
|
||||
if( upgrade_to_lifetime_member )
|
||||
return k.membership_lifetime_fee;
|
||||
return k.membership_annual_fee;
|
||||
}
|
||||
|
||||
struct predicate_validator
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
template<typename T>
|
||||
void operator()( const T& p )const
|
||||
{
|
||||
p.validate();
|
||||
}
|
||||
};
|
||||
|
||||
void assert_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
for( const auto& item : predicates )
|
||||
{
|
||||
FC_ASSERT( item.size() > 0 );
|
||||
fc::datastream<const char*> ds( item.data(), item.size() );
|
||||
predicate p;
|
||||
try {
|
||||
fc::raw::unpack( ds, p );
|
||||
}
|
||||
catch ( const fc::exception& e )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
p.visit( predicate_validator() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The fee for assert operations is proportional to their size,
|
||||
* but cheaper than a data fee because they require no storage
|
||||
*/
|
||||
share_type assert_operation::calculate_fee(const fee_schedule_type& k)const
|
||||
{
|
||||
return std::max(size_t(1), fc::raw::pack_size(*this) / 1024) * k.assert_op_fee;
|
||||
}
|
||||
|
||||
void balance_claim_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee == asset() );
|
||||
FC_ASSERT( balance_owner_key != public_key_type() );
|
||||
}
|
||||
|
||||
struct required_auth_visitor
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
vector<authority>& result;
|
||||
|
||||
required_auth_visitor( vector<authority>& r ):result(r){}
|
||||
|
||||
/** for most operations this is a no-op */
|
||||
template<typename T>
|
||||
void operator()(const T& )const {}
|
||||
|
||||
void operator()( const balance_claim_operation& o )const
|
||||
{
|
||||
result.push_back( authority( 1, o.balance_owner_key, 1 ) );
|
||||
}
|
||||
};
|
||||
|
||||
struct required_active_visitor
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
flat_set<account_id_type>& result;
|
||||
|
||||
required_active_visitor( flat_set<account_id_type>& r ):result(r){}
|
||||
|
||||
/** for most operations this is just the fee payer */
|
||||
template<typename T>
|
||||
void operator()(const T& o)const
|
||||
{
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
void operator()(const account_update_operation& o)const
|
||||
{
|
||||
/// if owner authority is required, no active authority is required
|
||||
if( !(o.owner || o.active) ) /// TODO: document why active cannot be updated by active?
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
void operator()( const proposal_delete_operation& o )const
|
||||
{
|
||||
if( !o.using_owner_authority )
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
|
||||
void operator()( const proposal_update_operation& o )const
|
||||
{
|
||||
result.insert( o.fee_payer() );
|
||||
for( auto id : o.active_approvals_to_add )
|
||||
result.insert(id);
|
||||
for( auto id : o.active_approvals_to_remove )
|
||||
result.insert(id);
|
||||
}
|
||||
void operator()( const custom_operation& o )const
|
||||
{
|
||||
result.insert( o.required_auths.begin(), o.required_auths.end() );
|
||||
}
|
||||
void operator()( const assert_operation& o )const
|
||||
{
|
||||
result.insert( o.fee_payer() );
|
||||
result.insert( o.required_auths.begin(), o.required_auths.end() );
|
||||
}
|
||||
};
|
||||
|
||||
struct required_owner_visitor
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
flat_set<account_id_type>& result;
|
||||
|
||||
required_owner_visitor( flat_set<account_id_type>& r ):result(r){}
|
||||
|
||||
/** for most operations this is a no-op */
|
||||
template<typename T>
|
||||
void operator()(const T& o)const {}
|
||||
|
||||
void operator()(const account_update_operation& o)const
|
||||
{
|
||||
if( o.owner || o.active ) /// TODO: document why active cannot be updated by active?
|
||||
result.insert( o.account );
|
||||
}
|
||||
|
||||
void operator()( const proposal_delete_operation& o )const
|
||||
{
|
||||
if( o.using_owner_authority )
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
|
||||
void operator()( const proposal_update_operation& o )const
|
||||
{
|
||||
for( auto id : o.owner_approvals_to_add )
|
||||
result.insert(id);
|
||||
for( auto id : o.owner_approvals_to_remove )
|
||||
result.insert(id);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void operation_get_required_authorities( const operation& op, vector<authority>& result )
|
||||
{
|
||||
op.visit( required_auth_visitor( result ) );
|
||||
}
|
||||
void operation_get_required_active_authorities( const operation& op, flat_set<account_id_type>& result )
|
||||
{
|
||||
op.visit( required_active_visitor( result ) );
|
||||
}
|
||||
void operation_get_required_owner_authorities( const operation& op, flat_set<account_id_type>& result )
|
||||
{
|
||||
op.visit( required_owner_visitor( result ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Used to validate operations in a polymorphic manner
|
||||
*/
|
||||
struct operation_validator
|
||||
{
|
||||
typedef void result_type;
|
||||
template<typename T>
|
||||
void operator()( const T& v )const { v.validate(); }
|
||||
};
|
||||
|
||||
void operation_validate( const operation& op )
|
||||
{
|
||||
op.visit( operation_validator() );
|
||||
}
|
||||
|
||||
void op_wrapper::validate()const
|
||||
{
|
||||
operation_validate(op);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace graphene::chain
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include <graphene/chain/proposal_evaluator.hpp>
|
||||
#include <graphene/chain/proposal_object.hpp>
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
|
@ -35,11 +36,14 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
|
|||
{
|
||||
// If we're dealing with the genesis authority, make sure this transaction has a sufficient review period.
|
||||
flat_set<account_id_type> auths;
|
||||
vector<authority> other;
|
||||
for( auto& op : o.proposed_ops )
|
||||
{
|
||||
operation_get_required_active_authorities(op.op, auths);
|
||||
operation_get_required_owner_authorities(op.op, auths);
|
||||
operation_get_required_authorities(op.op, auths, auths, other);
|
||||
}
|
||||
|
||||
FC_ASSERT( other.size() == 0 ); // TODO: what about other???
|
||||
|
||||
if( auths.find(account_id_type()) != auths.end() )
|
||||
FC_ASSERT( o.review_period_seconds
|
||||
&& *o.review_period_seconds >= global_parameters.genesis_proposal_review_period );
|
||||
|
|
@ -64,12 +68,11 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati
|
|||
|
||||
//Populate the required approval sets
|
||||
flat_set<account_id_type> required_active;
|
||||
|
||||
vector<authority> other;
|
||||
|
||||
// TODO: consider caching values from evaluate?
|
||||
for( auto& op : _proposed_trx.operations )
|
||||
{
|
||||
operation_get_required_active_authorities(op, required_active);
|
||||
operation_get_required_owner_authorities(op, proposal.required_owner_approvals);
|
||||
}
|
||||
operation_get_required_authorities(op, required_active, proposal.required_owner_approvals, other);
|
||||
|
||||
//All accounts which must provide both owner and active authority should be omitted from the active authority set;
|
||||
//owner authority approval implies active authority approval.
|
||||
|
|
|
|||
198
libraries/chain/protocol/account.cpp
Normal file
198
libraries/chain/protocol/account.cpp
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
#include <graphene/chain/protocol/account.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* Names must comply with the following grammar (RFC 1035):
|
||||
* <domain> ::= <subdomain> | " "
|
||||
* <subdomain> ::= <label> | <subdomain> "." <label>
|
||||
* <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
|
||||
* <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
||||
* <let-dig-hyp> ::= <let-dig> | "-"
|
||||
* <let-dig> ::= <letter> | <digit>
|
||||
*
|
||||
* Which is equivalent to the following:
|
||||
*
|
||||
* <domain> ::= <subdomain> | " "
|
||||
* <subdomain> ::= <label> ("." <label>)*
|
||||
* <label> ::= <letter> [ [ <let-dig-hyp>+ ] <let-dig> ]
|
||||
* <let-dig-hyp> ::= <let-dig> | "-"
|
||||
* <let-dig> ::= <letter> | <digit>
|
||||
*
|
||||
* I.e. a valid name consists of a dot-separated sequence
|
||||
* of one or more labels consisting of the following rules:
|
||||
*
|
||||
* - Each label is three characters or more
|
||||
* - Each label begins with a letter
|
||||
* - Each label ends with a letter or digit
|
||||
* - Each label contains only letters, digits or hyphens
|
||||
*
|
||||
* In addition we require the following:
|
||||
*
|
||||
* - All letters are lowercase
|
||||
* - Length is between (inclusive) GRAPHENE_MIN_ACCOUNT_NAME_LENGTH and GRAPHENE_MAX_ACCOUNT_NAME_LENGTH
|
||||
*/
|
||||
bool is_valid_name( const string& name )
|
||||
{
|
||||
const size_t len = name.size();
|
||||
if( len < GRAPHENE_MIN_ACCOUNT_NAME_LENGTH )
|
||||
return false;
|
||||
|
||||
if( len > GRAPHENE_MAX_ACCOUNT_NAME_LENGTH )
|
||||
return false;
|
||||
|
||||
size_t begin = 0;
|
||||
while( true )
|
||||
{
|
||||
size_t end = name.find_first_of( '.', begin );
|
||||
if( end == std::string::npos )
|
||||
end = len;
|
||||
if( end - begin < 3 )
|
||||
return false;
|
||||
switch( name[begin] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch( name[end-1] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
for( size_t i=begin+1; i<end-1; i++ )
|
||||
{
|
||||
switch( name[i] )
|
||||
{
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h':
|
||||
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p':
|
||||
case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
||||
case 'y': case 'z':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
|
||||
case '8': case '9':
|
||||
case '-':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if( end == len )
|
||||
break;
|
||||
begin = end+1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_cheap_name( const string& n )
|
||||
{
|
||||
bool v = false;
|
||||
for( auto c : n )
|
||||
{
|
||||
if( c >= '0' && c <= '9' ) return true;
|
||||
if( c == '.' || c == '-' || c == '/' ) return true;
|
||||
switch( c )
|
||||
{
|
||||
case 'a':
|
||||
case 'e':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'y':
|
||||
v = true;
|
||||
}
|
||||
}
|
||||
if( !v )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
share_type account_create_operation::calculate_fee( const fee_parameters_type& k )const
|
||||
{
|
||||
auto core_fee_required = k.basic_fee;
|
||||
|
||||
if( !is_cheap_name(name) )
|
||||
core_fee_required = k.premium_fee;
|
||||
|
||||
// Authorities and vote lists can be arbitrarily large, so charge a data fee for big ones
|
||||
core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
|
||||
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
|
||||
void account_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( is_valid_name( name ) );
|
||||
FC_ASSERT( referrer_percent <= GRAPHENE_100_PERCENT );
|
||||
FC_ASSERT( owner.num_auths() != 0 );
|
||||
FC_ASSERT( owner.address_auths.size() == 0 );
|
||||
// TODO: this asset causes many tests to fail, those tests should probably be updated
|
||||
//FC_ASSERT( active.num_auths() != 0 );
|
||||
FC_ASSERT( active.address_auths.size() == 0 );
|
||||
options.validate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
share_type account_update_operation::calculate_fee( const fee_parameters_type& k )const
|
||||
{
|
||||
auto core_fee_required = k.fee;
|
||||
if( new_options )
|
||||
core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
void account_update_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( account != account_id_type() );
|
||||
FC_ASSERT( owner || active || new_options );
|
||||
if( owner )
|
||||
{
|
||||
FC_ASSERT( owner->num_auths() != 0 );
|
||||
FC_ASSERT( owner->address_auths.size() == 0 );
|
||||
}
|
||||
if( active )
|
||||
{
|
||||
FC_ASSERT( active->num_auths() != 0 );
|
||||
FC_ASSERT( active->address_auths.size() == 0 );
|
||||
}
|
||||
|
||||
if( new_options )
|
||||
new_options->validate();
|
||||
}
|
||||
|
||||
|
||||
share_type account_upgrade_operation::calculate_fee(const fee_parameters_type& k) const
|
||||
{
|
||||
if( upgrade_to_lifetime_member )
|
||||
return k.membership_lifetime_fee;
|
||||
return k.membership_annual_fee;
|
||||
}
|
||||
|
||||
|
||||
void account_upgrade_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
void account_transfer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -15,8 +15,8 @@
|
|||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/address.hpp>
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/chain/protocol/address.hpp>
|
||||
#include <fc/crypto/elliptic.hpp>
|
||||
#include <fc/crypto/base58.hpp>
|
||||
#include <algorithm>
|
||||
|
|
@ -27,4 +27,32 @@ bool asset_symbol_eq_lit::evaluate( const database& db )const
|
|||
return asset_id(db).symbol == symbol;
|
||||
}
|
||||
|
||||
struct predicate_validator
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
template<typename T>
|
||||
void operator()( const T& p )const
|
||||
{
|
||||
p.validate();
|
||||
}
|
||||
};
|
||||
|
||||
void assert_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
for( const auto& item : predicates )
|
||||
item.visit( predicate_validator() );
|
||||
}
|
||||
|
||||
/**
|
||||
* The fee for assert operations is proportional to their size,
|
||||
* but cheaper than a data fee because they require no storage
|
||||
*/
|
||||
share_type assert_operation::calculate_fee(const fee_parameters_type& k)const
|
||||
{
|
||||
return k.fee * predicates.size();
|
||||
}
|
||||
|
||||
|
||||
} } }
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/asset.hpp>
|
||||
#include <graphene/chain/protocol/asset.hpp>
|
||||
#include <fc/uint128.hpp>
|
||||
#include <boost/rational.hpp>
|
||||
|
||||
196
libraries/chain/protocol/asset_ops.cpp
Normal file
196
libraries/chain/protocol/asset_ops.cpp
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
#include <graphene/chain/protocol/asset_ops.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* Valid symbols can contain [A-Z0-9], and '.'
|
||||
* They must start with [A, Z]
|
||||
* They must end with [A, Z]
|
||||
* They can contain a maximum of one '.'
|
||||
*/
|
||||
bool is_valid_symbol( const string& symbol )
|
||||
{
|
||||
if( symbol.size() < GRAPHENE_MIN_ASSET_SYMBOL_LENGTH )
|
||||
return false;
|
||||
|
||||
if( symbol.size() > GRAPHENE_MAX_ASSET_SYMBOL_LENGTH )
|
||||
return false;
|
||||
|
||||
if( !isalpha( symbol.front() ) )
|
||||
return false;
|
||||
|
||||
if( !isalpha( symbol.back() ) )
|
||||
return false;
|
||||
|
||||
bool dot_already_present = false;
|
||||
for( const auto c : symbol )
|
||||
{
|
||||
if( (isalpha( c ) || isdigit(c)) && isupper( c ) )
|
||||
continue;
|
||||
|
||||
if( c == '.' )
|
||||
{
|
||||
if( dot_already_present )
|
||||
return false;
|
||||
|
||||
dot_already_present = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
share_type asset_create_operation::calculate_fee(const asset_create_operation::fee_parameters_type& param)const
|
||||
{
|
||||
auto core_fee_required = param.long_symbol;
|
||||
|
||||
switch(symbol.size()) {
|
||||
case 3: core_fee_required = param.symbol3;
|
||||
break;
|
||||
case 4: core_fee_required = param.symbol4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// common_options contains several lists and a string. Charge fees for its size
|
||||
core_fee_required += calculate_data_fee( fc::raw::pack_size(*this), param.price_per_kbyte );
|
||||
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
void asset_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( is_valid_symbol(symbol) );
|
||||
common_options.validate();
|
||||
if( common_options.issuer_permissions & (disable_force_settle|global_settle) )
|
||||
FC_ASSERT( bitasset_options.valid() );
|
||||
if( is_prediction_market )
|
||||
{
|
||||
FC_ASSERT( bitasset_options.valid(), "Cannot have a User-Issued Asset implement a prediction market." );
|
||||
FC_ASSERT( common_options.issuer_permissions & global_settle );
|
||||
}
|
||||
if( bitasset_options ) bitasset_options->validate();
|
||||
|
||||
asset dummy = asset(1) * common_options.core_exchange_rate;
|
||||
FC_ASSERT(dummy.asset_id == asset_id_type(1));
|
||||
FC_ASSERT(precision <= 12);
|
||||
}
|
||||
|
||||
/*
|
||||
asset_update_operation::asset_update_operation(const asset_object& old)
|
||||
{
|
||||
issuer = old.issuer;
|
||||
asset_to_update = old.get_id();
|
||||
new_options = old.options;
|
||||
}
|
||||
*/
|
||||
|
||||
void asset_update_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
if( new_issuer )
|
||||
FC_ASSERT(issuer != *new_issuer);
|
||||
new_options.validate();
|
||||
|
||||
asset dummy = asset(1, asset_to_update) * new_options.core_exchange_rate;
|
||||
FC_ASSERT(dummy.asset_id == asset_id_type());
|
||||
}
|
||||
|
||||
share_type asset_update_operation::calculate_fee(const asset_update_operation::fee_parameters_type& k)const
|
||||
{
|
||||
return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
|
||||
}
|
||||
|
||||
|
||||
void asset_publish_feed_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
feed.validate();
|
||||
}
|
||||
|
||||
void asset_reserve_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount_to_reserve.amount.value <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
FC_ASSERT( amount_to_reserve.amount.value > 0 );
|
||||
}
|
||||
|
||||
void asset_issue_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( asset_to_issue.amount.value <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
FC_ASSERT( asset_to_issue.amount.value > 0 );
|
||||
FC_ASSERT( asset_to_issue.asset_id != 0 );
|
||||
}
|
||||
|
||||
void asset_fund_fee_pool_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( fee.asset_id == asset_id_type() );
|
||||
FC_ASSERT( amount > 0 );
|
||||
}
|
||||
|
||||
void asset_settle_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount.amount >= 0 );
|
||||
}
|
||||
|
||||
void asset_update_bitasset_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
new_options.validate();
|
||||
}
|
||||
|
||||
void asset_update_feed_producers_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
void asset_global_settle_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( asset_to_settle == settle_price.base.asset_id );
|
||||
}
|
||||
|
||||
void bitasset_options::validate() const
|
||||
{
|
||||
FC_ASSERT(minimum_feeds > 0);
|
||||
FC_ASSERT(force_settlement_offset_percent <= GRAPHENE_100_PERCENT);
|
||||
FC_ASSERT(maximum_force_settlement_volume <= GRAPHENE_100_PERCENT);
|
||||
}
|
||||
|
||||
void asset_options::validate()const
|
||||
{
|
||||
FC_ASSERT( max_supply > 0 );
|
||||
FC_ASSERT( max_supply <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
FC_ASSERT( market_fee_percent <= GRAPHENE_100_PERCENT );
|
||||
FC_ASSERT( max_market_fee >= 0 && max_market_fee <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
// There must be no high bits in permissions whose meaning is not known.
|
||||
FC_ASSERT( !(issuer_permissions & ~ASSET_ISSUER_PERMISSION_MASK) );
|
||||
// There must be no high bits in flags which are not also high in permissions.
|
||||
FC_ASSERT( !(flags & ~issuer_permissions ) );
|
||||
// The global_settle flag may never be set (this is a permission only)
|
||||
FC_ASSERT( !(flags & global_settle) );
|
||||
core_exchange_rate.validate();
|
||||
FC_ASSERT( core_exchange_rate.base.asset_id.instance.value == 0 ||
|
||||
core_exchange_rate.quote.asset_id.instance.value == 0 );
|
||||
|
||||
if(!whitelist_authorities.empty() || !blacklist_authorities.empty())
|
||||
FC_ASSERT( flags & white_list );
|
||||
for( auto item : whitelist_markets )
|
||||
{
|
||||
FC_ASSERT( blacklist_markets.find(item) == blacklist_markets.end() );
|
||||
}
|
||||
for( auto item : blacklist_markets )
|
||||
{
|
||||
FC_ASSERT( whitelist_markets.find(item) == whitelist_markets.end() );
|
||||
}
|
||||
}
|
||||
|
||||
} } // namespace graphene::chain
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/block.hpp>
|
||||
#include <graphene/chain/protocol/block.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/bitutil.hpp>
|
||||
|
||||
14
libraries/chain/protocol/custom.cpp
Normal file
14
libraries/chain/protocol/custom.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include <graphene/chain/protocol/custom.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void custom_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount > 0 );
|
||||
}
|
||||
share_type custom_operation::calculate_fee(const fee_parameters_type& k)const
|
||||
{
|
||||
return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
|
||||
}
|
||||
|
||||
} }
|
||||
19
libraries/chain/protocol/delegate.cpp
Normal file
19
libraries/chain/protocol/delegate.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/
|
||||
#include <graphene/chain/protocol/delegate.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void delegate_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT(url.size() < GRAPHENE_MAX_URL_LENGTH );
|
||||
}
|
||||
|
||||
void delegate_update_global_parameters_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
new_parameters.validate();
|
||||
}
|
||||
|
||||
|
||||
} } // graphene::chain
|
||||
26
libraries/chain/protocol/market.cpp
Normal file
26
libraries/chain/protocol/market.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/
|
||||
#include <graphene/chain/protocol/market.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void limit_order_create_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( amount_to_sell.asset_id != min_to_receive.asset_id );
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount_to_sell.amount > 0 );
|
||||
FC_ASSERT( min_to_receive.amount > 0 );
|
||||
}
|
||||
|
||||
void limit_order_cancel_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
void call_order_update_operation::validate()const
|
||||
{ try {
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( delta_collateral.asset_id != delta_debt.asset_id );
|
||||
FC_ASSERT( delta_collateral.amount != 0 || delta_debt.amount != 0 );
|
||||
} FC_CAPTURE_AND_RETHROW((*this)) }
|
||||
|
||||
} } // graphene::chain
|
||||
65
libraries/chain/protocol/memo.cpp
Normal file
65
libraries/chain/protocol/memo.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#include <graphene/chain/protocol/memo.hpp>
|
||||
#include <fc/crypto/aes.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void memo_data::set_message(const fc::ecc::private_key& priv, const fc::ecc::public_key& pub,
|
||||
const string& msg, uint64_t custom_nonce)
|
||||
{
|
||||
if( from != public_key_type() )
|
||||
{
|
||||
if( custom_nonce == 0 )
|
||||
{
|
||||
uint64_t entropy = fc::sha224::hash(fc::ecc::private_key::generate())._hash[0];
|
||||
entropy <<= 32;
|
||||
entropy &= 0xff00000000000000;
|
||||
nonce = (fc::time_point::now().time_since_epoch().count() & 0x00ffffffffffffff) | entropy;
|
||||
} else
|
||||
nonce = custom_nonce;
|
||||
auto secret = priv.get_shared_secret(pub);
|
||||
auto nonce_plus_secret = fc::sha512::hash(fc::to_string(nonce) + secret.str());
|
||||
string text = memo_message(digest_type::hash(msg)._hash[0], msg).serialize();
|
||||
message = fc::aes_encrypt( nonce_plus_secret, vector<char>(text.begin(), text.end()) );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto text = memo_message(0, msg).serialize();
|
||||
message = vector<char>(text.begin(), text.end());
|
||||
}
|
||||
}
|
||||
|
||||
string memo_data::get_message(const fc::ecc::private_key& priv,
|
||||
const fc::ecc::public_key& pub)const
|
||||
{
|
||||
if( from != public_key_type() )
|
||||
{
|
||||
auto secret = priv.get_shared_secret(pub);
|
||||
auto nonce_plus_secret = fc::sha512::hash(fc::to_string(nonce) + secret.str());
|
||||
auto plain_text = fc::aes_decrypt( nonce_plus_secret, message );
|
||||
auto result = memo_message::deserialize(string(plain_text.begin(), plain_text.end()));
|
||||
FC_ASSERT( result.checksum == uint32_t(digest_type::hash(result.text)._hash[0]) );
|
||||
return result.text;
|
||||
}
|
||||
else
|
||||
{
|
||||
return memo_message::deserialize(string(message.begin(), message.end())).text;
|
||||
}
|
||||
}
|
||||
|
||||
string memo_message::serialize() const
|
||||
{
|
||||
auto serial_checksum = string(sizeof(checksum), ' ');
|
||||
(uint32_t&)(*serial_checksum.data()) = checksum;
|
||||
return serial_checksum + text;
|
||||
}
|
||||
|
||||
memo_message memo_message::deserialize(const string& serial)
|
||||
{
|
||||
memo_message result;
|
||||
FC_ASSERT( serial.size() >= sizeof(result.checksum) );
|
||||
result.checksum = ((uint32_t&)(*serial.data()));
|
||||
result.text = serial.substr(sizeof(result.checksum));
|
||||
return result;
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
165
libraries/chain/protocol/operations.cpp
Normal file
165
libraries/chain/protocol/operations.cpp
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Cryptonomex, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and
|
||||
* the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted until September 8, 2015, provided that the following conditions are met:
|
||||
*
|
||||
* 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
||||
uint64_t base_operation::calculate_data_fee( uint64_t bytes, uint64_t price_per_kbyte )
|
||||
{
|
||||
auto result = (fc::uint128(bytes) * price_per_kbyte) / 1024;
|
||||
FC_ASSERT( result <= GRAPHENE_MAX_SHARE_SUPPLY );
|
||||
return result.to_uint64();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void balance_claim_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee == asset() );
|
||||
FC_ASSERT( balance_owner_key != public_key_type() );
|
||||
}
|
||||
|
||||
struct required_auth_visitor
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
vector<authority>& result;
|
||||
|
||||
required_auth_visitor( vector<authority>& r ):result(r){}
|
||||
|
||||
/** for most operations this is a no-op */
|
||||
template<typename T>
|
||||
void operator()(const T& )const {}
|
||||
|
||||
void operator()( const balance_claim_operation& o )const
|
||||
{
|
||||
result.push_back( authority( 1, o.balance_owner_key, 1 ) );
|
||||
}
|
||||
};
|
||||
|
||||
struct required_active_visitor
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
flat_set<account_id_type>& result;
|
||||
|
||||
required_active_visitor( flat_set<account_id_type>& r ):result(r){}
|
||||
|
||||
/** for most operations this is just the fee payer */
|
||||
template<typename T>
|
||||
void operator()(const T& o)const
|
||||
{
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
void operator()(const account_update_operation& o)const
|
||||
{
|
||||
/// if owner authority is required, no active authority is required
|
||||
if( !(o.owner || o.active) ) /// TODO: document why active cannot be updated by active?
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
void operator()( const proposal_delete_operation& o )const
|
||||
{
|
||||
if( !o.using_owner_authority )
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
|
||||
void operator()( const proposal_update_operation& o )const
|
||||
{
|
||||
result.insert( o.fee_payer() );
|
||||
for( auto id : o.active_approvals_to_add )
|
||||
result.insert(id);
|
||||
for( auto id : o.active_approvals_to_remove )
|
||||
result.insert(id);
|
||||
}
|
||||
void operator()( const custom_operation& o )const
|
||||
{
|
||||
result.insert( o.required_auths.begin(), o.required_auths.end() );
|
||||
}
|
||||
void operator()( const assert_operation& o )const
|
||||
{
|
||||
result.insert( o.fee_payer() );
|
||||
result.insert( o.required_auths.begin(), o.required_auths.end() );
|
||||
}
|
||||
};
|
||||
|
||||
struct required_owner_visitor
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
flat_set<account_id_type>& result;
|
||||
|
||||
required_owner_visitor( flat_set<account_id_type>& r ):result(r){}
|
||||
|
||||
/** for most operations this is a no-op */
|
||||
template<typename T>
|
||||
void operator()(const T& o)const {}
|
||||
|
||||
void operator()(const account_update_operation& o)const
|
||||
{
|
||||
if( o.owner || o.active ) /// TODO: document why active cannot be updated by active?
|
||||
result.insert( o.account );
|
||||
}
|
||||
|
||||
void operator()( const proposal_delete_operation& o )const
|
||||
{
|
||||
if( o.using_owner_authority )
|
||||
result.insert( o.fee_payer() );
|
||||
}
|
||||
|
||||
void operator()( const proposal_update_operation& o )const
|
||||
{
|
||||
for( auto id : o.owner_approvals_to_add )
|
||||
result.insert(id);
|
||||
for( auto id : o.owner_approvals_to_remove )
|
||||
result.insert(id);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void operation_get_required_authorities( const operation& op, vector<authority>& result )
|
||||
{
|
||||
op.visit( required_auth_visitor( result ) );
|
||||
}
|
||||
void operation_get_required_active_authorities( const operation& op, flat_set<account_id_type>& result )
|
||||
{
|
||||
op.visit( required_active_visitor( result ) );
|
||||
}
|
||||
void operation_get_required_owner_authorities( const operation& op, flat_set<account_id_type>& result )
|
||||
{
|
||||
op.visit( required_owner_visitor( result ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Used to validate operations in a polymorphic manner
|
||||
*/
|
||||
struct operation_validator
|
||||
{
|
||||
typedef void result_type;
|
||||
template<typename T>
|
||||
void operator()( const T& v )const { v.validate(); }
|
||||
};
|
||||
|
||||
void operation_validate( const operation& op )
|
||||
{
|
||||
op.visit( operation_validator() );
|
||||
}
|
||||
|
||||
|
||||
} } // namespace graphene::chain
|
||||
59
libraries/chain/protocol/proposal.cpp
Normal file
59
libraries/chain/protocol/proposal.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/
|
||||
#include <graphene/chain/protocol/operations.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
proposal_create_operation proposal_create_operation::genesis_proposal(const chain_parameters& global_params, fc::time_point_sec head_block_time )
|
||||
{
|
||||
proposal_create_operation op;
|
||||
op.expiration_time = head_block_time + global_params.maximum_proposal_lifetime;
|
||||
op.review_period_seconds = global_params.genesis_proposal_review_period;
|
||||
return op;
|
||||
}
|
||||
|
||||
void proposal_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( !proposed_ops.empty() );
|
||||
for( const auto& op : proposed_ops ) operation_validate( op.op );
|
||||
}
|
||||
|
||||
share_type proposal_create_operation::calculate_fee(const fee_parameters_type& k) const
|
||||
{
|
||||
return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
|
||||
}
|
||||
|
||||
void proposal_update_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0);
|
||||
FC_ASSERT(!(active_approvals_to_add.empty() && active_approvals_to_remove.empty() &&
|
||||
owner_approvals_to_add.empty() && owner_approvals_to_remove.empty() &&
|
||||
key_approvals_to_add.empty() && key_approvals_to_remove.empty()));
|
||||
for( auto a : active_approvals_to_add )
|
||||
{
|
||||
FC_ASSERT(active_approvals_to_remove.find(a) == active_approvals_to_remove.end(),
|
||||
"Cannot add and remove approval at the same time.");
|
||||
}
|
||||
for( auto a : owner_approvals_to_add )
|
||||
{
|
||||
FC_ASSERT(owner_approvals_to_remove.find(a) == owner_approvals_to_remove.end(),
|
||||
"Cannot add and remove approval at the same time.");
|
||||
}
|
||||
for( auto a : key_approvals_to_add )
|
||||
{
|
||||
FC_ASSERT(key_approvals_to_remove.find(a) == key_approvals_to_remove.end(),
|
||||
"Cannot add and remove approval at the same time.");
|
||||
}
|
||||
}
|
||||
|
||||
void proposal_delete_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
share_type proposal_update_operation::calculate_fee(const fee_parameters_type& k) const
|
||||
{
|
||||
return k.fee + calculate_data_fee( fc::raw::pack_size(*this), k.price_per_kbyte );
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -15,7 +15,8 @@
|
|||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/transaction.hpp>
|
||||
#include <graphene/chain/protocol/transaction.hpp>
|
||||
#include <graphene/chain/protocol/fee_schedule.hpp>
|
||||
#include <fc/io/raw.hpp>
|
||||
#include <fc/bitutil.hpp>
|
||||
|
||||
|
|
@ -91,11 +92,7 @@ void transaction::set_expiration( const block_id_type& reference_block, unsigned
|
|||
void transaction::get_required_authorities( flat_set<account_id_type>& active, flat_set<account_id_type>& owner, vector<authority>& other )
|
||||
{
|
||||
for( const auto& op : operations )
|
||||
{
|
||||
operation_get_required_active_authorities( op, active );
|
||||
operation_get_required_owner_authorities( op, owner );
|
||||
operation_get_required_authorities( op, other );
|
||||
}
|
||||
operation_get_required_authorities( op, active, owner, other );
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
41
libraries/chain/protocol/transfer.cpp
Normal file
41
libraries/chain/protocol/transfer.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/
|
||||
#include <graphene/chain/protocol/transfer.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
share_type transfer_operation::calculate_fee( const fee_parameters_type& schedule )const
|
||||
{
|
||||
share_type core_fee_required = schedule.fee;
|
||||
if( memo )
|
||||
core_fee_required += calculate_data_fee( fc::raw::pack_size(memo), schedule.price_per_kbyte );
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
|
||||
void transfer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( from != to );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
share_type override_transfer_operation::calculate_fee( const fee_parameters_type& schedule )const
|
||||
{
|
||||
share_type core_fee_required = schedule.fee;
|
||||
if( memo )
|
||||
core_fee_required += calculate_data_fee( fc::raw::pack_size(memo), schedule.price_per_kbyte );
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
|
||||
void override_transfer_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( from != to );
|
||||
FC_ASSERT( amount.amount > 0 );
|
||||
FC_ASSERT( issuer != from );
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <graphene/chain/config.hpp>
|
||||
#include <graphene/chain/types.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
#include <fc/crypto/base58.hpp>
|
||||
#include <fc/crypto/ripemd160.hpp>
|
||||
48
libraries/chain/protocol/withdraw_permission.cpp
Normal file
48
libraries/chain/protocol/withdraw_permission.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/
|
||||
#include <graphene/chain/protocol/withdraw_permission.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void withdraw_permission_update_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( withdrawal_limit.amount > 0 );
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( withdrawal_period_sec > 0 );
|
||||
FC_ASSERT( withdraw_from_account != authorized_account );
|
||||
FC_ASSERT( periods_until_expiration > 0 );
|
||||
}
|
||||
|
||||
void withdraw_permission_claim_operation::validate()const
|
||||
{
|
||||
FC_ASSERT( withdraw_to_account != withdraw_from_account );
|
||||
FC_ASSERT( amount_to_withdraw.amount > 0 );
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
}
|
||||
|
||||
share_type withdraw_permission_claim_operation::calculate_fee(const fee_parameters_type& k)const
|
||||
{
|
||||
share_type core_fee_required = k.fee;
|
||||
if( memo )
|
||||
core_fee_required += calculate_data_fee( fc::raw::pack_size(memo), k.price_per_kbyte );
|
||||
return core_fee_required;
|
||||
}
|
||||
|
||||
void withdraw_permission_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( withdraw_from_account != authorized_account );
|
||||
FC_ASSERT( withdrawal_limit.amount > 0 );
|
||||
//TODO: better bounds checking on these values
|
||||
FC_ASSERT( withdrawal_period_sec > 0 );
|
||||
FC_ASSERT( periods_until_expiration > 0 );
|
||||
}
|
||||
|
||||
void withdraw_permission_delete_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( withdraw_from_account != authorized_account );
|
||||
}
|
||||
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
19
libraries/chain/protocol/witness.cpp
Normal file
19
libraries/chain/protocol/witness.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/
|
||||
#include <graphene/chain/protocol/witness.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
|
||||
void witness_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0);
|
||||
FC_ASSERT(url.size() < GRAPHENE_MAX_URL_LENGTH );
|
||||
}
|
||||
|
||||
void witness_withdraw_pay_operation::validate() const
|
||||
{
|
||||
FC_ASSERT( fee.amount >= 0 );
|
||||
FC_ASSERT( amount >= 0 );
|
||||
}
|
||||
|
||||
} } // graphene::chain
|
||||
15
libraries/chain/protocol/worker.cpp
Normal file
15
libraries/chain/protocol/worker.cpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#include <graphene/chain/protocol/worker.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void worker_create_operation::validate() const
|
||||
{
|
||||
FC_ASSERT(fee.amount >= 0);
|
||||
FC_ASSERT(work_end_date > work_begin_date);
|
||||
FC_ASSERT(daily_pay > 0);
|
||||
FC_ASSERT(daily_pay < GRAPHENE_MAX_SHARE_SUPPLY);
|
||||
FC_ASSERT(name.size() < GRAPHENE_MAX_WORKER_NAME_LENGTH );
|
||||
FC_ASSERT(url.size() < GRAPHENE_MAX_URL_LENGTH );
|
||||
}
|
||||
|
||||
} }
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue