Implement #103 - Override Transfers by Issuer
This commit is contained in:
parent
17c999ecd5
commit
bb71e1933b
7 changed files with 114 additions and 5 deletions
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue