void fire_delegate_operation::evaluate( transaction_evaluation_state& eval_state ) { try { auto delegate_record = eval_state._current_state->get_account_record( this->delegate_id ); if( !delegate_record ) FC_CAPTURE_AND_THROW( unknown_account_id, (delegate_id) ); if( !delegate_record->is_delegate() ) FC_CAPTURE_AND_THROW( not_a_delegate, (delegate_record) ); switch( (fire_delegate_operation::reason_type)this->reason ) { case fire_delegate_operation::multiple_blocks_signed: { auto proof = fc::raw::unpack<multiple_block_proof>( this->data ); FC_ASSERT( proof.first.id() != proof.second.id() ); FC_ASSERT( proof.first.timestamp == proof.second.timestamp ) FC_ASSERT( proof.first.signee() == proof.second.signee() ) FC_ASSERT( proof.first.validate_signee( delegate_record->active_key() ) ); // then fire the delegate // this maintains the invariant of total votes == total shares delegate_record->adjust_votes_against( delegate_record->votes_for() ); delegate_record->adjust_votes_for( -delegate_record->votes_for() ); eval_state._current_state->store_account_record( *delegate_record ); break; } case fire_delegate_operation::invalid_testimony: { auto testimony = fc::raw::unpack<signed_delegate_testimony>( this->data ); bool is_delegates_key = false; auto signee = testimony.signee(); for( auto key : delegate_record->active_key_history ) { if( signee == key.second ) { is_delegates_key = true; break; } } if( !is_delegates_key ) FC_CAPTURE_AND_THROW( not_a_delegate_signature, (signee)(delegate_record) ); auto trx_loc = eval_state._current_state->get_transaction( testimony.transaction_id ); // delegate said it was valid, but it is invalid if( !trx_loc && testimony.valid ) { delegate_record->adjust_votes_against( delegate_record->votes_for() ); delegate_record->adjust_votes_for( -delegate_record->votes_for() ); eval_state._current_state->store_account_record( *delegate_record ); } else { FC_CAPTURE_AND_THROW( invalid_fire_operation ); } break; } } } FC_CAPTURE_AND_RETHROW( (*this) ) }
void transaction_evaluation_state::update_delegate_votes() { auto asset_rec = _current_state->get_asset_record( BASE_ASSET_ID ); auto max_votes = 2 * (asset_rec->current_share_supply / BTS_BLOCKCHAIN_NUM_DELEGATES); for( auto del_vote : net_delegate_votes ) { auto del_rec = _current_state->get_name_record( del_vote.first ); FC_ASSERT( !!del_rec ); del_rec->adjust_votes_for( del_vote.second.votes_for ); del_rec->adjust_votes_against( del_vote.second.votes_against ); if( del_rec->votes_for() > max_votes || del_rec->votes_against() > max_votes ) fail( BTS_DELEGATE_MAX_VOTE_LIMIT, fc::variant() ); _current_state->store_name_record( *del_rec ); } }