Implement #103 - Override Transfers by Issuer

This commit is contained in:
Daniel Larimer 2015-07-01 16:21:18 -04:00
parent 17c999ecd5
commit bb71e1933b
7 changed files with 114 additions and 5 deletions

View file

@ -81,6 +81,7 @@ void database::initialize_evaluators()
register_evaluator<limit_order_cancel_evaluator>();
register_evaluator<call_order_update_evaluator>();
register_evaluator<transfer_evaluator>();
register_evaluator<override_transfer_evaluator>();
register_evaluator<asset_fund_fee_pool_evaluator>();
register_evaluator<asset_publish_feeds_evaluator>();
register_evaluator<proposal_create_evaluator>();

View file

@ -90,6 +90,7 @@ namespace graphene { namespace chain {
bool charges_market_fees()const { return options.flags & charge_market_fee; }
/// @return true if this asset may only be transferred to/from the issuer or market orders
bool is_transfer_restricted()const { return options.flags & transfer_restricted; }
bool can_override()const { return options.flags & override_authority; }
/// Helper function to get an asset object with the given amount in this asset's type
asset amount(share_type a)const { return asset(a, id); }

View file

@ -501,13 +501,13 @@ namespace graphene { namespace chain {
*/
struct transfer_operation
{
asset fee;
asset fee;
/// Account to transfer asset from
account_id_type from;
account_id_type from;
/// Account to transfer asset to
account_id_type to;
account_id_type to;
/// The amount of asset to transfer from @ref from to @ref to
asset amount;
asset amount;
/// User provided data encrypted to the memo key of the "to" account
optional<memo_data> memo;
@ -524,6 +524,41 @@ namespace graphene { namespace chain {
}
};
/**
* @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
{
asset fee;
account_id_type issuer;
/// Account to transfer asset from
account_id_type from;
/// Account to transfer asset to
account_id_type to;
/// The amount of asset to transfer from @ref from to @ref to
asset amount;
/// User provided data encrypted to the memo key of the "to" account
optional<memo_data> memo;
account_id_type fee_payer()const { return issuer; }
void get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&)const;
void validate()const;
share_type calculate_fee(const fee_schedule_type& k)const;
void get_balance_delta( balance_accumulator& acc, const operation_result& result = asset())const
{
acc.adjust( fee_payer(), -fee );
acc.adjust( from, -amount );
acc.adjust( to, amount );
}
};
/**
* @ingroup operations
*/
@ -1420,7 +1455,8 @@ namespace graphene { namespace chain {
worker_create_operation,
custom_operation,
assert_operation,
balance_claim_operation
balance_claim_operation,
override_transfer_operation
> operation;
/// @} // operations group
@ -1588,6 +1624,8 @@ FC_REFLECT( graphene::chain::call_order_update_operation, (fee)(funding_account)
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)

View file

@ -31,4 +31,13 @@ namespace graphene { namespace chain {
void_result do_apply( const transfer_operation& o );
};
class override_transfer_evaluator : public evaluator<override_transfer_evaluator>
{
public:
typedef override_transfer_operation operation_type;
void_result do_evaluate( const override_transfer_operation& o );
void_result do_apply( const override_transfer_operation& o );
};
} } // graphene::chain

View file

@ -227,6 +227,15 @@ share_type transfer_operation::calculate_fee( const fee_schedule_type& schedule
return core_fee_required;
}
share_type override_transfer_operation::calculate_fee( const fee_schedule_type& schedule )const
{
share_type core_fee_required = schedule.transfer_fee;
if( memo )
core_fee_required += schedule.total_data_fee(memo->message);
return core_fee_required;
}
struct key_data_validate
{
typedef void result_type;
@ -291,6 +300,20 @@ void transfer_operation::validate()const
FC_ASSERT( amount.amount > 0 );
}
void override_transfer_operation::get_required_auth(flat_set<account_id_type>& active_auth_set,
flat_set<account_id_type>&) const
{
active_auth_set.insert( issuer );
}
void override_transfer_operation::validate()const
{
FC_ASSERT( fee.amount >= 0 );
FC_ASSERT( from != to );
FC_ASSERT( amount.amount > 0 );
FC_ASSERT( issuer != from );
}
void asset_create_operation::get_required_auth(flat_set<account_id_type>& active_auth_set, flat_set<account_id_type>&) const
{
active_auth_set.insert(issuer);

View file

@ -53,4 +53,40 @@ void_result transfer_evaluator::do_apply( const transfer_operation& o )
return void_result();
} FC_CAPTURE_AND_RETHROW( (o) ) }
void_result override_transfer_evaluator::do_evaluate( const override_transfer_operation& op )
{ try {
database& d = db();
const asset_object& asset_type = op.amount.asset_id(d);
FC_ASSERT( asset_type.can_override() );
FC_ASSERT( asset_type.issuer == op.issuer );
const account_object& from_account = op.from(d);
const account_object& to_account = op.to(d);
const asset_object& fee_asset_type = op.fee.asset_id(d);
if( asset_type.options.flags & white_list )
{
FC_ASSERT( to_account.is_authorized_asset( asset_type ) );
FC_ASSERT( from_account.is_authorized_asset( asset_type ) );
}
if( fee_asset_type.options.flags & white_list )
FC_ASSERT( from_account.is_authorized_asset( asset_type ) );
FC_ASSERT( d.get_balance( &from_account, &asset_type ).amount >= op.amount.amount,
"", ("total_transfer",op.amount)("balance",d.get_balance(&from_account, &asset_type).amount) );
return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }
void_result override_transfer_evaluator::do_apply( const override_transfer_operation& o )
{ try {
db().adjust_balance( o.from, -o.amount );
db().adjust_balance( o.to, o.amount );
return void_result();
} FC_CAPTURE_AND_RETHROW( (o) ) }
} } // graphene::chain

View file

@ -187,6 +187,7 @@ struct operation_get_impacted_accounts
void operator()( const worker_create_operation& )const {}
void operator()( const assert_operation& )const {}
void operator()( const balance_claim_operation& )const {}
void operator()( const override_transfer_operation& )const {}
};