This commit is contained in:
Daniel Larimer 2015-06-16 18:46:16 -04:00
commit 3bc325436f
20 changed files with 187 additions and 152 deletions

View file

@ -25,18 +25,19 @@ namespace graphene { namespace chain {
void_result account_create_evaluator::do_evaluate( const account_create_operation& op ) void_result account_create_evaluator::do_evaluate( const account_create_operation& op )
{ try { { try {
database& d = db(); database& d = db();
FC_ASSERT( d.find_object(op.voting_account) ); FC_ASSERT( d.find_object(op.options.voting_account) );
FC_ASSERT( is_relative(op.memo_key) || d.find_object(op.memo_key) ); FC_ASSERT( is_relative(op.options.memo_key) || d.find_object(op.options.memo_key) );
FC_ASSERT( fee_paying_account->is_lifetime_member() ); FC_ASSERT( fee_paying_account->is_lifetime_member() );
FC_ASSERT( op.referrer(d).is_member(d.head_block_time()) ); FC_ASSERT( op.referrer(d).is_member(d.head_block_time()) );
const auto& global_props = d.get_global_properties(); const auto& global_props = d.get_global_properties();
uint32_t max_vote_id = global_props.next_available_vote_id;
const auto& chain_params = global_props.parameters; const auto& chain_params = global_props.parameters;
FC_ASSERT( op.num_witness <= chain_params.maximum_witness_count );
FC_ASSERT( op.num_committee <= chain_params.maximum_committee_count );
FC_ASSERT( op.owner.auths.size() <= chain_params.maximum_authority_membership ); FC_ASSERT( op.owner.auths.size() <= chain_params.maximum_authority_membership );
FC_ASSERT( op.active.auths.size() <= chain_params.maximum_authority_membership ); FC_ASSERT( op.active.auths.size() <= chain_params.maximum_authority_membership );
check_relative_ids(op.owner);
check_relative_ids(op.active);
FC_ASSERT( d.find(key_id_type(get_relative_id(op.options.memo_key))) );
for( auto id : op.owner.auths ) for( auto id : op.owner.auths )
{ {
FC_ASSERT( is_relative(id.first) || d.find_object(id.first) ); FC_ASSERT( is_relative(id.first) || d.find_object(id.first) );
@ -45,18 +46,22 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio
{ {
FC_ASSERT( is_relative(id.first) || d.find_object(id.first) ); FC_ASSERT( is_relative(id.first) || d.find_object(id.first) );
} }
uint32_t max_vote_id = global_props.next_available_vote_id;
FC_ASSERT( op.options.num_witness <= chain_params.maximum_witness_count );
FC_ASSERT( op.options.num_committee <= chain_params.maximum_committee_count );
safe<uint32_t> counts[vote_id_type::VOTE_TYPE_COUNT]; safe<uint32_t> counts[vote_id_type::VOTE_TYPE_COUNT];
for( auto id : op.vote ) for( auto id : op.options.votes )
{ {
FC_ASSERT( id < max_vote_id ); FC_ASSERT( id < max_vote_id );
counts[id.type()]++; counts[id.type()]++;
} }
FC_ASSERT(counts[vote_id_type::witness] <= op.num_witness, FC_ASSERT(counts[vote_id_type::witness] <= op.options.num_witness,
"", "",
("count", counts[vote_id_type::witness])("num", op.num_witness)); ("count", counts[vote_id_type::witness])("num", op.options.num_witness));
FC_ASSERT(counts[vote_id_type::committee] <= op.num_committee, FC_ASSERT(counts[vote_id_type::committee] <= op.options.num_committee,
"", "",
("count", counts[vote_id_type::committee])("num", op.num_committee)); ("count", counts[vote_id_type::committee])("num", op.options.num_committee));
auto& acnt_indx = d.get_index_type<account_index>(); auto& acnt_indx = d.get_index_type<account_index>();
if( op.name.size() ) if( op.name.size() )
@ -65,17 +70,6 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio
FC_ASSERT( current_account_itr == acnt_indx.indices().get<by_name>().end() ); FC_ASSERT( current_account_itr == acnt_indx.indices().get<by_name>().end() );
} }
// TODO: this check can be removed after GRAPHENE_LEGACY_NAME_IMPORT_PERIOD
// legacy account check
if( d.get_dynamic_global_properties().head_block_number < GRAPHENE_LEGACY_NAME_IMPORT_PERIOD )
{
auto legacy_account_itr = acnt_indx.indices().get<by_name>().find( "bts-"+op.name );
if( legacy_account_itr != acnt_indx.indices().get<by_name>().end() )
{
FC_ASSERT( fee_paying_account->id == legacy_account_itr->id );
}
}
// verify child account authority // verify child account authority
auto pos = op.name.find( '/' ); auto pos = op.name.find( '/' );
if( pos != string::npos ) if( pos != string::npos )
@ -93,9 +87,6 @@ void_result account_create_evaluator::do_evaluate( const account_create_operatio
object_id_type account_create_evaluator::do_apply( const account_create_operation& o ) object_id_type account_create_evaluator::do_apply( const account_create_operation& o )
{ try { { try {
auto owner = resolve_relative_ids( o.owner );
auto active = resolve_relative_ids( o.active );
const auto& stats_obj = db().create<account_statistics_object>( [&]( account_statistics_object& ){ const auto& stats_obj = db().create<account_statistics_object>( [&]( account_statistics_object& ){
}); });
@ -110,14 +101,11 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
obj.referrer_rewards_percentage = o.referrer_percent; obj.referrer_rewards_percentage = o.referrer_percent;
obj.name = o.name; obj.name = o.name;
obj.owner = owner; obj.owner = resolve_relative_ids(o.owner);
obj.active = active; obj.active = resolve_relative_ids(o.active);
obj.statistics = stats_obj.id; obj.statistics = stats_obj.id;
obj.memo_key = get_relative_id(o.memo_key); obj.options = o.options;
obj.voting_account = o.voting_account; obj.options.memo_key = get_relative_id(obj.options.memo_key);
obj.votes = o.vote;
obj.num_witness = o.num_witness;
obj.num_committee = o.num_committee;
}); });
return new_acnt_object.id; return new_acnt_object.id;
@ -128,14 +116,12 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio
{ {
database& d = db(); database& d = db();
FC_ASSERT( !o.memo_key || is_relative(*o.memo_key) || db().find_object(*o.memo_key) );
const auto& chain_params = db().get_global_properties().parameters; const auto& chain_params = db().get_global_properties().parameters;
FC_ASSERT( o.num_witness <= chain_params.maximum_witness_count );
FC_ASSERT( o.num_committee <= chain_params.maximum_committee_count );
if( o.owner ) if( o.owner )
{ {
FC_ASSERT( o.owner->auths.size() <= chain_params.maximum_authority_membership ); FC_ASSERT( o.owner->auths.size() <= chain_params.maximum_authority_membership );
check_relative_ids(*o.owner);
for( auto id : o.owner->auths ) for( auto id : o.owner->auths )
{ {
FC_ASSERT( is_relative(id.first) || db().find<object>(id.first) ); FC_ASSERT( is_relative(id.first) || db().find<object>(id.first) );
@ -144,6 +130,7 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio
if( o.active ) if( o.active )
{ {
FC_ASSERT( o.active->auths.size() <= chain_params.maximum_authority_membership ); FC_ASSERT( o.active->auths.size() <= chain_params.maximum_authority_membership );
check_relative_ids(*o.active);
for( auto id : o.active->auths ) for( auto id : o.active->auths )
{ {
FC_ASSERT( is_relative(id.first) || db().find<object>(id.first) ); FC_ASSERT( is_relative(id.first) || db().find<object>(id.first) );
@ -152,10 +139,13 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio
acnt = &o.account(d); acnt = &o.account(d);
if( o.vote ) if( o.new_options )
{ {
FC_ASSERT( d.find(key_id_type(get_relative_id(o.new_options->memo_key))) );
FC_ASSERT( o.new_options->num_witness <= chain_params.maximum_witness_count );
FC_ASSERT( o.new_options->num_committee <= chain_params.maximum_committee_count );
uint32_t max_vote_id = d.get_global_properties().next_available_vote_id; uint32_t max_vote_id = d.get_global_properties().next_available_vote_id;
for( auto id : *o.vote ) for( auto id : o.new_options->votes )
{ {
FC_ASSERT( id < max_vote_id ); FC_ASSERT( id < max_vote_id );
} }
@ -165,15 +155,15 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio
} }
void_result account_update_evaluator::do_apply( const account_update_operation& o ) void_result account_update_evaluator::do_apply( const account_update_operation& o )
{ {
db().modify( *acnt, [&]( account_object& a ){ db().modify( *acnt, [&](account_object& a){
if( o.owner ) a.owner = *o.owner; if( o.owner ) a.owner = resolve_relative_ids(*o.owner);
if( o.active ) a.active = *o.active; if( o.active ) a.active = resolve_relative_ids(*o.active);
if( o.voting_account ) a.voting_account = *o.voting_account; if( o.new_options )
if( o.memo_key ) a.memo_key = *o.memo_key; {
if( o.vote ) a.votes = *o.vote; a.options = *o.new_options;
a.num_witness = o.num_witness; a.options.memo_key = get_relative_id(a.options.memo_key);
a.num_committee = o.num_committee; }
}); });
return void_result(); return void_result();
} }

View file

@ -131,4 +131,19 @@ void account_statistics_object::process_fees(const account_object& a, database&
} }
} }
void account_object::options_type::validate() const
{
auto needed_witnesses = num_witness;
auto needed_committee = num_committee;
for( vote_id_type id : votes )
if( id.type() == vote_id_type::witness && needed_witnesses )
--needed_witnesses;
else if ( id.type() == vote_id_type::committee && needed_committee )
--needed_committee;
FC_ASSERT( needed_witnesses == 0 && needed_committee == 0,
"May not specify fewer witnesses or committee members than the number voted for.");
}
} } // graphene::chain } } // graphene::chain

View file

@ -151,7 +151,7 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
n.owner.add_authority(genesis_key.get_id(), 1); n.owner.add_authority(genesis_key.get_id(), 1);
n.owner.weight_threshold = 1; n.owner.weight_threshold = 1;
n.active = n.owner; n.active = n.owner;
n.memo_key = genesis_key.id; n.options.memo_key = genesis_key.id;
n.statistics = genesis_statistics.id; n.statistics = genesis_statistics.id;
}); });
@ -262,7 +262,7 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
auto mangle_to_name = [](const fc::static_variant<public_key_type, address>& key) { auto mangle_to_name = [](const fc::static_variant<public_key_type, address>& key) {
string addr = string(key.which() == std::decay<decltype(key)>::type::tag<address>::value? key.get<address>() string addr = string(key.which() == std::decay<decltype(key)>::type::tag<address>::value? key.get<address>()
: key.get<public_key_type>()); : key.get<public_key_type>());
string result = "bts"; string result = "import";
string key_string = string(addr).substr(sizeof(GRAPHENE_ADDRESS_PREFIX)-1); string key_string = string(addr).substr(sizeof(GRAPHENE_ADDRESS_PREFIX)-1);
for( char c : key_string ) for( char c : key_string )
{ {
@ -295,7 +295,7 @@ void database::init_genesis(const genesis_allocation& initial_allocation)
cop.registrar = account_id_type(1); cop.registrar = account_id_type(1);
cop.active = account_authority; cop.active = account_authority;
cop.owner = account_authority; cop.owner = account_authority;
cop.memo_key = key_id; cop.options.memo_key = key_id;
trx.operations.push_back(cop); trx.operations.push_back(cop);
trx.validate(); trx.validate();
auto ptrx = apply_transaction(trx, ~0); auto ptrx = apply_transaction(trx, ~0);

View file

@ -307,15 +307,16 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
// Usually they're the same, but if the stake account has specified a voting_account, that account is the one // Usually they're the same, but if the stake account has specified a voting_account, that account is the one
// specifying the opinions. // specifying the opinions.
const account_object& opinion_account = const account_object& opinion_account =
(stake_account.voting_account == account_id_type())? stake_account (stake_account.options.voting_account ==
: d.get(stake_account.voting_account); account_id_type())? stake_account
: d.get(stake_account.options.voting_account);
const auto& stats = stake_account.statistics(d); const auto& stats = stake_account.statistics(d);
uint64_t voting_stake = stats.total_core_in_orders.value uint64_t voting_stake = stats.total_core_in_orders.value
+ (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0) + (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0)
+ d.get_balance(stake_account.get_id(), asset_id_type()).amount.value; + d.get_balance(stake_account.get_id(), asset_id_type()).amount.value;
for( vote_id_type id : opinion_account.votes ) for( vote_id_type id : opinion_account.options.votes )
{ {
uint32_t offset = id.instance(); uint32_t offset = id.instance();
// if they somehow managed to specify an illegal offset, ignore it. // if they somehow managed to specify an illegal offset, ignore it.
@ -323,9 +324,9 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
d._vote_tally_buffer[ offset ] += voting_stake; d._vote_tally_buffer[ offset ] += voting_stake;
} }
if( opinion_account.num_witness <= props.parameters.maximum_witness_count ) if( opinion_account.options.num_witness <= props.parameters.maximum_witness_count )
{ {
uint16_t offset = std::min(size_t(opinion_account.num_witness/2), uint16_t offset = std::min(size_t(opinion_account.options.num_witness/2),
d._witness_count_histogram_buffer.size() - 1); d._witness_count_histogram_buffer.size() - 1);
// votes for a number greater than maximum_witness_count // votes for a number greater than maximum_witness_count
// are turned into votes for maximum_witness_count. // are turned into votes for maximum_witness_count.
@ -335,9 +336,9 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
// parameter was lowered. // parameter was lowered.
d._witness_count_histogram_buffer[ offset ] += voting_stake; d._witness_count_histogram_buffer[ offset ] += voting_stake;
} }
if( opinion_account.num_committee <= props.parameters.maximum_committee_count ) if( opinion_account.options.num_committee <= props.parameters.maximum_committee_count )
{ {
uint16_t offset = std::min(size_t(opinion_account.num_committee/2), uint16_t offset = std::min(size_t(opinion_account.options.num_committee/2),
d._committee_count_histogram_buffer.size() - 1); d._committee_count_histogram_buffer.size() - 1);
// votes for a number greater than maximum_committee_count // votes for a number greater than maximum_committee_count
// are turned into votes for maximum_committee_count. // are turned into votes for maximum_committee_count.

View file

@ -115,7 +115,15 @@ namespace graphene { namespace chain {
return rel_id; return rel_id;
} }
authority generic_evaluator::resolve_relative_ids( const authority& a )const void generic_evaluator::check_relative_ids(const authority& a)const
{
for( const auto& item : a.auths )
{
auto id = get_relative_id( item.first );
FC_ASSERT( id.type() == key_object_type || id.type() == account_object_type );
}
}
authority generic_evaluator::resolve_relative_ids(const authority& a)const
{ {
authority result; authority result;
result.auths.reserve( a.auths.size() ); result.auths.reserve( a.auths.size() );

View file

@ -144,6 +144,7 @@ class database;
/// The account's name. This name must be unique among all account names on the graph. May not be empty. /// The account's name. This name must be unique among all account names on the graph. May not be empty.
string name; string name;
/** /**
* The owner authority represents absolute control over the account. Usually the keys in this authority will * The owner authority represents absolute control over the account. Usually the keys in this authority will
* be kept in cold storage, as they should not be needed very often and compromise of these keys constitutes * be kept in cold storage, as they should not be needed very often and compromise of these keys constitutes
@ -154,19 +155,30 @@ class database;
/// The owner authority contains the hot keys of the account. This authority has control over nearly all /// The owner authority contains the hot keys of the account. This authority has control over nearly all
/// operations the account may perform. /// operations the account may perform.
authority active; authority active;
/// 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.
key_id_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;
uint16_t num_witness = 0; /// These are the fields which can be updated by the active authority.
uint16_t num_committee = 0; struct options_type {
/// This is the list of vote IDs this account votes for. The weight of these votes is determined by this /// The memo key is the key this account will typically use to encrypt/sign transaction memos and other non-
/// account's balance of core asset. /// validated account activities. This field is here to prevent confusion if the active authority has zero or
flat_set<vote_id_type> votes; /// multiple keys in it.
object_id_type memo_key = key_id_type();
key_id_type get_memo_key()const { return 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<vote_id_type> votes;
void validate()const;
} options;
/// The reference implementation records the account's statistics in a separate object. This field contains the /// The reference implementation records the account's statistics in a separate object. This field contains the
/// ID of that object. /// ID of that object.
@ -293,8 +305,10 @@ FC_REFLECT_DERIVED( graphene::chain::account_object,
(graphene::db::annotated_object<graphene::chain::account_object>), (graphene::db::annotated_object<graphene::chain::account_object>),
(membership_expiration_date)(registrar)(referrer)(lifetime_referrer) (membership_expiration_date)(registrar)(referrer)(lifetime_referrer)
(network_fee_percentage)(lifetime_referrer_fee_percentage)(referrer_rewards_percentage) (network_fee_percentage)(lifetime_referrer_fee_percentage)(referrer_rewards_percentage)
(name)(owner)(active)(memo_key)(voting_account)(num_witness)(num_committee)(votes) (name)(owner)(active)(options)(statistics)(whitelisting_accounts)(blacklisting_accounts)
(statistics)(whitelisting_accounts)(blacklisting_accounts)(cashback_vb) ) (cashback_vb) )
FC_REFLECT(graphene::chain::account_object::options_type, (memo_key)(voting_account)(num_witness)(num_committee)(votes))
FC_REFLECT_DERIVED( graphene::chain::account_balance_object, FC_REFLECT_DERIVED( graphene::chain::account_balance_object,
(graphene::db::object), (graphene::db::object),

View file

@ -112,7 +112,6 @@
#define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 ) #define GRAPHENE_DEFAULT_WORKER_BUDGET_PER_DAY (GRAPHENE_BLOCKCHAIN_PRECISION * int64_t(500) * 1000 )
#define GRAPHENE_MAX_INTEREST_APR uint16_t( 10000 ) #define GRAPHENE_MAX_INTEREST_APR uint16_t( 10000 )
#define GRAPHENE_LEGACY_NAME_IMPORT_PERIOD 3000000 /** 3 million blocks */
/** /**
* Reserved Account IDs with special meaning * Reserved Account IDs with special meaning

View file

@ -102,6 +102,7 @@ namespace graphene { namespace chain {
object_id_type get_relative_id( object_id_type rel_id )const; object_id_type get_relative_id( object_id_type rel_id )const;
void check_relative_ids(const authority& a)const;
authority resolve_relative_ids( const authority& a )const; authority resolve_relative_ids( const authority& a )const;
asset fee_from_account; asset fee_from_account;

View file

@ -27,6 +27,7 @@
#include <graphene/chain/authority.hpp> #include <graphene/chain/authority.hpp>
#include <graphene/chain/asset_object.hpp> #include <graphene/chain/asset_object.hpp>
#include <graphene/chain/worker_object.hpp> #include <graphene/chain/worker_object.hpp>
#include <graphene/chain/account_object.hpp>
#include <fc/static_variant.hpp> #include <fc/static_variant.hpp>
#include <fc/uint128.hpp> #include <fc/uint128.hpp>
@ -137,12 +138,8 @@ namespace graphene { namespace chain {
string name; string name;
authority owner; authority owner;
authority active; authority active;
account_id_type voting_account;
object_id_type memo_key = key_id_type();
uint16_t num_witness = 0; account_object::options_type options;
uint16_t num_committee = 0;
flat_set<vote_id_type> vote;
account_id_type fee_payer()const { return registrar; } account_id_type fee_payer()const { return registrar; }
void get_required_auth(flat_set<account_id_type>& active_auth_set , flat_set<account_id_type>&)const; void get_required_auth(flat_set<account_id_type>& active_auth_set , flat_set<account_id_type>&)const;
@ -203,15 +200,17 @@ namespace graphene { namespace chain {
*/ */
struct account_update_operation struct account_update_operation
{ {
asset fee; asset fee;
account_id_type account; /// The account to update
optional<authority> owner; account_id_type account;
optional<authority> active;
optional<account_id_type> voting_account; /// New owner authority. If set, this operation requires owner authority to execute.
optional<object_id_type> memo_key; optional<authority> owner;
optional<flat_set<vote_id_type>> vote; /// New active authority. If set, this operation requires owner authority to execute.
uint16_t num_witness = 0; optional<authority> active;
uint16_t num_committee = 0;
/// New account options
optional<account_object::options_type> new_options;
account_id_type fee_payer()const { return account; } account_id_type fee_payer()const { return account; }
void get_required_auth(flat_set<account_id_type>& active_auth_set , flat_set<account_id_type>& owner_auth_set)const; void get_required_auth(flat_set<account_id_type>& active_auth_set , flat_set<account_id_type>& owner_auth_set)const;
@ -1566,13 +1565,11 @@ FC_REFLECT( graphene::chain::key_create_operation,
FC_REFLECT( graphene::chain::account_create_operation, FC_REFLECT( graphene::chain::account_create_operation,
(fee)(registrar) (fee)(registrar)
(referrer)(referrer_percent) (referrer)(referrer_percent)
(name) (name)(owner)(active)(options)
(owner)(active)(voting_account)(memo_key)
(num_witness)(num_committee)(vote)
) )
FC_REFLECT( graphene::chain::account_update_operation, FC_REFLECT( graphene::chain::account_update_operation,
(fee)(account)(owner)(active)(voting_account)(memo_key)(num_witness)(num_committee)(vote) (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_upgrade_operation, (fee)(account_to_upgrade)(upgrade_to_lifetime_member) )

View file

@ -149,9 +149,11 @@ void account_update_operation::validate()const
{ {
FC_ASSERT( fee.amount >= 0 ); FC_ASSERT( fee.amount >= 0 );
FC_ASSERT( account != account_id_type() ); FC_ASSERT( account != account_id_type() );
FC_ASSERT( owner || active || voting_account || memo_key || vote ); FC_ASSERT( owner || active || new_options );
}
if( new_options )
new_options->validate();
}
share_type asset_create_operation::calculate_fee( const fee_schedule_type& schedule )const share_type asset_create_operation::calculate_fee( const fee_schedule_type& schedule )const
{ {
@ -209,10 +211,7 @@ void account_create_operation::validate()const
FC_ASSERT( owner.weight_threshold == 1 ); FC_ASSERT( owner.weight_threshold == 1 );
FC_ASSERT( owner.auths.size() == 1 ); FC_ASSERT( owner.auths.size() == 1 );
} }
FC_ASSERT( num_witness + num_committee >= num_witness ); // no overflow options.validate();
FC_ASSERT( num_witness + num_committee <= vote.size() );
// FC_ASSERT( (num_witness == 0) || (num_witness&0x01) == 0, "must be odd number" );
// FC_ASSERT( (num_committee == 0) || (num_committee&0x01) == 0, "must be odd number" );
} }

View file

@ -448,7 +448,7 @@ flat_set<key_id_type> account_history_plugin_impl::get_keys_for_account( const a
flat_set<key_id_type> key_id_set; flat_set<key_id_type> key_id_set;
key_id_set.reserve(owner_auths.size() + active_auths.size() + 2); key_id_set.reserve(owner_auths.size() + active_auths.size() + 2);
key_id_set.insert(acct.memo_key); key_id_set.insert(acct.options.memo_key);
// we don't use get_keys() here to avoid an intermediate copy operation // we don't use get_keys() here to avoid an intermediate copy operation
for( const pair<object_id_type, weight_type>& item : active_auths ) for( const pair<object_id_type, weight_type>& item : active_auths )

View file

@ -5,10 +5,10 @@
#define GRAPHENE_GIT_REVISION_UNIX_TIMESTAMP @GRAPHENE_GIT_REVISION_UNIX_TIMESTAMP@ #define GRAPHENE_GIT_REVISION_UNIX_TIMESTAMP @GRAPHENE_GIT_REVISION_UNIX_TIMESTAMP@
#define GRAPHENE_GIT_REVISION_DESCRIPTION "@GRAPHENE_GIT_REVISION_DESCRIPTION@" #define GRAPHENE_GIT_REVISION_DESCRIPTION "@GRAPHENE_GIT_REVISION_DESCRIPTION@"
namespace bts { namespace utilities { namespace graphene { namespace utilities {
const char* const git_revision_sha = GRAPHENE_GIT_REVISION_SHA; const char* const git_revision_sha = GRAPHENE_GIT_REVISION_SHA;
const uint32_t git_revision_unix_timestamp = GRAPHENE_GIT_REVISION_UNIX_TIMESTAMP; const uint32_t git_revision_unix_timestamp = GRAPHENE_GIT_REVISION_UNIX_TIMESTAMP;
const char* const git_revision_description = GRAPHENE_GIT_REVISION_DESCRIPTION; const char* const git_revision_description = GRAPHENE_GIT_REVISION_DESCRIPTION;
} } // end namespace bts::utilities } } // end namespace graphene::utilities

View file

@ -724,7 +724,7 @@ public:
account_create_op.name = name; account_create_op.name = name;
account_create_op.owner = authority(1, owner_rkid, 1); account_create_op.owner = authority(1, owner_rkid, 1);
account_create_op.active = authority(1, active_rkid, 1); account_create_op.active = authority(1, active_rkid, 1);
account_create_op.memo_key = active_rkid; account_create_op.options.memo_key = active_rkid;
signed_transaction tx; signed_transaction tx;
@ -820,7 +820,7 @@ public:
account_create_op.name = account_name; account_create_op.name = account_name;
account_create_op.owner = authority(1, owner_rkid, 1); account_create_op.owner = authority(1, owner_rkid, 1);
account_create_op.active = authority(1, active_rkid, 1); account_create_op.active = authority(1, active_rkid, 1);
account_create_op.memo_key = active_rkid; account_create_op.options.memo_key = active_rkid;
// current_fee_schedule() // current_fee_schedule()
// find_account(pay_from_account) // find_account(pay_from_account)
@ -1087,10 +1087,10 @@ public:
if( memo.size() ) if( memo.size() )
{ {
xfer_op.memo = memo_data(); xfer_op.memo = memo_data();
xfer_op.memo->from = from_account.memo_key; xfer_op.memo->from = from_account.options.memo_key;
xfer_op.memo->to = to_account.memo_key; xfer_op.memo->to = to_account.options.memo_key;
xfer_op.memo->set_message(get_private_key(from_account.memo_key), xfer_op.memo->set_message(get_private_key(from_account.options.memo_key),
get_public_key(to_account.memo_key), memo); get_public_key(to_account.options.memo_key), memo);
} }
signed_transaction tx; signed_transaction tx;
@ -1117,10 +1117,10 @@ public:
if( memo.size() ) if( memo.size() )
{ {
issue_op.memo = memo_data(); issue_op.memo = memo_data();
issue_op.memo->from = issuer.memo_key; issue_op.memo->from = issuer.options.memo_key;
issue_op.memo->to = to.memo_key; issue_op.memo->to = to.options.memo_key;
issue_op.memo->set_message(get_private_key(issuer.memo_key), issue_op.memo->set_message(get_private_key(issuer.options.memo_key),
get_public_key(to.memo_key), memo); get_public_key(to.options.memo_key), memo);
} }
signed_transaction tx; signed_transaction tx;
@ -1200,7 +1200,7 @@ void dbg_make_mia(string creator, string symbol)
void flood_network(string prefix, uint32_t number_of_transactions) void flood_network(string prefix, uint32_t number_of_transactions)
{ {
const account_object& master = *_wallet.my_accounts.get<by_name>().lower_bound("bts"); const account_object& master = *_wallet.my_accounts.get<by_name>().lower_bound("import");
int number_of_accounts = number_of_transactions / 3; int number_of_accounts = number_of_transactions / 3;
number_of_transactions -= number_of_accounts; number_of_transactions -= number_of_accounts;
auto key = derive_private_key("floodshill", 0); auto key = derive_private_key("floodshill", 0);

View file

@ -193,7 +193,7 @@ void database_fixture::verify_account_history_plugin_index( )const
if( auth.first.type() == key_object_type ) if( auth.first.type() == key_object_type )
acct_addresses.insert( key_id_type( auth.first )(db).key_address() ); acct_addresses.insert( key_id_type( auth.first )(db).key_address() );
} }
acct_addresses.insert( acct.memo_key(db).key_address() ); acct_addresses.insert( acct.options.get_memo_key()(db).key_address() );
for( const address& addr : acct_addresses ) for( const address& addr : acct_addresses )
tuples_from_db.emplace_back( account_id, addr ); tuples_from_db.emplace_back( account_id, addr );
} }
@ -294,7 +294,7 @@ account_create_operation database_fixture::make_account(
create_account.name = name; create_account.name = name;
create_account.owner = authority(123, key, 123); create_account.owner = authority(123, key, 123);
create_account.active = authority(321, key, 321); create_account.active = authority(321, key, 321);
create_account.memo_key = key; create_account.options.memo_key = key;
auto& active_delegates = db.get_global_properties().active_delegates; auto& active_delegates = db.get_global_properties().active_delegates;
if( active_delegates.size() > 0 ) if( active_delegates.size() > 0 )
@ -305,9 +305,9 @@ account_create_operation database_fixture::make_account(
votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id); votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id);
votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id); votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id);
votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id); votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id);
create_account.vote = flat_set<vote_id_type>(votes.begin(), votes.end()); create_account.options.votes = flat_set<vote_id_type>(votes.begin(), votes.end());
} }
create_account.num_committee = create_account.vote.size(); create_account.options.num_committee = create_account.options.votes.size();
create_account.fee = create_account.calculate_fee(db.current_fee_schedule()); create_account.fee = create_account.calculate_fee(db.current_fee_schedule());
return create_account; return create_account;
@ -332,7 +332,7 @@ account_create_operation database_fixture::make_account(
create_account.name = name; create_account.name = name;
create_account.owner = authority(123, key, 123); create_account.owner = authority(123, key, 123);
create_account.active = authority(321, key, 321); create_account.active = authority(321, key, 321);
create_account.memo_key = key; create_account.options.memo_key = key;
const vector<delegate_id_type>& active_delegates = db.get_global_properties().active_delegates; const vector<delegate_id_type>& active_delegates = db.get_global_properties().active_delegates;
if( active_delegates.size() > 0 ) if( active_delegates.size() > 0 )
@ -343,9 +343,9 @@ account_create_operation database_fixture::make_account(
votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id); votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id);
votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id); votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id);
votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id); votes.insert(active_delegates[rand() % active_delegates.size()](db).vote_id);
create_account.vote = flat_set<vote_id_type>(votes.begin(), votes.end()); create_account.options.votes = flat_set<vote_id_type>(votes.begin(), votes.end());
} }
create_account.num_committee = create_account.vote.size(); create_account.options.num_committee = create_account.options.votes.size();
create_account.fee = create_account.calculate_fee(db.current_fee_schedule()); create_account.fee = create_account.calculate_fee(db.current_fee_schedule());
return create_account; return create_account;
@ -499,7 +499,7 @@ const account_object& database_fixture::create_account(
account_create_op.name = name; account_create_op.name = name;
account_create_op.owner = authority(1234, key_rkid, 1234); account_create_op.owner = authority(1234, key_rkid, 1234);
account_create_op.active = authority(5678, key_rkid, 5678); account_create_op.active = authority(5678, key_rkid, 5678);
account_create_op.memo_key = key_rkid; account_create_op.options.memo_key = key_rkid;
trx.operations.push_back( account_create_op ); trx.operations.push_back( account_create_op );
trx.validate(); trx.validate();

View file

@ -166,7 +166,7 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture )
// size() < num_active_keys is possible when some keys are duplicates // size() < num_active_keys is possible when some keys are duplicates
create_op.active.weight_threshold = create_op.active.auths.size(); create_op.active.weight_threshold = create_op.active.auths.size();
create_op.memo_key = key_ids[ *(it++) ] ; create_op.options.memo_key = key_ids[ *(it++) ] ;
create_op.registrar = sam_account_object.id; create_op.registrar = sam_account_object.id;
trx.operations.push_back( create_op ); trx.operations.push_back( create_op );
// trx.sign( sam_key ); // trx.sign( sam_key );
@ -191,6 +191,7 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture )
update_op.account = alice_account_id; update_op.account = alice_account_id;
update_op.owner = authority(); update_op.owner = authority();
update_op.active = authority(); update_op.active = authority();
update_op.new_options = create_op.options;
for( int owner_index=0; owner_index<num_owner_keys; owner_index++ ) for( int owner_index=0; owner_index<num_owner_keys; owner_index++ )
update_op.owner->auths[ key_ids[ *(it++) ] ] = 1; update_op.owner->auths[ key_ids[ *(it++) ] ] = 1;
@ -200,7 +201,8 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture )
update_op.active->auths[ key_ids[ *(it++) ] ] = 1; update_op.active->auths[ key_ids[ *(it++) ] ] = 1;
// size() < num_active_keys is possible when some keys are duplicates // size() < num_active_keys is possible when some keys are duplicates
update_op.active->weight_threshold = update_op.active->auths.size(); update_op.active->weight_threshold = update_op.active->auths.size();
update_op.memo_key = key_ids[ *(it++) ] ; FC_ASSERT( update_op.new_options.valid() );
update_op.new_options->memo_key = key_ids[ *(it++) ] ;
trx.operations.push_back( update_op ); trx.operations.push_back( update_op );
for( int i=0; i<int(create_op.owner.weight_threshold); i++) for( int i=0; i<int(create_op.owner.weight_threshold); i++)

View file

@ -474,7 +474,8 @@ BOOST_FIXTURE_TEST_CASE( fired_delegates, database_fixture )
//Oh noes! Nathan votes for a whole new slate of delegates! //Oh noes! Nathan votes for a whole new slate of delegates!
account_update_operation op; account_update_operation op;
op.account = nathan->id; op.account = nathan->id;
op.vote = delegates; op.new_options = nathan->options;
op.new_options->votes = delegates;
trx.operations.push_back(op); trx.operations.push_back(op);
trx.set_expiration(db.head_block_time() + GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION); trx.set_expiration(db.head_block_time() + GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION);
db.push_transaction(trx, ~0); db.push_transaction(trx, ~0);
@ -874,7 +875,7 @@ BOOST_FIXTURE_TEST_CASE( max_authority_membership, database_fixture )
anon_create_op.owner = owner_auth; anon_create_op.owner = owner_auth;
anon_create_op.active = active_auth; anon_create_op.active = active_auth;
anon_create_op.registrar = sam_account_object.id; anon_create_op.registrar = sam_account_object.id;
anon_create_op.memo_key = sam_account_object.memo_key; anon_create_op.options.memo_key = sam_account_object.options.memo_key;
anon_create_op.name = generate_anon_acct_name(); anon_create_op.name = generate_anon_acct_name();
tx.operations.push_back( anon_create_op ); tx.operations.push_back( anon_create_op );
@ -913,10 +914,10 @@ BOOST_FIXTURE_TEST_CASE( bogus_signature, database_fixture )
account_object bob_account_object = create_account( "bob", bob_key ); account_object bob_account_object = create_account( "bob", bob_key );
account_object charlie_account_object = create_account( "charlie", charlie_key ); account_object charlie_account_object = create_account( "charlie", charlie_key );
key_id_type alice_key_id = alice_account_object.memo_key; key_id_type alice_key_id = alice_account_object.options.memo_key;
// unneeded, comment it out to silence compiler warning // unneeded, comment it out to silence compiler warning
//key_id_type bob_key_id = bob_account_object.memo_key; //key_id_type bob_key_id = bob_account_object.memo_key;
key_id_type charlie_key_id = charlie_account_object.memo_key; key_id_type charlie_key_id = charlie_account_object.options.memo_key;
uint32_t skip = database::skip_transaction_dupe_check; uint32_t skip = database::skip_transaction_dupe_check;
@ -994,9 +995,10 @@ BOOST_FIXTURE_TEST_CASE( voting_account, database_fixture )
{ {
account_update_operation op; account_update_operation op;
op.account = nathan_id; op.account = nathan_id;
op.voting_account = vikram_id; op.new_options = nathan_id(db).options;
op.vote = flat_set<vote_id_type>{nathan_delegate(db).vote_id}; op.new_options->voting_account = vikram_id;
op.num_committee = 1; op.new_options->votes = flat_set<vote_id_type>{nathan_delegate(db).vote_id};
op.new_options->num_committee = 1;
trx.operations.push_back(op); trx.operations.push_back(op);
trx.sign(nathan_key_id, nathan_private_key); trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx); db.push_transaction(trx);
@ -1005,11 +1007,16 @@ BOOST_FIXTURE_TEST_CASE( voting_account, database_fixture )
{ {
account_update_operation op; account_update_operation op;
op.account = vikram_id; op.account = vikram_id;
op.vote = vikram_id(db).votes; op.new_options = vikram_id(db).options;
op.vote->insert(vikram_delegate(db).vote_id); op.new_options->votes.insert(vikram_delegate(db).vote_id);
op.num_committee = 11; op.new_options->num_committee = 11;
trx.operations.push_back(op); trx.operations.push_back(op);
trx.sign(vikram_key_id, vikram_private_key); trx.sign(vikram_key_id, vikram_private_key);
// Fails because num_committee is larger than the cardinality of committee members being voted for
BOOST_CHECK_THROW(db.push_transaction(trx), fc::exception);
op.new_options->num_committee = 3;
trx.operations = {op};
trx.sign(vikram_key_id, vikram_private_key);
db.push_transaction(trx); db.push_transaction(trx);
trx.clear(); trx.clear();
} }

View file

@ -429,8 +429,8 @@ BOOST_FIXTURE_TEST_CASE( maintenance_interval, database_fixture )
{ {
account_update_operation op; account_update_operation op;
op.account = nathan.id; op.account = nathan.id;
op.vote = nathan.votes; op.new_options = nathan.options;
op.vote->insert(nathans_delegate.vote_id); op.new_options->votes.insert(nathans_delegate.vote_id);
trx.operations.push_back(op); trx.operations.push_back(op);
db.push_transaction(trx, ~0); db.push_transaction(trx, ~0);
trx.operations.clear(); trx.operations.clear();

View file

@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE( cashback_test )
op.referrer = referrer_name ## _id; \ op.referrer = referrer_name ## _id; \
op.referrer_percent = referrer_rate*GRAPHENE_1_PERCENT; \ op.referrer_percent = referrer_rate*GRAPHENE_1_PERCENT; \
op.name = BOOST_PP_STRINGIZE(actor_name); \ op.name = BOOST_PP_STRINGIZE(actor_name); \
op.memo_key = actor_name ## _key_id; \ op.options.memo_key = actor_name ## _key_id; \
op.active = authority(1, actor_name ## _key_id, 1); \ op.active = authority(1, actor_name ## _key_id, 1); \
op.owner = op.active; \ op.owner = op.active; \
op.fee = op.calculate_fee(fees); \ op.fee = op.calculate_fee(fees); \

View file

@ -57,8 +57,8 @@ BOOST_AUTO_TEST_CASE( create_account_test )
REQUIRE_THROW_WITH_VALUE(op, name, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); REQUIRE_THROW_WITH_VALUE(op, name, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
REQUIRE_THROW_WITH_VALUE(op, name, "aaaa."); REQUIRE_THROW_WITH_VALUE(op, name, "aaaa.");
REQUIRE_THROW_WITH_VALUE(op, name, ".aaaa"); REQUIRE_THROW_WITH_VALUE(op, name, ".aaaa");
REQUIRE_THROW_WITH_VALUE(op, voting_account, account_id_type(999999999)); REQUIRE_THROW_WITH_VALUE(op, options.voting_account, account_id_type(999999999));
REQUIRE_THROW_WITH_VALUE(op, memo_key, key_id_type(999999999)); REQUIRE_THROW_WITH_VALUE(op, options.memo_key, key_id_type(999999999));
auto auth_bak = op.owner; auto auth_bak = op.owner;
op.owner.add_authority(account_id_type(9999999999), 10); op.owner.add_authority(account_id_type(9999999999), 10);
@ -85,8 +85,8 @@ BOOST_AUTO_TEST_CASE( create_account_test )
BOOST_CHECK(nathan_account.owner.auths.at(genesis_key) == 123); BOOST_CHECK(nathan_account.owner.auths.at(genesis_key) == 123);
BOOST_REQUIRE(nathan_account.active.auths.size() == 1); BOOST_REQUIRE(nathan_account.active.auths.size() == 1);
BOOST_CHECK(nathan_account.active.auths.at(genesis_key) == 321); BOOST_CHECK(nathan_account.active.auths.at(genesis_key) == 321);
BOOST_CHECK(nathan_account.voting_account == account_id_type()); BOOST_CHECK(nathan_account.options.voting_account == account_id_type());
BOOST_CHECK(nathan_account.memo_key == genesis_key); BOOST_CHECK(nathan_account.options.memo_key == genesis_key);
const account_statistics_object& statistics = nathan_account.statistics(db); const account_statistics_object& statistics = nathan_account.statistics(db);
BOOST_CHECK(statistics.id.space() == implementation_ids); BOOST_CHECK(statistics.id.space() == implementation_ids);
@ -159,13 +159,13 @@ BOOST_AUTO_TEST_CASE( update_account )
op.account = nathan.id; op.account = nathan.id;
op.owner = authority(2, key_id, 1, key_id_type(), 1); op.owner = authority(2, key_id, 1, key_id_type(), 1);
op.active = authority(2, key_id, 1, key_id_type(), 1); op.active = authority(2, key_id, 1, key_id_type(), 1);
//op.voting_account = key_id; op.new_options = nathan.options;
op.vote = flat_set<vote_id_type>({active_delegates[0](db).vote_id, active_delegates[5](db).vote_id}); op.new_options->votes = flat_set<vote_id_type>({active_delegates[0](db).vote_id, active_delegates[5](db).vote_id});
op.new_options->num_committee = 2;
trx.operations.back() = op; trx.operations.back() = op;
db.push_transaction(trx, ~0); db.push_transaction(trx, ~0);
//BOOST_CHECK(nathan.voting_key == key_id); BOOST_CHECK(nathan.options.memo_key == key_id_type());
BOOST_CHECK(nathan.memo_key == key_id_type());
BOOST_CHECK(nathan.active.weight_threshold == 2); BOOST_CHECK(nathan.active.weight_threshold == 2);
BOOST_CHECK(nathan.active.auths.size() == 2); BOOST_CHECK(nathan.active.auths.size() == 2);
BOOST_CHECK(nathan.active.auths.at(key_id) == 1); BOOST_CHECK(nathan.active.auths.at(key_id) == 1);
@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE( update_account )
BOOST_CHECK(nathan.owner.auths.size() == 2); BOOST_CHECK(nathan.owner.auths.size() == 2);
BOOST_CHECK(nathan.owner.auths.at(key_id) == 1); BOOST_CHECK(nathan.owner.auths.at(key_id) == 1);
BOOST_CHECK(nathan.owner.auths.at(key_id_type()) == 1); BOOST_CHECK(nathan.owner.auths.at(key_id_type()) == 1);
BOOST_CHECK(nathan.votes.size() == 2); BOOST_CHECK(nathan.options.votes.size() == 2);
/** these votes are no longer tallied in real time /** these votes are no longer tallied in real time
BOOST_CHECK(active_delegates[0](db).vote(db).total_votes == 30000); BOOST_CHECK(active_delegates[0](db).vote(db).total_votes == 30000);

View file

@ -399,10 +399,12 @@ BOOST_AUTO_TEST_CASE( witness_create )
{ {
account_update_operation op; account_update_operation op;
op.account = nathan_id; op.account = nathan_id;
op.vote = nathan_id(db).votes; op.new_options = nathan_id(db).options;
op.vote->insert(nathan_witness_id(db).vote_id); op.new_options->votes.insert(nathan_witness_id(db).vote_id);
op.num_witness = std::count_if(op.vote->begin(), op.vote->end(), [](vote_id_type id) { return id.type() == vote_id_type::witness; }); op.new_options->num_witness = std::count_if(op.new_options->votes.begin(), op.new_options->votes.end(),
op.num_committee = std::count_if(op.vote->begin(), op.vote->end(), [](vote_id_type id) { return id.type() == vote_id_type::committee; }); [](vote_id_type id) { return id.type() == vote_id_type::witness; });
op.new_options->num_committee = std::count_if(op.new_options->votes.begin(), op.new_options->votes.end(),
[](vote_id_type id) { return id.type() == vote_id_type::committee; });
trx.operations.push_back(op); trx.operations.push_back(op);
trx.sign(nathan_key_id, nathan_private_key); trx.sign(nathan_key_id, nathan_private_key);
db.push_transaction(trx); db.push_transaction(trx);
@ -540,8 +542,8 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
{ {
account_update_operation op; account_update_operation op;
op.account = nathan_id; op.account = nathan_id;
op.vote = nathan_id(db).votes; op.new_options = nathan_id(db).options;
op.vote->insert(worker_id_type()(db).vote_for); op.new_options->votes.insert(worker_id_type()(db).vote_for);
trx.operations.push_back(op); trx.operations.push_back(op);
db.push_transaction(trx, ~0); db.push_transaction(trx, ~0);
trx.clear(); trx.clear();
@ -580,8 +582,8 @@ BOOST_AUTO_TEST_CASE( worker_pay_test )
{ {
account_update_operation op; account_update_operation op;
op.account = nathan_id; op.account = nathan_id;
op.vote = nathan_id(db).votes; op.new_options = nathan_id(db).options;
op.vote->erase(worker_id_type()(db).vote_for); op.new_options->votes.erase(worker_id_type()(db).vote_for);
trx.operations.push_back(op); trx.operations.push_back(op);
db.push_transaction(trx, ~0); db.push_transaction(trx, ~0);
trx.clear(); trx.clear();
@ -653,8 +655,8 @@ BOOST_AUTO_TEST_CASE( refund_worker_test )
{ {
account_update_operation op; account_update_operation op;
op.account = nathan_id; op.account = nathan_id;
op.vote = nathan_id(db).votes; op.new_options = nathan_id(db).options;
op.vote->insert(worker_id_type()(db).vote_for); op.new_options->votes.insert(worker_id_type()(db).vote_for);
trx.operations.push_back(op); trx.operations.push_back(op);
db.push_transaction(trx, ~0); db.push_transaction(trx, ~0);
trx.clear(); trx.clear();