Implement buyback accounts #538
This commit is contained in:
parent
bd22592d19
commit
c33fe35e4e
21 changed files with 373 additions and 4 deletions
|
|
@ -346,6 +346,8 @@ namespace graphene { namespace app {
|
|||
break;
|
||||
case impl_special_authority_object_type:
|
||||
break;
|
||||
case impl_buyback_object_type:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ add_library( graphene_chain
|
|||
worker_evaluator.cpp
|
||||
confidential_evaluator.cpp
|
||||
special_authority.cpp
|
||||
buyback.cpp
|
||||
|
||||
account_object.cpp
|
||||
asset_object.cpp
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include <fc/smart_ref_impl.hpp>
|
||||
|
||||
#include <graphene/chain/account_evaluator.hpp>
|
||||
#include <graphene/chain/buyback.hpp>
|
||||
#include <graphene/chain/buyback_object.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
|
@ -80,6 +82,8 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio
|
|||
evaluate_special_authority( d, *op.extensions.value.owner_special_authority );
|
||||
if( op.extensions.value.active_special_authority.valid() )
|
||||
evaluate_special_authority( d, *op.extensions.value.active_special_authority );
|
||||
if( op.extensions.value.buyback_options.valid() )
|
||||
evaluate_buyback_account_options( d, *op.extensions.value.buyback_options );
|
||||
|
||||
uint32_t max_vote_id = global_props.next_available_vote_id;
|
||||
|
||||
|
|
@ -115,6 +119,7 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio
|
|||
object_id_type account_create_evaluator::do_apply( const account_create_operation& o )
|
||||
{ try {
|
||||
|
||||
database& d = db();
|
||||
uint16_t referrer_percent = o.referrer_percent;
|
||||
bool has_small_percent = (
|
||||
(db().head_block_time() <= HARDFORK_453_TIME)
|
||||
|
|
@ -154,6 +159,11 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
|
|||
obj.owner_special_authority = *(o.extensions.value.owner_special_authority);
|
||||
if( o.extensions.value.active_special_authority.valid() )
|
||||
obj.active_special_authority = *(o.extensions.value.active_special_authority);
|
||||
if( o.extensions.value.buyback_options.valid() )
|
||||
{
|
||||
obj.allowed_assets = o.extensions.value.buyback_options->markets;
|
||||
obj.allowed_assets->emplace( o.extensions.value.buyback_options->asset_to_buy );
|
||||
}
|
||||
});
|
||||
|
||||
if( has_small_percent )
|
||||
|
|
@ -186,6 +196,21 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
|
|||
} );
|
||||
}
|
||||
|
||||
if( o.extensions.value.buyback_options.valid() )
|
||||
{
|
||||
asset_id_type asset_to_buy = o.extensions.value.buyback_options->asset_to_buy;
|
||||
|
||||
d.create< buyback_object >( [&]( buyback_object& bo )
|
||||
{
|
||||
bo.asset_to_buy = asset_to_buy;
|
||||
} );
|
||||
|
||||
d.modify( asset_to_buy(d), [&]( asset_object& a )
|
||||
{
|
||||
a.buyback_account = new_acnt_object.id;
|
||||
} );
|
||||
}
|
||||
|
||||
return new_acnt_object.id;
|
||||
} FC_CAPTURE_AND_RETHROW((o)) }
|
||||
|
||||
|
|
|
|||
45
libraries/chain/buyback.cpp
Normal file
45
libraries/chain/buyback.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <graphene/chain/protocol/buyback.hpp>
|
||||
#include <graphene/chain/database.hpp>
|
||||
#include <graphene/chain/exceptions.hpp>
|
||||
#include <graphene/chain/hardfork.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
void evaluate_buyback_account_options( const database& db, const buyback_account_options& bbo )
|
||||
{
|
||||
FC_ASSERT( db.head_block_time() >= HARDFORK_538_TIME );
|
||||
const asset_object& a = bbo.asset_to_buy(db);
|
||||
GRAPHENE_ASSERT( a.issuer == bbo.asset_to_buy_issuer,
|
||||
account_create_buyback_incorrect_issuer, "Incorrect asset issuer specified in buyback_account_options", ("asset", a)("bbo", bbo) );
|
||||
GRAPHENE_ASSERT( !a.buyback_account.valid(),
|
||||
account_create_buyback_already_exists, "Cannot create buyback for asset which already has buyback", ("asset", a)("bbo", bbo) );
|
||||
// TODO: Replace with chain parameter #554
|
||||
GRAPHENE_ASSERT( bbo.markets.size() < GRAPHENE_DEFAULT_MAX_BUYBACK_MARKETS,
|
||||
account_create_buyback_too_many_markets, "Too many buyback markets", ("asset", a)("bbo", bbo) );
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
#include <graphene/chain/balance_object.hpp>
|
||||
#include <graphene/chain/block_summary_object.hpp>
|
||||
#include <graphene/chain/budget_record_object.hpp>
|
||||
#include <graphene/chain/buyback_object.hpp>
|
||||
#include <graphene/chain/chain_property_object.hpp>
|
||||
#include <graphene/chain/committee_member_object.hpp>
|
||||
#include <graphene/chain/confidential_object.hpp>
|
||||
|
|
@ -210,6 +211,7 @@ void database::initialize_indexes()
|
|||
add_index< primary_index<simple_index<witness_schedule_object > > >();
|
||||
add_index< primary_index<simple_index<budget_record_object > > >();
|
||||
add_index< primary_index< special_authority_index > >();
|
||||
add_index< primary_index< buyback_index > >();
|
||||
}
|
||||
|
||||
void database::init_genesis(const genesis_state_type& genesis_state)
|
||||
|
|
|
|||
|
|
@ -33,9 +33,11 @@
|
|||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/asset_object.hpp>
|
||||
#include <graphene/chain/budget_record_object.hpp>
|
||||
#include <graphene/chain/buyback_object.hpp>
|
||||
#include <graphene/chain/chain_property_object.hpp>
|
||||
#include <graphene/chain/committee_member_object.hpp>
|
||||
#include <graphene/chain/global_property_object.hpp>
|
||||
#include <graphene/chain/market_object.hpp>
|
||||
#include <graphene/chain/special_authority_object.hpp>
|
||||
#include <graphene/chain/vesting_balance_object.hpp>
|
||||
#include <graphene/chain/vote_count.hpp>
|
||||
|
|
@ -522,10 +524,88 @@ void update_top_n_authorities( database& db )
|
|||
} );
|
||||
}
|
||||
|
||||
void create_buyback_orders( database& db )
|
||||
{
|
||||
const auto& bbo_idx = db.get_index_type< buyback_index >().indices().get<by_id>();
|
||||
const auto& bal_idx = db.get_index_type< account_balance_index >().indices().get< by_account_asset >();
|
||||
|
||||
for( const buyback_object& bbo : bbo_idx )
|
||||
{
|
||||
const asset_object& asset_to_buy = bbo.asset_to_buy(db);
|
||||
assert( asset_to_buy.buyback_account.valid() );
|
||||
|
||||
const account_object& buyback_account = (*(asset_to_buy.buyback_account))(db);
|
||||
asset_id_type next_asset = asset_id_type();
|
||||
|
||||
if( !buyback_account.allowed_assets.valid() )
|
||||
{
|
||||
wlog( "skipping buyback account ${b} at block ${n} because allowed_assets does not exist", ("b", buyback_account)("n", db.head_block_num()) );
|
||||
continue;
|
||||
}
|
||||
|
||||
while( true )
|
||||
{
|
||||
auto it = bal_idx.lower_bound( boost::make_tuple( buyback_account.id, next_asset ) );
|
||||
if( it == bal_idx.end() )
|
||||
break;
|
||||
if( it->owner != buyback_account.id )
|
||||
break;
|
||||
asset_id_type asset_to_sell = it->asset_type;
|
||||
share_type amount_to_sell = it->balance;
|
||||
next_asset = asset_to_sell + 1;
|
||||
if( asset_to_sell == asset_to_buy.id )
|
||||
continue;
|
||||
if( amount_to_sell == 0 )
|
||||
continue;
|
||||
if( buyback_account.allowed_assets->find( asset_to_sell ) == buyback_account.allowed_assets->end() )
|
||||
{
|
||||
wlog( "buyback account ${b} not selling disallowed holdings of asset ${a} at block ${n}", ("b", buyback_account)("a", asset_to_sell)("n", db.head_block_num()) );
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
transaction_evaluation_state buyback_context(&db);
|
||||
buyback_context.skip_fee_schedule_check = true;
|
||||
|
||||
limit_order_create_operation create_vop;
|
||||
create_vop.fee = asset( 0, asset_id_type() );
|
||||
create_vop.seller = buyback_account.id;
|
||||
create_vop.amount_to_sell = asset( amount_to_sell, asset_to_sell );
|
||||
create_vop.min_to_receive = asset( 1, asset_to_buy.id );
|
||||
create_vop.expiration = time_point_sec::maximum();
|
||||
create_vop.fill_or_kill = false;
|
||||
|
||||
limit_order_id_type order_id = db.apply_operation( buyback_context, create_vop ).get< object_id_type >();
|
||||
|
||||
if( db.find( order_id ) != nullptr )
|
||||
{
|
||||
limit_order_cancel_operation cancel_vop;
|
||||
cancel_vop.fee = asset( 0, asset_id_type() );
|
||||
cancel_vop.order = order_id;
|
||||
cancel_vop.fee_paying_account = buyback_account.id;
|
||||
|
||||
db.apply_operation( buyback_context, cancel_vop );
|
||||
}
|
||||
}
|
||||
catch( const fc::exception& e )
|
||||
{
|
||||
// we can in fact get here, e.g. if asset issuer of buy/sell asset blacklists/whitelists the buyback account
|
||||
wlog( "Skipping buyback processing selling ${as} for ${ab} for buyback account ${b} at block ${n}; exception was ${e}",
|
||||
("as", asset_to_sell)("ab", asset_to_buy)("b", buyback_account)("n", db.head_block_num())("e", e.to_detail_string()) );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void database::perform_chain_maintenance(const signed_block& next_block, const global_property_object& global_props)
|
||||
{
|
||||
const auto& gpo = get_global_properties();
|
||||
|
||||
create_buyback_orders(*this);
|
||||
|
||||
struct vote_tally_helper {
|
||||
database& d;
|
||||
const global_property_object& props;
|
||||
|
|
|
|||
4
libraries/chain/hardfork.d/538.hf
Normal file
4
libraries/chain/hardfork.d/538.hf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// #538 Buyback accounts
|
||||
#ifndef HARDFORK_538_TIME
|
||||
#define HARDFORK_538_TIME (fc::time_point_sec( 1455127200 ))
|
||||
#endif
|
||||
|
|
@ -208,6 +208,13 @@ namespace graphene { namespace chain {
|
|||
special_authority owner_special_authority = no_special_authority();
|
||||
special_authority active_special_authority = no_special_authority();
|
||||
|
||||
/**
|
||||
* This is a set of assets which the account is allowed to have.
|
||||
* This is utilized to restrict buyback accounts to the assets that trade in their markets.
|
||||
* In the future we may expand this to allow accounts to e.g. voluntarily restrict incoming transfers.
|
||||
*/
|
||||
optional< flat_set<asset_id_type> > allowed_assets;
|
||||
|
||||
bool has_special_authority()const
|
||||
{
|
||||
return (owner_special_authority.which() != special_authority::tag< no_special_authority >::value)
|
||||
|
|
@ -358,6 +365,7 @@ FC_REFLECT_DERIVED( graphene::chain::account_object,
|
|||
(whitelisting_accounts)(blacklisted_accounts)
|
||||
(cashback_vb)
|
||||
(owner_special_authority)(active_special_authority)
|
||||
(allowed_assets)
|
||||
)
|
||||
|
||||
FC_REFLECT_DERIVED( graphene::chain::account_balance_object,
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ namespace graphene { namespace chain {
|
|||
/// Extra data associated with BitAssets. This field is non-null if and only if is_market_issued() returns true
|
||||
optional<asset_bitasset_data_id_type> bitasset_data_id;
|
||||
|
||||
optional<account_id_type> buyback_account;
|
||||
|
||||
asset_id_type get_id()const { return id; }
|
||||
|
||||
void validate()const
|
||||
|
|
@ -261,4 +263,5 @@ FC_REFLECT_DERIVED( graphene::chain::asset_object, (graphene::db::object),
|
|||
(options)
|
||||
(dynamic_asset_data_id)
|
||||
(bitasset_data_id)
|
||||
(buyback_account)
|
||||
)
|
||||
|
|
|
|||
34
libraries/chain/include/graphene/chain/buyback.hpp
Normal file
34
libraries/chain/include/graphene/chain/buyback.hpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/buyback.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
class database;
|
||||
|
||||
void evaluate_buyback_account_options( const database& db, const buyback_account_options& auth );
|
||||
|
||||
} } // graphene::chain
|
||||
67
libraries/chain/include/graphene/chain/buyback_object.hpp
Normal file
67
libraries/chain/include/graphene/chain/buyback_object.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
#include <graphene/db/object.hpp>
|
||||
#include <graphene/db/generic_index.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
/**
|
||||
* buyback_authority_object only exists to help with a specific indexing problem.
|
||||
* We want to be able to iterate over all assets that have a buyback program.
|
||||
* However, assets which have a buyback program are very rare. So rather
|
||||
* than indexing asset_object by the buyback field (requiring additional
|
||||
* bookkeeping for every asset), we instead maintain a buyback_object
|
||||
* pointing to each asset which has buyback (requiring additional
|
||||
* bookkeeping only for every asset which has buyback).
|
||||
*
|
||||
* This class is an implementation detail.
|
||||
*/
|
||||
|
||||
class buyback_object : public graphene::db::abstract_object< buyback_object >
|
||||
{
|
||||
public:
|
||||
static const uint8_t space_id = implementation_ids;
|
||||
static const uint8_t type_id = impl_buyback_object_type;
|
||||
|
||||
asset_id_type asset_to_buy;
|
||||
};
|
||||
|
||||
struct by_asset;
|
||||
|
||||
typedef multi_index_container<
|
||||
buyback_object,
|
||||
indexed_by<
|
||||
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
|
||||
ordered_unique< tag<by_asset>, member< buyback_object, asset_id_type, &buyback_object::asset_to_buy> >
|
||||
>
|
||||
> buyback_multi_index_type;
|
||||
|
||||
typedef generic_index< buyback_object, buyback_multi_index_type > buyback_index;
|
||||
|
||||
} } // graphene::chain
|
||||
|
||||
FC_REFLECT( graphene::chain::buyback_object, (asset_to_buy) )
|
||||
|
|
@ -107,6 +107,7 @@
|
|||
#define GRAPHENE_DEFAULT_FEE_LIQUIDATION_THRESHOLD GRAPHENE_BLOCKCHAIN_PRECISION * 100;
|
||||
#define GRAPHENE_DEFAULT_ACCOUNTS_PER_FEE_SCALE 1000
|
||||
#define GRAPHENE_DEFAULT_ACCOUNT_FEE_SCALE_BITSHIFTS 4
|
||||
#define GRAPHENE_DEFAULT_MAX_BUYBACK_MARKETS 4
|
||||
|
||||
#define GRAPHENE_MAX_WORKER_NAME_LENGTH 63
|
||||
|
||||
|
|
|
|||
|
|
@ -412,12 +412,14 @@ namespace graphene { namespace chain {
|
|||
|
||||
//////////////////// db_block.cpp ////////////////////
|
||||
|
||||
public:
|
||||
// these were formerly private, but they have a fairly well-defined API, so let's make them public
|
||||
void apply_block( const signed_block& next_block, uint32_t skip = skip_nothing );
|
||||
processed_transaction apply_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
|
||||
operation_result apply_operation( transaction_evaluation_state& eval_state, const operation& op );
|
||||
private:
|
||||
void _apply_block( const signed_block& next_block );
|
||||
processed_transaction _apply_transaction( const signed_transaction& trx );
|
||||
operation_result apply_operation( transaction_evaluation_state& eval_state, const operation& op );
|
||||
|
||||
|
||||
///Steps involved in applying a new block
|
||||
///@{
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ namespace graphene { namespace chain {
|
|||
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_create );
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( max_auth_exceeded, account_create, 1, "Exceeds max authority fan-out" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( auth_account_not_found, account_create, 2, "Auth account not found" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_incorrect_issuer, account_create, 3, "Incorrect issuer specified for account" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_already_exists, account_create, 4, "Cannot create buyback for asset which already has buyback" )
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( buyback_too_many_markets, account_create, 5, "Too many buyback markets" )
|
||||
|
||||
GRAPHENE_DECLARE_OP_BASE_EXCEPTIONS( account_update );
|
||||
GRAPHENE_DECLARE_OP_EVALUATE_EXCEPTION( max_auth_exceeded, account_update, 1, "Exceeds max authority fan-out" )
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ bool _is_authorized_asset(const database& d, const account_object& acct, const a
|
|||
inline bool is_authorized_asset(const database& d, const account_object& acct, const asset_object& asset_obj)
|
||||
{
|
||||
bool fast_check = !(asset_obj.options.flags & white_list);
|
||||
fast_check &= !(acct.allowed_assets.valid());
|
||||
|
||||
if( fast_check )
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <graphene/chain/protocol/base.hpp>
|
||||
#include <graphene/chain/protocol/buyback.hpp>
|
||||
#include <graphene/chain/protocol/ext.hpp>
|
||||
#include <graphene/chain/protocol/special_authority.hpp>
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
|
@ -69,6 +70,7 @@ namespace graphene { namespace chain {
|
|||
optional< void_t > null_ext;
|
||||
optional< special_authority > owner_special_authority;
|
||||
optional< special_authority > active_special_authority;
|
||||
optional< buyback_account_options > buyback_options;
|
||||
};
|
||||
|
||||
struct fee_parameters_type
|
||||
|
|
@ -98,6 +100,14 @@ namespace graphene { namespace chain {
|
|||
account_id_type fee_payer()const { return registrar; }
|
||||
void validate()const;
|
||||
share_type calculate_fee(const fee_parameters_type& )const;
|
||||
|
||||
void get_required_active_authorities( flat_set<account_id_type>& a )const
|
||||
{
|
||||
// registrar should be required anyway as it is the fee_payer(), but we insert it here just to be sure
|
||||
a.insert( registrar );
|
||||
if( extensions.value.buyback_options.valid() )
|
||||
a.insert( extensions.value.buyback_options->asset_to_buy_issuer );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -258,7 +268,7 @@ FC_REFLECT_TYPENAME( graphene::chain::account_whitelist_operation::account_listi
|
|||
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::ext, (null_ext)(owner_special_authority)(active_special_authority) )
|
||||
FC_REFLECT(graphene::chain::account_create_operation::ext, (null_ext)(owner_special_authority)(active_special_authority)(buyback_options) )
|
||||
FC_REFLECT( graphene::chain::account_create_operation,
|
||||
(fee)(registrar)
|
||||
(referrer)(referrer_percent)
|
||||
|
|
|
|||
|
|
@ -109,6 +109,11 @@ namespace graphene { namespace chain {
|
|||
uint32_t num_auths()const { return account_auths.size() + key_auths.size() + address_auths.size(); }
|
||||
void clear() { account_auths.clear(); key_auths.clear(); }
|
||||
|
||||
static authority null_authority()
|
||||
{
|
||||
return authority( 1, GRAPHENE_NULL_ACCOUNT, 1 );
|
||||
}
|
||||
|
||||
uint32_t weight_threshold = 0;
|
||||
flat_map<account_id_type,weight_type> account_auths;
|
||||
flat_map<public_key_type,weight_type> key_auths;
|
||||
|
|
|
|||
52
libraries/chain/include/graphene/chain/protocol/buyback.hpp
Normal file
52
libraries/chain/include/graphene/chain/protocol/buyback.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Cryptonomex, Inc., and contributors.
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <graphene/chain/protocol/types.hpp>
|
||||
|
||||
namespace graphene { namespace chain {
|
||||
|
||||
struct buyback_account_options
|
||||
{
|
||||
/**
|
||||
* The asset to buy.
|
||||
*/
|
||||
asset_id_type asset_to_buy;
|
||||
|
||||
/**
|
||||
* Issuer of the asset. Must sign the transaction, must match issuer
|
||||
* of specified asset.
|
||||
*/
|
||||
account_id_type asset_to_buy_issuer;
|
||||
|
||||
/**
|
||||
* What assets the account is willing to buy with.
|
||||
* Other assets will just sit there since the account has null authority.
|
||||
*/
|
||||
flat_set< asset_id_type > markets;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
FC_REFLECT( graphene::chain::buyback_account_options, (asset_to_buy)(asset_to_buy_issuer)(markets) );
|
||||
|
|
@ -153,7 +153,8 @@ namespace graphene { namespace chain {
|
|||
impl_chain_property_object_type,
|
||||
impl_witness_schedule_object_type,
|
||||
impl_budget_record_object_type,
|
||||
impl_special_authority_object_type
|
||||
impl_special_authority_object_type,
|
||||
impl_buyback_object_type
|
||||
};
|
||||
|
||||
//typedef fc::unsigned_int object_id_type;
|
||||
|
|
@ -203,6 +204,7 @@ namespace graphene { namespace chain {
|
|||
class witness_schedule_object;
|
||||
class budget_record_object;
|
||||
class special_authority_object;
|
||||
class buyback_object;
|
||||
|
||||
typedef object_id< implementation_ids, impl_global_property_object_type, global_property_object> global_property_id_type;
|
||||
typedef object_id< implementation_ids, impl_dynamic_global_property_object_type, dynamic_global_property_object> dynamic_global_property_id_type;
|
||||
|
|
@ -221,6 +223,7 @@ namespace graphene { namespace chain {
|
|||
typedef object_id< implementation_ids, impl_budget_record_object_type, budget_record_object > budget_record_id_type;
|
||||
typedef object_id< implementation_ids, impl_blinded_balance_object_type, blinded_balance_object > blinded_balance_id_type;
|
||||
typedef object_id< implementation_ids, impl_special_authority_object_type, special_authority_object > special_authority_id_type;
|
||||
typedef object_id< implementation_ids, impl_buyback_object_type, buyback_object > buyback_id_type;
|
||||
|
||||
typedef fc::array<char, GRAPHENE_MAX_ASSET_SYMBOL_LENGTH> symbol_type;
|
||||
typedef fc::ripemd160 block_id_type;
|
||||
|
|
@ -351,6 +354,7 @@ FC_REFLECT_ENUM( graphene::chain::impl_object_type,
|
|||
(impl_witness_schedule_object_type)
|
||||
(impl_budget_record_object_type)
|
||||
(impl_special_authority_object_type)
|
||||
(impl_buyback_object_type)
|
||||
)
|
||||
|
||||
FC_REFLECT_TYPENAME( graphene::chain::share_type )
|
||||
|
|
|
|||
|
|
@ -37,6 +37,13 @@ bool _is_authorized_asset(
|
|||
const account_object& acct,
|
||||
const asset_object& asset_obj)
|
||||
{
|
||||
if( acct.allowed_assets.valid() )
|
||||
{
|
||||
if( acct.allowed_assets->find( asset_obj.id ) == acct.allowed_assets->end() )
|
||||
return false;
|
||||
// must still pass other checks even if it is in allowed_assets
|
||||
}
|
||||
|
||||
for( const auto id : acct.blacklisting_accounts )
|
||||
{
|
||||
if( asset_obj.options.blacklist_authorities.find(id) != asset_obj.options.blacklist_authorities.end() )
|
||||
|
|
|
|||
|
|
@ -190,6 +190,19 @@ void account_create_operation::validate()const
|
|||
validate_special_authority( *extensions.value.owner_special_authority );
|
||||
if( extensions.value.active_special_authority.valid() )
|
||||
validate_special_authority( *extensions.value.active_special_authority );
|
||||
if( extensions.value.buyback_options.valid() )
|
||||
{
|
||||
FC_ASSERT( !(extensions.value.owner_special_authority.valid()) );
|
||||
FC_ASSERT( !(extensions.value.active_special_authority.valid()) );
|
||||
FC_ASSERT( owner == authority::null_authority() );
|
||||
FC_ASSERT( active == authority::null_authority() );
|
||||
size_t n_markets = extensions.value.buyback_options->markets.size();
|
||||
FC_ASSERT( n_markets > 0 );
|
||||
for( const asset_id_type m : extensions.value.buyback_options->markets )
|
||||
{
|
||||
FC_ASSERT( m != extensions.value.buyback_options->asset_to_buy );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue