void update_balance_vote_operation::evaluate( transaction_evaluation_state& eval_state )const { try { auto current_balance_record = eval_state.pending_state()->get_balance_record( this->balance_id ); FC_ASSERT( current_balance_record.valid(), "No such balance!" ); FC_ASSERT( current_balance_record->condition.asset_id == 0, "Only BTS balances can have restricted owners." ); FC_ASSERT( current_balance_record->condition.type == withdraw_signature_type, "Restricted owners not enabled for anything but basic balances" ); auto last_update_secs = current_balance_record->last_update.sec_since_epoch(); ilog("last_update_secs is: ${secs}", ("secs", last_update_secs) ); auto balance = current_balance_record->balance; auto fee = BTS_BLOCKCHAIN_PRECISION / 2; FC_ASSERT( balance > fee ); auto asset_rec = eval_state.pending_state()->get_asset_record( current_balance_record->condition.asset_id ); if( asset_rec->is_market_issued() ) FC_ASSERT( current_balance_record->condition.slate_id == 0 ); if( current_balance_record->condition.slate_id ) { eval_state.adjust_vote( current_balance_record->condition.slate_id, -balance ); } current_balance_record->balance -= balance; current_balance_record->last_update = eval_state.pending_state()->now(); ilog("I'm storing a balance record whose last update is: ${secs}", ("secs", current_balance_record->last_update) ); eval_state.pending_state()->store_balance_record( *current_balance_record ); auto new_restricted_owner = current_balance_record->restricted_owner; auto new_slate = current_balance_record->condition.slate_id; if( this->new_restricted_owner.valid() && (this->new_restricted_owner != new_restricted_owner) ) { ilog("@n new restricted owner specified and its not the existing one"); for( const auto& owner : current_balance_record->owners() ) //eventually maybe multisig can delegate vote { if( !eval_state.check_signature( owner ) ) FC_CAPTURE_AND_THROW( missing_signature, (owner) ); } new_restricted_owner = this->new_restricted_owner; new_slate = this->new_slate; } else // NOT this->new_restricted_owner.valid() || (this->new_restricted_owner == new_restricted_owner) { auto restricted_owner = current_balance_record->restricted_owner; /* FC_ASSERT( restricted_owner.valid(), "Didn't specify a new restricted owner, but one currently exists." ); */ ilog( "@n now: ${secs}", ("secs", eval_state.pending_state()->now().sec_since_epoch()) ); ilog( "@n last update: ${secs}", ("secs", last_update_secs ) ); FC_ASSERT( eval_state.pending_state()->now().sec_since_epoch() - last_update_secs >= BTS_BLOCKCHAIN_VOTE_UPDATE_PERIOD_SEC, "You cannot update your vote this frequently with only the voting key!" ); if( NOT eval_state.check_signature( *restricted_owner ) ) { const auto& owners = current_balance_record->owners(); for( const auto& owner : owners ) //eventually maybe multisig can delegate vote { if( NOT eval_state.check_signature( owner ) ) FC_CAPTURE_AND_THROW( missing_signature, (owner) ); } } new_slate = this->new_slate; } const auto owner = current_balance_record->owner(); FC_ASSERT( owner.valid() ); withdraw_condition new_condition( withdraw_with_signature( *owner ), 0, new_slate ); balance_record newer_balance_record( new_condition ); auto new_balance_record = eval_state.pending_state()->get_balance_record( newer_balance_record.id() ); if( !new_balance_record.valid() ) new_balance_record = current_balance_record; new_balance_record->condition = new_condition; if( new_balance_record->balance == 0 ) { new_balance_record->deposit_date = eval_state.pending_state()->now(); } else { fc::uint128 old_sec_since_epoch( current_balance_record->deposit_date.sec_since_epoch() ); fc::uint128 new_sec_since_epoch( eval_state.pending_state()->now().sec_since_epoch() ); fc::uint128 avg = (old_sec_since_epoch * new_balance_record->balance) + (new_sec_since_epoch * balance); avg /= (new_balance_record->balance + balance); new_balance_record->deposit_date = time_point_sec( avg.to_integer() ); } new_balance_record->last_update = eval_state.pending_state()->now(); new_balance_record->balance += (balance - fee); new_balance_record->restricted_owner = new_restricted_owner; eval_state.add_balance( asset(fee, 0) ); // update delegate vote on deposited account.. if( new_balance_record->condition.slate_id ) eval_state.adjust_vote( new_balance_record->condition.slate_id, (balance-fee) ); ilog("I'm storing a balance record whose last update is: ${secs}", ("secs", new_balance_record->last_update) ); eval_state.pending_state()->store_balance_record( *new_balance_record ); } FC_CAPTURE_AND_RETHROW( (*this) ) }
void Helper ( const AbstractDistMatrix<S>& A, AbstractDistMatrix<T>& B ) { EL_DEBUG_CSE // TODO: Decide whether S or T should be used as the transmission type // based upon which is smaller. Transmit S by default. const Int height = A.Height(); const Int width = A.Width(); const Grid& g = B.Grid(); B.Resize( height, width ); Zero( B ); const bool BPartic = B.Participating(); const int BRoot = B.Root(); const bool includeViewers = (A.Grid() != B.Grid()); const Int localHeight = A.LocalHeight(); const Int localWidth = A.LocalWidth(); auto& ALoc = A.LockedMatrix(); auto& BLoc = B.Matrix(); // TODO: Break into smaller pieces to avoid excessive memory usage? vector<Entry<S>> remoteEntries; vector<int> distOwners; if( A.RedundantRank() == 0 ) { const bool noRedundant = B.RedundantSize() == 1; const int colStride = B.ColStride(); const int rowRank = B.RowRank(); const int colRank = B.ColRank(); vector<Int> globalRows(localHeight), localRows(localHeight); vector<int> ownerRows(localHeight); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const Int i = A.GlobalRow(iLoc); const int ownerRow = B.RowOwner(i); globalRows[iLoc] = i; ownerRows[iLoc] = ownerRow; localRows[iLoc] = B.LocalRow(i,ownerRow); } remoteEntries.reserve( localHeight*localWidth ); distOwners.reserve( localHeight*localWidth ); for( Int jLoc=0; jLoc<localWidth; ++jLoc ) { const Int j = A.GlobalCol(jLoc); const int ownerCol = B.ColOwner(j); const Int localCol = B.LocalCol(j,ownerCol); const bool isLocalCol = ( BPartic && ownerCol == rowRank ); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const int ownerRow = ownerRows[iLoc]; const Int localRow = localRows[iLoc]; const bool isLocalRow = ( BPartic && ownerRow == colRank ); const S& alpha = ALoc(iLoc,jLoc); if( noRedundant && isLocalRow && isLocalCol ) { BLoc(localRow,localCol) = Caster<S,T>::Cast(alpha); } else { remoteEntries.push_back ( Entry<S>{localRow,localCol,alpha} ); distOwners.push_back( ownerRow + colStride*ownerCol ); } } } } // We will first push to redundant rank 0 of B const int redundantRootB = 0; // Compute the metadata // ==================== const Int totalSend = remoteEntries.size(); mpi::Comm comm; vector<int> sendCounts, owners(totalSend); if( includeViewers ) { comm = g.ViewingComm(); const int viewingSize = mpi::Size( g.ViewingComm() ); const int distBSize = mpi::Size( B.DistComm() ); vector<int> distBToViewing(distBSize); for( int distBRank=0; distBRank<distBSize; ++distBRank ) { const int vcOwner = g.CoordsToVC (B.ColDist(),B.RowDist(),distBRank,BRoot,redundantRootB); distBToViewing[distBRank] = g.VCToViewing(vcOwner); } sendCounts.resize(viewingSize,0); for( Int k=0; k<totalSend; ++k ) { owners[k] = distBToViewing[distOwners[k]]; ++sendCounts[owners[k]]; } } else { if( !g.InGrid() ) return; comm = g.VCComm(); const int distBSize = mpi::Size( B.DistComm() ); vector<int> distBToVC(distBSize); for( int distBRank=0; distBRank<distBSize; ++distBRank ) { distBToVC[distBRank] = g.CoordsToVC (B.ColDist(),B.RowDist(),distBRank,BRoot,redundantRootB); } const int vcSize = mpi::Size( g.VCComm() ); sendCounts.resize(vcSize,0); for( Int k=0; k<totalSend; ++k ) { owners[k] = distBToVC[distOwners[k]]; ++sendCounts[owners[k]]; } } SwapClear( distOwners ); // Pack the data // ============= vector<int> sendOffs; Scan( sendCounts, sendOffs ); vector<Entry<S>> sendBuf; FastResize( sendBuf, totalSend ); auto offs = sendOffs; for( Int k=0; k<totalSend; ++k ) sendBuf[offs[owners[k]]++] = remoteEntries[k]; SwapClear( remoteEntries ); SwapClear( owners ); // Exchange and unpack the data // ============================ auto recvBuf = mpi::AllToAll( sendBuf, sendCounts, sendOffs, comm ); if( BPartic ) { if( B.RedundantRank() == redundantRootB ) { Int recvBufSize = recvBuf.size(); for( Int k=0; k<recvBufSize; ++k ) { const auto& entry = recvBuf[k]; BLoc(entry.i,entry.j) = Caster<S,T>::Cast(entry.value); } } El::Broadcast( B, B.RedundantComm(), redundantRootB ); } }