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::evaluate_deposit( const deposit_operation& op ) { try { auto deposit_balance_id = op.balance_id(); auto delegate_record = _current_state->get_name_record( op.condition.delegate_id ); if( !delegate_record ) fail( BTS_INVALID_NAME_ID, fc::variant(op) ); if( !delegate_record->is_delegate() ) fail( BTS_INVALID_DELEGATE_ID, fc::variant(op) ); auto cur_record = _current_state->get_balance_record( deposit_balance_id ); if( !cur_record ) { cur_record = balance_record( op.condition ); } cur_record->last_update = _current_state->now(); cur_record->balance += op.amount; sub_balance( deposit_balance_id, asset(op.amount, cur_record->condition.asset_id) ); if( cur_record->condition.asset_id == 0 ) add_vote( cur_record->condition.delegate_id, op.amount ); _current_state->store_balance_record( *cur_record ); } FC_RETHROW_EXCEPTIONS( warn, "", ("op",op) ) }
string pretty_block_list( const vector<block_record>& block_records, cptr client ) { if( block_records.empty() ) return "No blocks found.\n"; FC_ASSERT( client != nullptr ); std::stringstream out; out << std::left; out << std::setw( 8 ) << "HEIGHT"; out << std::setw( 20 ) << "TIMESTAMP"; out << std::setw( 32 ) << "SIGNING DELEGATE"; out << std::setw( 8 ) << "# TXS"; out << std::setw( 8 ) << "SIZE"; out << std::setw( 16 ) << "TOTAL FEES"; out << std::setw( 8 ) << "LATENCY"; out << std::setw( 15 ) << "PROCESSING TIME"; out << "\n"; out << pretty_line( 115 ); out << "\n"; auto last_block_timestamp = block_records.front().timestamp; for( const auto& block_record : block_records ) { /* Print any missed slots */ const bool descending = last_block_timestamp > block_record.timestamp; while( last_block_timestamp != block_record.timestamp ) { if( descending ) last_block_timestamp -= BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC; else last_block_timestamp += BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC; if( last_block_timestamp == block_record.timestamp ) break; out << std::setw( 8 ) << "MISSED"; out << std::setw( 20 ) << pretty_timestamp( last_block_timestamp ); const auto slot_record = client->get_chain()->get_slot_record( last_block_timestamp ); FC_ASSERT( slot_record.valid() ); const auto delegate_record = client->get_chain()->get_account_record( slot_record->block_producer_id ); FC_ASSERT( delegate_record.valid() && delegate_record->is_delegate() ); out << std::setw( 32 ) << pretty_shorten( delegate_record->name, 31 ); out << std::setw( 8 ) << "N/A"; out << std::setw( 8 ) << "N/A"; out << std::setw( 16 ) << "N/A"; out << std::setw( 8 ) << "N/A"; out << std::setw( 15 ) << "N/A"; out << '\n'; } /* Print produced block */ out << std::setw( 8 ) << block_record.block_num; out << std::setw( 20 ) << pretty_timestamp( block_record.timestamp ); const auto& delegate_name = client->blockchain_get_block_signee( block_record.block_num ); out << std::setw( 32 ); if( FILTER_OUTPUT_FOR_TESTS ) out << "[redacted]"; else out << pretty_shorten( delegate_name, 31 ); out << std::setw( 8 ) << block_record.user_transaction_ids.size(); out << std::setw( 8 ) << block_record.block_size; out << std::setw( 16 ) << client->get_chain()->to_pretty_asset( asset( block_record.total_fees ) ); if( FILTER_OUTPUT_FOR_TESTS ) { out << std::setw( 8 ) << "[redacted]"; out << std::setw( 15 ) << "[redacted]"; } else { out << std::setw( 8 ) << block_record.latency.to_seconds(); out << std::setw( 15 ) << block_record.processing_time.count() / double( 1000000 ); } out << '\n'; } return out.str(); }
share_type account_record::delegate_pay_rate()const { if( is_delegate() ) return delegate_info->pay_rate; return -1; }
void account_record::adjust_votes_for( share_type delta ) { FC_ASSERT( is_delegate() ); delegate_info->votes_for += delta; }
int64_t account_record::net_votes()const { FC_ASSERT( is_delegate() ); return delegate_info->votes_for; }
share_type votes_against()const { FC_ASSERT( is_delegate() ); return delegate_info->votes_against; }
share_type votes_for()const { FC_ASSERT( is_delegate() ); return delegate_info->votes_for; }
void adjust_votes_against( share_type delta ) { FC_ASSERT( is_delegate() ); delegate_info->votes_against += delta; }
int64_t net_votes()const { // TODO: move to cpp FC_ASSERT( is_delegate() ); return delegate_info->votes_for - delegate_info->votes_against; }
share_type delegate_pay_balance()const { // TODO: move to cpp FC_ASSERT( is_delegate() ); return delegate_info->pay_balance; }