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<limit_order_cancel_evaluator>();
|
||||||
register_evaluator<call_order_update_evaluator>();
|
register_evaluator<call_order_update_evaluator>();
|
||||||
register_evaluator<transfer_evaluator>();
|
register_evaluator<transfer_evaluator>();
|
||||||
|
register_evaluator<override_transfer_evaluator>();
|
||||||
register_evaluator<asset_fund_fee_pool_evaluator>();
|
register_evaluator<asset_fund_fee_pool_evaluator>();
|
||||||
register_evaluator<asset_publish_feeds_evaluator>();
|
register_evaluator<asset_publish_feeds_evaluator>();
|
||||||
register_evaluator<proposal_create_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; }
|
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
|
/// @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 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
|
/// 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); }
|
asset amount(share_type a)const { return asset(a, id); }
|
||||||
|
|
|
||||||
|
|
@ -501,13 +501,13 @@ namespace graphene { namespace chain {
|
||||||
*/
|
*/
|
||||||
struct transfer_operation
|
struct transfer_operation
|
||||||
{
|
{
|
||||||
asset fee;
|
asset fee;
|
||||||
/// Account to transfer asset from
|
/// Account to transfer asset from
|
||||||
account_id_type from;
|
account_id_type from;
|
||||||
/// Account to transfer asset to
|
/// 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
|
/// 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
|
/// User provided data encrypted to the memo key of the "to" account
|
||||||
optional<memo_data> memo;
|
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
|
* @ingroup operations
|
||||||
*/
|
*/
|
||||||
|
|
@ -1420,7 +1455,8 @@ namespace graphene { namespace chain {
|
||||||
worker_create_operation,
|
worker_create_operation,
|
||||||
custom_operation,
|
custom_operation,
|
||||||
assert_operation,
|
assert_operation,
|
||||||
balance_claim_operation
|
balance_claim_operation,
|
||||||
|
override_transfer_operation
|
||||||
> operation;
|
> operation;
|
||||||
|
|
||||||
/// @} // operations group
|
/// @} // operations group
|
||||||
|
|
@ -1588,6 +1624,8 @@ FC_REFLECT( graphene::chain::call_order_update_operation, (fee)(funding_account)
|
||||||
|
|
||||||
FC_REFLECT( graphene::chain::transfer_operation,
|
FC_REFLECT( graphene::chain::transfer_operation,
|
||||||
(fee)(from)(to)(amount)(memo) )
|
(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,
|
FC_REFLECT( graphene::chain::asset_create_operation,
|
||||||
(fee)
|
(fee)
|
||||||
|
|
|
||||||
|
|
@ -31,4 +31,13 @@ namespace graphene { namespace chain {
|
||||||
void_result do_apply( const transfer_operation& o );
|
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
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,15 @@ share_type transfer_operation::calculate_fee( const fee_schedule_type& schedule
|
||||||
return core_fee_required;
|
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
|
struct key_data_validate
|
||||||
{
|
{
|
||||||
typedef void result_type;
|
typedef void result_type;
|
||||||
|
|
@ -291,6 +300,20 @@ void transfer_operation::validate()const
|
||||||
FC_ASSERT( amount.amount > 0 );
|
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
|
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);
|
active_auth_set.insert(issuer);
|
||||||
|
|
|
||||||
|
|
@ -53,4 +53,40 @@ void_result transfer_evaluator::do_apply( const transfer_operation& o )
|
||||||
return void_result();
|
return void_result();
|
||||||
} FC_CAPTURE_AND_RETHROW( (o) ) }
|
} 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
|
} } // graphene::chain
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,7 @@ struct operation_get_impacted_accounts
|
||||||
void operator()( const worker_create_operation& )const {}
|
void operator()( const worker_create_operation& )const {}
|
||||||
void operator()( const assert_operation& )const {}
|
void operator()( const assert_operation& )const {}
|
||||||
void operator()( const balance_claim_operation& )const {}
|
void operator()( const balance_claim_operation& )const {}
|
||||||
|
void operator()( const override_transfer_operation& )const {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue