diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 011e784b..08b0aec2 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -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} ) diff --git a/libraries/chain/account_evaluator.cpp b/libraries/chain/account_evaluator.cpp index ba54ac6a..ca659a7b 100644 --- a/libraries/chain/account_evaluator.cpp +++ b/libraries/chain/account_evaluator.cpp @@ -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)) } diff --git a/libraries/chain/assert_evaluator.cpp b/libraries/chain/assert_evaluator.cpp index 6b805d2d..f7fe1a14 100644 --- a/libraries/chain/assert_evaluator.cpp +++ b/libraries/chain/assert_evaluator.cpp @@ -18,7 +18,6 @@ #include #include -#include #include @@ -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& pdata : o.predicates ) + for( const auto& p : o.predicates ) { - fc::datastream 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) ) } diff --git a/libraries/chain/asset_evaluator.cpp b/libraries/chain/asset_evaluator.cpp index 60255490..b296be92 100644 --- a/libraries/chain/asset_evaluator.cpp +++ b/libraries/chain/asset_evaluator.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include @@ -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& 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; diff --git a/libraries/chain/asset_object.cpp b/libraries/chain/asset_object.cpp index 57c1bfff..f56b107a 100644 --- a/libraries/chain/asset_object.cpp +++ b/libraries/chain/asset_object.cpp @@ -17,7 +17,6 @@ */ #include #include -#include #include @@ -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 { diff --git a/libraries/chain/block_database.cpp b/libraries/chain/block_database.cpp index e4b4b01a..2851ad64 100644 --- a/libraries/chain/block_database.cpp +++ b/libraries/chain/block_database.cpp @@ -16,6 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/database.cpp b/libraries/chain/database.cpp new file mode 100644 index 00000000..122ab994 --- /dev/null +++ b/libraries/chain/database.cpp @@ -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" diff --git a/libraries/chain/db_block.cpp b/libraries/chain/db_block.cpp index c400ea74..574c7d6f 100644 --- a/libraries/chain/db_block.cpp +++ b/libraries/chain/db_block.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/db_debug.cpp b/libraries/chain/db_debug.cpp index 8c34df21..bfba2a0d 100644 --- a/libraries/chain/db_debug.cpp +++ b/libraries/chain/db_debug.cpp @@ -20,8 +20,7 @@ #include #include -#include -#include +#include #include #include diff --git a/libraries/chain/db_getter.cpp b/libraries/chain/db_getter.cpp index 7268fcf3..28e15602 100644 --- a/libraries/chain/db_getter.cpp +++ b/libraries/chain/db_getter.cpp @@ -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; } diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 9cceaea3..88cb28ac 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -24,25 +24,20 @@ #include #include #include -#include #include -#include #include #include #include #include #include -#include #include #include #include #include #include -#include -#include +#include #include -#include #include #include #include @@ -50,6 +45,8 @@ #include #include +#include + #include #include @@ -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(); register_evaluator(); register_evaluator(); + register_evaluator(); register_evaluator(); register_evaluator(); register_evaluator(); @@ -85,7 +141,6 @@ void database::initialize_evaluators() register_evaluator(); register_evaluator(); register_evaluator(); - register_evaluator(); register_evaluator(); register_evaluator(); register_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& p) { diff --git a/libraries/chain/db_maint.cpp b/libraries/chain/db_maint.cpp index 1fd4bf98..bc9ce537 100644 --- a/libraries/chain/db_maint.cpp +++ b/libraries/chain/db_maint.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include @@ -59,6 +59,25 @@ void database::perform_account_maintenance(std::tuple helpers) detail::for_each(helpers, a, detail::gen_seq()); } +/// @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 + 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 ) { diff --git a/libraries/chain/db_management.cpp b/libraries/chain/db_management.cpp index 14dbba9d..e77ccc2f 100644 --- a/libraries/chain/db_management.cpp +++ b/libraries/chain/db_management.cpp @@ -19,6 +19,7 @@ #include #include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/db_market.cpp b/libraries/chain/db_market.cpp index ff54af38..8b20c3c9 100644 --- a/libraries/chain/db_market.cpp +++ b/libraries/chain/db_market.cpp @@ -20,8 +20,7 @@ #include #include -#include -#include +#include #include @@ -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() ) { diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index 32aafb72..78ca531b 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -20,12 +20,12 @@ #include #include -#include #include -#include #include +#include #include #include +#include #include diff --git a/libraries/chain/delegate_evaluator.cpp b/libraries/chain/delegate_evaluator.cpp index 606dd00e..966fe8c4 100644 --- a/libraries/chain/delegate_evaluator.cpp +++ b/libraries/chain/delegate_evaluator.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include 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 diff --git a/libraries/chain/evaluator.cpp b/libraries/chain/evaluator.cpp index a8bdb277..c34a49cb 100644 --- a/libraries/chain/evaluator.cpp +++ b/libraries/chain/evaluator.cpp @@ -21,8 +21,8 @@ #include #include #include -#include -#include +#include +#include #include @@ -85,9 +85,7 @@ database& generic_evaluator::db()const { return trx_state->db(); } flat_set owner_auths; vector 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) || diff --git a/libraries/chain/global_parameters_evaluator.cpp b/libraries/chain/global_parameters_evaluator.cpp deleted file mode 100644 index b73cfa14..00000000 --- a/libraries/chain/global_parameters_evaluator.cpp +++ /dev/null @@ -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 -#include -#include - -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 diff --git a/libraries/chain/include/graphene/chain/account_object.hpp b/libraries/chain/include/graphene/chain/account_object.hpp index 75c5c826..d625dac3 100644 --- a/libraries/chain/include/graphene/chain/account_object.hpp +++ b/libraries/chain/include/graphene/chain/account_object.hpp @@ -16,14 +16,12 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include #include #include -#include namespace graphene { namespace chain { -class database; + class database; /** * @class account_statistics_object diff --git a/libraries/chain/include/graphene/chain/assert_evaluator.hpp b/libraries/chain/include/graphene/chain/assert_evaluator.hpp index 37ff998b..74cb5aee 100644 --- a/libraries/chain/include/graphene/chain/assert_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/assert_evaluator.hpp @@ -16,8 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#include #include -#include #include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/asset_evaluator.hpp b/libraries/chain/include/graphene/chain/asset_evaluator.hpp index 89952732..e9966fbc 100644 --- a/libraries/chain/include/graphene/chain/asset_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/asset_evaluator.hpp @@ -16,8 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#include #include -#include #include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/asset_object.hpp b/libraries/chain/include/graphene/chain/asset_object.hpp index 955b88b6..d434f868 100644 --- a/libraries/chain/include/graphene/chain/asset_object.hpp +++ b/libraries/chain/include/graphene/chain/asset_object.hpp @@ -16,8 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#include #include -#include #include #include @@ -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 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 blacklist_authorities; - - /** defines the assets that this asset may be traded against in the market */ - flat_set whitelist_markets; - /** defines the assets that this asset may not be traded against in the market, must not overlap whitelist */ - flat_set 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), (symbol) diff --git a/libraries/chain/include/graphene/chain/balance_evaluator.hpp b/libraries/chain/include/graphene/chain/balance_evaluator.hpp index f3eee7d3..acd2e1f1 100644 --- a/libraries/chain/include/graphene/chain/balance_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/balance_evaluator.hpp @@ -1,7 +1,7 @@ #pragma once +#include #include -#include #include #include #include diff --git a/libraries/chain/include/graphene/chain/block_database.hpp b/libraries/chain/include/graphene/chain/block_database.hpp index 0ca9bc9c..1e8a97a6 100644 --- a/libraries/chain/include/graphene/chain/block_database.hpp +++ b/libraries/chain/include/graphene/chain/block_database.hpp @@ -17,7 +17,7 @@ */ #pragma once #include -#include +#include namespace graphene { namespace chain { class block_database diff --git a/libraries/chain/include/graphene/chain/call_order_evaluator.hpp b/libraries/chain/include/graphene/chain/call_order_evaluator.hpp deleted file mode 100644 index 025a9292..00000000 --- a/libraries/chain/include/graphene/chain/call_order_evaluator.hpp +++ /dev/null @@ -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 -#include -#include - -namespace graphene { namespace chain { - - class call_order_update_evaluator : public 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 diff --git a/libraries/chain/include/graphene/chain/custom_evaluator.hpp b/libraries/chain/include/graphene/chain/custom_evaluator.hpp index 3b315c1f..afa87dfb 100644 --- a/libraries/chain/include/graphene/chain/custom_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/custom_evaluator.hpp @@ -16,8 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#include #include -#include #include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 7de14fbd..4c901c42 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -17,8 +17,7 @@ */ #pragma once #include -#include -#include +#include #include #include #include @@ -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; diff --git a/libraries/chain/include/graphene/chain/delegate_evaluator.hpp b/libraries/chain/include/graphene/chain/delegate_evaluator.hpp index 9d3d478e..c6f2af88 100644 --- a/libraries/chain/include/graphene/chain/delegate_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/delegate_evaluator.hpp @@ -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 + { + 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 diff --git a/libraries/chain/include/graphene/chain/delegate_object.hpp b/libraries/chain/include/graphene/chain/delegate_object.hpp index d55e008e..053eadd2 100644 --- a/libraries/chain/include/graphene/chain/delegate_object.hpp +++ b/libraries/chain/include/graphene/chain/delegate_object.hpp @@ -16,7 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include +#include #include #include diff --git a/libraries/chain/include/graphene/chain/evaluator.hpp b/libraries/chain/include/graphene/chain/evaluator.hpp index 386834f7..add4bc48 100644 --- a/libraries/chain/include/graphene/chain/evaluator.hpp +++ b/libraries/chain/include/graphene/chain/evaluator.hpp @@ -16,8 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include namespace graphene { namespace chain { @@ -194,7 +193,7 @@ namespace graphene { namespace chain { const auto& op = o.get(); 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); } diff --git a/libraries/chain/include/graphene/chain/fork_database.hpp b/libraries/chain/include/graphene/chain/fork_database.hpp index 31cd89f0..cf79f955 100644 --- a/libraries/chain/include/graphene/chain/fork_database.hpp +++ b/libraries/chain/include/graphene/chain/fork_database.hpp @@ -16,8 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include #include #include diff --git a/libraries/chain/include/graphene/chain/genesis_state.hpp b/libraries/chain/include/graphene/chain/genesis_state.hpp index 594e9542..00ac6e56 100644 --- a/libraries/chain/include/graphene/chain/genesis_state.hpp +++ b/libraries/chain/include/graphene/chain/genesis_state.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/libraries/chain/include/graphene/chain/global_parameters_evaluator.hpp b/libraries/chain/include/graphene/chain/global_parameters_evaluator.hpp deleted file mode 100644 index 1c3fb771..00000000 --- a/libraries/chain/include/graphene/chain/global_parameters_evaluator.hpp +++ /dev/null @@ -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 - -namespace graphene { namespace chain { - -class global_parameters_update_evaluator : public 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 diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index 126458b0..5fc30259 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -16,10 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include +#include #include -#include -#include #include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/limit_order_evaluator.hpp b/libraries/chain/include/graphene/chain/limit_order_evaluator.hpp index 82e31566..994b487f 100644 --- a/libraries/chain/include/graphene/chain/limit_order_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/limit_order_evaluator.hpp @@ -22,31 +22,5 @@ namespace graphene { namespace chain { - class limit_order_create_evaluator : public 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 - { - 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 diff --git a/libraries/chain/include/graphene/chain/limit_order_object.hpp b/libraries/chain/include/graphene/chain/limit_order_object.hpp deleted file mode 100644 index f45bb3f6..00000000 --- a/libraries/chain/include/graphene/chain/limit_order_object.hpp +++ /dev/null @@ -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 -#include -#include -#include -#include - -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 - { - 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, - member< object, object_id_type, &object::id > >, - ordered_non_unique< tag, member< limit_order_object, time_point_sec, &limit_order_object::expiration> >, - ordered_unique< tag, - 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, std::less > - > - > - > limit_order_multi_index_type; - - typedef generic_index limit_order_index; - -} } - -FC_REFLECT_DERIVED( graphene::chain::limit_order_object, - (graphene::db::object), - (expiration)(seller)(for_sale)(sell_price) - ) - diff --git a/libraries/chain/include/graphene/chain/call_order_object.hpp b/libraries/chain/include/graphene/chain/market_evaluator.hpp similarity index 53% rename from libraries/chain/include/graphene/chain/call_order_object.hpp rename to libraries/chain/include/graphene/chain/market_evaluator.hpp index ea00217e..7e5b7258 100644 --- a/libraries/chain/include/graphene/chain/call_order_object.hpp +++ b/libraries/chain/include/graphene/chain/market_evaluator.hpp @@ -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 -#include -#include -#include -#include -#include +#include +#include +#include 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 + { + 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, + member< object, object_id_type, &object::id > >, + ordered_non_unique< tag, member< limit_order_object, time_point_sec, &limit_order_object::expiration> >, + ordered_unique< tag, + 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, std::less > + > + > + > limit_order_multi_index_type; + + typedef generic_index limit_order_index; /** * @class call_order_object @@ -121,8 +147,58 @@ namespace graphene { namespace chain { typedef generic_index call_order_index; typedef generic_index force_settlement_index; + + + + + class limit_order_create_evaluator : public 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 + { + 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 + { + 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) ) diff --git a/libraries/chain/include/graphene/chain/operation_history_object.hpp b/libraries/chain/include/graphene/chain/operation_history_object.hpp index 9f5d6e9e..644668ab 100644 --- a/libraries/chain/include/graphene/chain/operation_history_object.hpp +++ b/libraries/chain/include/graphene/chain/operation_history_object.hpp @@ -16,8 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#include #include -#include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/operations.hpp b/libraries/chain/include/graphene/chain/operations.hpp deleted file mode 100644 index 8d2c6b6e..00000000 --- a/libraries/chain/include/graphene/chain/operations.hpp +++ /dev/null @@ -1,1608 +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. - */ -/* Copyright (C) Cryptonomex, Inc - All Rights Reserved - * - * All modifications become property of Cryptonomex, Inc. - * - **/ -#pragma once - -#include -#include -#include -#include - -/// TODO: why does this file depend upon database objects? -/// we should remove these headers -#include -#include - -#include -#include - -namespace graphene { namespace chain { - - bool is_valid_symbol( const string& symbol ); - bool is_valid_name( const string& s ); - bool is_premium_name( const string& n ); - bool is_cheap_name( const string& n ); - - struct void_result{}; - typedef fc::static_variant operation_result; - - struct base_operation - { - template - share_type calculate_fee(const T& params)const - { - return params.fee; - } - }; - - /** - * @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 - * - * @{ - */ - - /** - * @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 = 150000; }; - - asset fee; - account_id_type fee_paying_account; - // TODO: replace this with a pure vector because all nodes need to know about all predicates and - // this will simplify the code. - vector> predicates; - flat_set required_auths; - - account_id_type fee_payer()const { return fee_paying_account; } - void validate()const; - }; - - /** - * @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; - }; - - - /// 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 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; - }; - - /** - * @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); } - }; - - /** - * @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 owner; - /// New active authority. If set, this operation requires owner authority to execute: TODO: why? - optional active; - - /// New account options - optional new_options; - - account_id_type fee_payer()const { return account; } - void validate()const; - share_type calculate_fee( const fee_parameters_type& k )const; - }; - - /** - * @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; - - }; - - /** - * @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 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; - }; - - /** - * @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 global_parameters_update_operation : public base_operation - { - struct fee_parameters_type { uint64_t fee = GRAPHENE_BLOCKCHAIN_PRECISION; }; - - asset fee; - fc::fwd new_parameters; - - account_id_type fee_payer()const { return account_id_type(); } - void validate()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); - }; - - /** - * @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 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; - }; - - /** - * @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 base_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; - - 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 base_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; - - account_id_type fee_payer()const { return issuer; } - void validate()const; - share_type calculate_fee(const fee_parameters_type& k)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_object::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 - fc::optional 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_object::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 new_issuer; - /// TODO: operations should not depend upon data model objects, reverse the dependency - asset_object::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; - - asset_object::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 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; - - 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; - }; - - /** - * @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 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; - }; - - /** - * @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 proposed_ops; - time_point_sec expiration_time; - optional 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 class database& db); - - 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 active_approvals_to_add; - flat_set active_approvals_to_remove; - flat_set owner_approvals_to_add; - flat_set owner_approvals_to_remove; - flat_set key_approvals_to_add; - flat_set 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; - }; - ///@} - - /** - * @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 {}; - - object_id_type order_id; - account_id_type account_id; - asset pays; - asset receives; - asset fee; // paid by receiving account - - - pair 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; } - }; - - /** - * @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; - - 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; - }; - - 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 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; - }; - - - /** - * @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; - }; - - /** - * @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. - * - * @{ - */ - /** - * @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; - }; - ///@} - - /** - * @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 required_auths; - uint16_t id; - vector data; - - account_id_type fee_payer()const { return payer; } - void validate()const; - share_type calculate_fee(const fee_parameters_type& k)const; - }; - - /** - * @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, - 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, - delegate_create_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, - fill_order_operation, - global_parameters_update_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, vector& result ); - void operation_get_required_active_authorities( const operation& op, flat_set& result ); - void operation_get_required_owner_authorities( const operation& op, flat_set& result ); - void operation_validate( const operation& op ); - - /** - * Used to track the result of applying an operation and when it was applied. - */ - 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( graphene::chain::op_wrapper, (op) ) -FC_REFLECT( graphene::chain::memo_message, (checksum)(text) ) -FC_REFLECT( graphene::chain::memo_data, (from)(to)(nonce)(message) ) - -FC_REFLECT( graphene::chain::account_create_operation, - (fee)(registrar) - (referrer)(referrer_percent) - (name)(owner)(active)(options) - ) - -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::delegate_create_operation::fee_parameters_type, (fee) ) -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::global_parameters_update_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::transfer_operation::fee_parameters_type, (base_fee)(price_per_kbyte) ) -FC_REFLECT( graphene::chain::override_transfer_operation::fee_parameters_type, (base_fee)(price_per_kbyte) ) -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::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) ) -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::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::vesting_balance_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::vesting_balance_withdraw_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::worker_create_operation::fee_parameters_type, (fee) ) -FC_REFLECT( graphene::chain::custom_operation::fee_parameters_type, (fee)(price_per_kbyte) ) - -/// THIS IS THE ONLY VIRTUAL OPERATION THUS FAR... -FC_REFLECT( graphene::chain::fill_order_operation::fee_parameters_type, ) - -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_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_whitelist_operation, (fee)(authorizing_account)(account_to_list)(new_listing)) -FC_REFLECT( graphene::chain::account_transfer_operation, (fee)(account_id)(new_owner) ) - -FC_REFLECT( graphene::chain::delegate_create_operation, - (fee)(delegate_account)(url) ) - -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) ) - -FC_REFLECT( graphene::chain::limit_order_create_operation, - (fee)(seller)(amount_to_sell)(min_to_receive)(expiration)(fill_or_kill) - ) -FC_REFLECT( graphene::chain::fill_order_operation, (fee)(order_id)(account_id)(pays)(receives) ) -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::transfer_operation, - (fee)(from)(to)(amount)(memo) ) -FC_REFLECT( graphene::chain::override_transfer_operation, - (fee)(issuer)(from)(to)(amount)(memo) ) - -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::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) ) - -FC_REFLECT( graphene::chain::asset_fund_fee_pool_operation, (fee)(from_account)(asset_id)(amount) ); - -FC_REFLECT( graphene::chain::global_parameters_update_operation, (fee)(new_parameters) ); - -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) ) - -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::worker_create_operation, - (fee)(owner)(work_begin_date)(work_end_date)(daily_pay)(name)(url)(initializer) ) - -FC_REFLECT( graphene::chain::custom_operation, (fee)(payer)(required_auths)(id)(data) ) -FC_REFLECT( graphene::chain::assert_operation, (fee)(fee_paying_account)(predicates)(required_auths) ) - -FC_REFLECT( graphene::chain::void_result, ) -FC_REFLECT( graphene::chain::balance_claim_operation, - (fee)(deposit_to_account)(balance_to_claim)(balance_owner_key)(total_claimed) ) - -FC_REFLECT(graphene::chain::account_options, (memo_key)(voting_account)(num_witness)(num_committee)(votes)) - -FC_REFLECT_TYPENAME( graphene::chain::operation ) -FC_REFLECT_TYPENAME( graphene::chain::operation_result ) -FC_REFLECT_TYPENAME( fc::flat_set ) -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 ) - diff --git a/libraries/chain/include/graphene/chain/predicate.hpp b/libraries/chain/include/graphene/chain/predicate.hpp deleted file mode 100644 index 32822ff0..00000000 --- a/libraries/chain/include/graphene/chain/predicate.hpp +++ /dev/null @@ -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 - -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 ) diff --git a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp index 27db2a00..606895bd 100644 --- a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp @@ -17,8 +17,8 @@ */ #pragma once +#include #include -#include #include #include diff --git a/libraries/chain/include/graphene/chain/proposal_object.hpp b/libraries/chain/include/graphene/chain/proposal_object.hpp index 6adc761b..eb8d890c 100644 --- a/libraries/chain/include/graphene/chain/proposal_object.hpp +++ b/libraries/chain/include/graphene/chain/proposal_object.hpp @@ -17,8 +17,7 @@ */ #pragma once -#include -#include +#include #include #include diff --git a/libraries/chain/include/graphene/chain/protocol/README.md b/libraries/chain/include/graphene/chain/protocol/README.md new file mode 100644 index 00000000..6f19578c --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/README.md @@ -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. diff --git a/libraries/chain/include/graphene/chain/protocol/account.hpp b/libraries/chain/include/graphene/chain/protocol/account.hpp new file mode 100644 index 00000000..8d35daf8 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/account.hpp @@ -0,0 +1,224 @@ +#pragma once +#include + +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 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 owner; + /// New active authority. If set, this operation requires owner authority to execute: TODO: why? + optional active; + + /// New account options + optional 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) ) diff --git a/libraries/chain/include/graphene/chain/address.hpp b/libraries/chain/include/graphene/chain/protocol/address.hpp similarity index 100% rename from libraries/chain/include/graphene/chain/address.hpp rename to libraries/chain/include/graphene/chain/protocol/address.hpp diff --git a/libraries/chain/include/graphene/chain/protocol/assert.hpp b/libraries/chain/include/graphene/chain/protocol/assert.hpp new file mode 100644 index 00000000..b6e2a575 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/assert.hpp @@ -0,0 +1,73 @@ +#pragma once +#include + +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 predicates; + flat_set 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) ) diff --git a/libraries/chain/include/graphene/chain/asset.hpp b/libraries/chain/include/graphene/chain/protocol/asset.hpp similarity index 98% rename from libraries/chain/include/graphene/chain/asset.hpp rename to libraries/chain/include/graphene/chain/protocol/asset.hpp index f528b10a..4c116c37 100644 --- a/libraries/chain/include/graphene/chain/asset.hpp +++ b/libraries/chain/include/graphene/chain/protocol/asset.hpp @@ -16,8 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp new file mode 100644 index 00000000..0e345001 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/asset_ops.hpp @@ -0,0 +1,444 @@ +#pragma once +#include +#include + +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 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 blacklist_authorities; + + /** defines the assets that this asset may be traded against in the market */ + flat_set whitelist_markets; + /** defines the assets that this asset may not be traded against in the market, must not overlap whitelist */ + flat_set 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; + /// 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 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 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; + + 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) ); + diff --git a/libraries/chain/include/graphene/chain/authority.hpp b/libraries/chain/include/graphene/chain/protocol/authority.hpp similarity index 98% rename from libraries/chain/include/graphene/chain/authority.hpp rename to libraries/chain/include/graphene/chain/protocol/authority.hpp index 8b384410..843a4638 100644 --- a/libraries/chain/include/graphene/chain/authority.hpp +++ b/libraries/chain/include/graphene/chain/protocol/authority.hpp @@ -16,8 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/protocol/balance.hpp b/libraries/chain/include/graphene/chain/protocol/balance.hpp new file mode 100644 index 00000000..f4e56dc6 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/balance.hpp @@ -0,0 +1,32 @@ +#pragma once +#include + +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) ) diff --git a/libraries/chain/include/graphene/chain/protocol/base.hpp b/libraries/chain/include/graphene/chain/protocol/base.hpp new file mode 100644 index 00000000..d146eac2 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/base.hpp @@ -0,0 +1,83 @@ +#pragma once +#include +#include +#include + + +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 operation_result; + + struct base_operation + { + template + share_type calculate_fee(const T& params)const + { + return params.fee; + } + void get_required_authorities( vector& )const{} + void get_required_active_authorities( flat_set& )const{} + void get_required_owner_authorities( flat_set& )const{} + void get_impacted_accounts( flat_set& )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, ) diff --git a/libraries/chain/include/graphene/chain/block.hpp b/libraries/chain/include/graphene/chain/protocol/block.hpp similarity index 97% rename from libraries/chain/include/graphene/chain/block.hpp rename to libraries/chain/include/graphene/chain/protocol/block.hpp index 5b5746d0..7f7e4f4c 100644 --- a/libraries/chain/include/graphene/chain/block.hpp +++ b/libraries/chain/include/graphene/chain/protocol/block.hpp @@ -16,8 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp similarity index 93% rename from libraries/chain/include/graphene/chain/chain_parameters.hpp rename to libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index 4cf84fb3..ff202a2d 100644 --- a/libraries/chain/include/graphene/chain/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -16,14 +16,24 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include +#include +#include + +namespace graphene { namespace chain { struct fee_schedule; } } +/* +namespace fc { + template inline void pack( Stream& s, const graphene::chain::fee_schedule& value ); + template 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 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 diff --git a/libraries/chain/include/graphene/chain/protocol/config.hpp b/libraries/chain/include/graphene/chain/protocol/config.hpp new file mode 100644 index 00000000..05a3e495 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/config.hpp @@ -0,0 +1,2 @@ +#pragma once +#include diff --git a/libraries/chain/include/graphene/chain/protocol/custom.hpp b/libraries/chain/include/graphene/chain/protocol/custom.hpp new file mode 100644 index 00000000..552f5b45 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/custom.hpp @@ -0,0 +1,35 @@ + +#pragma once +#include + +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 required_auths; + uint16_t id; + vector 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) ) diff --git a/libraries/chain/include/graphene/chain/protocol/delegate.hpp b/libraries/chain/include/graphene/chain/protocol/delegate.hpp new file mode 100644 index 00000000..0782fbb1 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/delegate.hpp @@ -0,0 +1,59 @@ +#pragma once +#include +#include + +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) ); diff --git a/libraries/chain/include/graphene/chain/fee_schedule.hpp b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp similarity index 93% rename from libraries/chain/include/graphene/chain/fee_schedule.hpp rename to libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp index 401483e8..3d7a671d 100644 --- a/libraries/chain/include/graphene/chain/fee_schedule.hpp +++ b/libraries/chain/include/graphene/chain/protocol/fee_schedule.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include 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) ) - - - -} } diff --git a/libraries/chain/include/graphene/chain/protocol/market.hpp b/libraries/chain/include/graphene/chain/protocol/market.hpp new file mode 100644 index 00000000..2a10e1d3 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/market.hpp @@ -0,0 +1,147 @@ +#pragma once +#include + +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 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 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) ) diff --git a/libraries/chain/include/graphene/chain/protocol/memo.hpp b/libraries/chain/include/graphene/chain/protocol/memo.hpp new file mode 100644 index 00000000..b5bec350 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/memo.hpp @@ -0,0 +1,68 @@ +#pragma once +#include + +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 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) ) diff --git a/libraries/chain/include/graphene/chain/protocol/operations.hpp b/libraries/chain/include/graphene/chain/protocol/operations.hpp new file mode 100644 index 00000000..e162ed8c --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/operations.hpp @@ -0,0 +1,117 @@ +/* Copyright (C) Cryptonomex, Inc - All Rights Reserved **/ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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& active, + flat_set& owner, + vector& other ); + + void operation_get_impacted_accounts( const operation& op, + flat_set& 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) ) + + + + + + diff --git a/libraries/chain/include/graphene/chain/protocol/proposal.hpp b/libraries/chain/include/graphene/chain/protocol/proposal.hpp new file mode 100644 index 00000000..acefb19b --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/proposal.hpp @@ -0,0 +1,145 @@ +#pragma once +#include + +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 proposed_ops; + time_point_sec expiration_time; + optional 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 active_approvals_to_add; + flat_set active_approvals_to_remove; + flat_set owner_approvals_to_add; + flat_set owner_approvals_to_remove; + flat_set key_approvals_to_add; + flat_set 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) ) + diff --git a/libraries/chain/include/graphene/chain/transaction.hpp b/libraries/chain/include/graphene/chain/protocol/transaction.hpp similarity index 99% rename from libraries/chain/include/graphene/chain/transaction.hpp rename to libraries/chain/include/graphene/chain/protocol/transaction.hpp index a377556b..c2c084b2 100644 --- a/libraries/chain/include/graphene/chain/transaction.hpp +++ b/libraries/chain/include/graphene/chain/protocol/transaction.hpp @@ -16,8 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include #include diff --git a/libraries/chain/include/graphene/chain/protocol/transfer.hpp b/libraries/chain/include/graphene/chain/protocol/transfer.hpp new file mode 100644 index 00000000..5080884e --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/transfer.hpp @@ -0,0 +1,83 @@ +#pragma once +#include +#include + +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; + + 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; + + 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) ) + diff --git a/libraries/chain/include/graphene/chain/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp similarity index 98% rename from libraries/chain/include/graphene/chain/types.hpp rename to libraries/chain/include/graphene/chain/protocol/types.hpp index d391f19e..3c903f03 100644 --- a/libraries/chain/include/graphene/chain/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -29,11 +29,14 @@ #include #include #include +#include +#include + #include #include #include #include -#include +#include #include 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 ) + FC_REFLECT_ENUM( graphene::chain::vote_id_type::vote_type, (witness)(committee)(worker)(VOTE_TYPE_COUNT) ) FC_REFLECT( graphene::chain::vote_id_type, (content) ) diff --git a/libraries/chain/include/graphene/chain/protocol/vesting.hpp b/libraries/chain/include/graphene/chain/protocol/vesting.hpp new file mode 100644 index 00000000..9cd2323c --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/vesting.hpp @@ -0,0 +1,96 @@ +#pragma once +#include + +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 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 ) diff --git a/libraries/chain/include/graphene/chain/protocol/withdraw_permission.hpp b/libraries/chain/include/graphene/chain/protocol/withdraw_permission.hpp new file mode 100644 index 00000000..13712c5f --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/withdraw_permission.hpp @@ -0,0 +1,158 @@ +#pragma once +#include +#include + +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; + + 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) ) + diff --git a/libraries/chain/include/graphene/chain/protocol/witness.hpp b/libraries/chain/include/graphene/chain/protocol/witness.hpp new file mode 100644 index 00000000..b0292508 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/witness.hpp @@ -0,0 +1,59 @@ +#pragma once +#include + +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) ) diff --git a/libraries/chain/include/graphene/chain/protocol/worker.hpp b/libraries/chain/include/graphene/chain/protocol/worker.hpp new file mode 100644 index 00000000..968a8dc7 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/worker.hpp @@ -0,0 +1,82 @@ +#pragma once +#include + +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) ) + diff --git a/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp b/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp index 83c3e5a7..6054763c 100644 --- a/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp +++ b/libraries/chain/include/graphene/chain/transaction_evaluation_state.hpp @@ -16,9 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include -#include +#include namespace graphene { namespace chain { class database; diff --git a/libraries/chain/include/graphene/chain/transaction_object.hpp b/libraries/chain/include/graphene/chain/transaction_object.hpp index 06ed0e74..e8f630e7 100644 --- a/libraries/chain/include/graphene/chain/transaction_object.hpp +++ b/libraries/chain/include/graphene/chain/transaction_object.hpp @@ -18,7 +18,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/libraries/chain/include/graphene/chain/transfer_evaluator.hpp b/libraries/chain/include/graphene/chain/transfer_evaluator.hpp index a4ab5cc7..b9c70902 100644 --- a/libraries/chain/include/graphene/chain/transfer_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/transfer_evaluator.hpp @@ -16,8 +16,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once +#include #include -#include #include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp index e935f434..efac5243 100644 --- a/libraries/chain/include/graphene/chain/vesting_balance_object.hpp +++ b/libraries/chain/include/graphene/chain/vesting_balance_object.hpp @@ -17,14 +17,16 @@ */ #pragma once -#include +#include +#include +#include #include #include -#include -#include -#include +#include + + namespace graphene { namespace chain { using namespace graphene::db; diff --git a/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp b/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp index a89d1cc1..145ab5bf 100644 --- a/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp +++ b/libraries/chain/include/graphene/chain/withdraw_permission_object.hpp @@ -16,8 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include -#include +#include #include namespace graphene { namespace chain { diff --git a/libraries/chain/include/graphene/chain/witness_object.hpp b/libraries/chain/include/graphene/chain/witness_object.hpp index 89d0b527..875db07e 100644 --- a/libraries/chain/include/graphene/chain/witness_object.hpp +++ b/libraries/chain/include/graphene/chain/witness_object.hpp @@ -16,7 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include +#include #include #include diff --git a/libraries/chain/include/graphene/chain/witness_schedule_object.hpp b/libraries/chain/include/graphene/chain/witness_schedule_object.hpp index 2e0d43f5..2819d20f 100644 --- a/libraries/chain/include/graphene/chain/witness_schedule_object.hpp +++ b/libraries/chain/include/graphene/chain/witness_schedule_object.hpp @@ -20,7 +20,7 @@ // needed to serialize witness_scheduler #include -#include +#include #include #include diff --git a/libraries/chain/include/graphene/chain/worker_evaluator.hpp b/libraries/chain/include/graphene/chain/worker_evaluator.hpp index 98865b9c..d22843b5 100644 --- a/libraries/chain/include/graphene/chain/worker_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/worker_evaluator.hpp @@ -17,10 +17,121 @@ */ #pragma once #include -#include 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 + { + 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& stake_vote_tallies)const { + return stake_vote_tallies[vote_for] - stake_vote_tallies[vote_against]; + } + }; + + typedef flat_index worker_index; + + class worker_create_evaluator : public 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) + ) diff --git a/libraries/chain/include/graphene/chain/worker_object.hpp b/libraries/chain/include/graphene/chain/worker_object.hpp deleted file mode 100644 index 9b7af36f..00000000 --- a/libraries/chain/include/graphene/chain/worker_object.hpp +++ /dev/null @@ -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 -#include - -#include - -#include - -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 - void operator()( WorkerType& worker)const - { - static_assert(worker_type::tag::value == - worker_initializer::tag::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().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 - 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 - { - 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& stake_vote_tallies)const { - return stake_vote_tallies[vote_for] - stake_vote_tallies[vote_against]; - } - }; - - typedef flat_index 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) - ) diff --git a/libraries/chain/limit_order_evaluator.cpp b/libraries/chain/limit_order_evaluator.cpp deleted file mode 100644 index 88cc864b..00000000 --- a/libraries/chain/limit_order_evaluator.cpp +++ /dev/null @@ -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 -#include -#include -#include - -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& 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 diff --git a/libraries/chain/call_order_evaluator.cpp b/libraries/chain/market_evaluator.cpp similarity index 67% rename from libraries/chain/call_order_evaluator.cpp rename to libraries/chain/market_evaluator.cpp index 379e2287..22f1b76b 100644 --- a/libraries/chain/call_order_evaluator.cpp +++ b/libraries/chain/market_evaluator.cpp @@ -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 -#include +#include #include -#include -#include #include 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& 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 { diff --git a/libraries/chain/operations.cpp b/libraries/chain/operations.cpp deleted file mode 100644 index 002f2313..00000000 --- a/libraries/chain/operations.cpp +++ /dev/null @@ -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 -#include -#include -#include - -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): - * ::= | " " - * ::=