void user_auction_claim_operation::evaluate( transaction_evaluation_state& eval_state )
    { try {
        FC_ASSERT( !"This operation is not enabled yet!" );

        auto chain = eval_state._current_state;   
        auto obj = chain->get_object_record( this->auction_id );
        FC_ASSERT( obj.valid(), "No such auction." );
        auto auction = obj->as<user_auction_record>();
        FC_ASSERT( auction.is_complete( *chain ), "Auction is not over yet." );
        if( this->claim_balance )
        {
            FC_ASSERT( NOT auction.balance_claimed,
                    "Those auction winnings have already been claimed." );
            eval_state.check_update_permission( auction.beneficiary );
            eval_state.add_balance( auction.previous_bid );
            auction.balance_claimed = true;
        }
        if( this->claim_object ) // set the item's owner to the winner
        {
            FC_ASSERT( NOT auction.object_claimed, "That object has already been claimed." );
            eval_state.check_update_permission( auction.previous_bidder );
            auto item = chain->get_object_record( auction.item );
            FC_ASSERT( item->owner_object == auction._id, "An auction was being held for an item owned by someone else?");
            item->owner_object = auction.previous_bidder;
            chain->store_object_record( *item );
            auction.object_claimed = true;
        }
        chain->store_object_record( object_record( auction ) );
    } FC_CAPTURE_AND_RETHROW( (eval_state)(*this) ) }
Example #2
0
   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) ) }
Example #3
0
   void withdraw_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
       if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_withdraw, (amount) );

      obalance_record current_balance_record = eval_state.pending_state()->get_balance_record( this->balance_id );
      if( !current_balance_record.valid() )
         FC_CAPTURE_AND_THROW( unknown_balance_record, (balance_id) );

      if( this->amount > current_balance_record->get_spendable_balance( eval_state.pending_state()->now() ).amount )
         FC_CAPTURE_AND_THROW( insufficient_funds, (current_balance_record)(amount) );

      auto asset_rec = eval_state.pending_state()->get_asset_record( current_balance_record->condition.asset_id );
      FC_ASSERT( asset_rec.valid() );

      const bool authority_is_retracting = asset_rec->flag_is_active( asset_record::retractable_balances )
                                           && eval_state.verify_authority( asset_rec->authority );

      if( !authority_is_retracting )
      {
         FC_ASSERT( !asset_rec->flag_is_active( asset_record::halted_withdrawals ) );

         switch( (withdraw_condition_types)current_balance_record->condition.type )
         {
            case withdraw_signature_type:
            {
                const withdraw_with_signature condition = current_balance_record->condition.as<withdraw_with_signature>();
                const address owner = condition.owner;
                if( !eval_state.check_signature( owner ) )
                    FC_CAPTURE_AND_THROW( missing_signature, (owner) );
                break;
            }

            case withdraw_vesting_type:
            {
                const withdraw_vesting condition = current_balance_record->condition.as<withdraw_vesting>();
                const address owner = condition.owner;
                if( !eval_state.check_signature( owner ) )
                    FC_CAPTURE_AND_THROW( missing_signature, (owner) );
                break;
            }

            case withdraw_multisig_type:
            {
               auto multisig = current_balance_record->condition.as<withdraw_with_multisig>();

               uint32_t valid_signatures = 0;
               for( const auto& sig : multisig.owners )
                    valid_signatures += eval_state.check_signature( sig );

               if( valid_signatures < multisig.required )
                   FC_CAPTURE_AND_THROW( missing_signature, (valid_signatures)(multisig) );
               break;
            }

            default:
               FC_CAPTURE_AND_THROW( invalid_withdraw_condition, (current_balance_record->condition) );
         }
      }

      // update delegate vote on withdrawn account..
      if( current_balance_record->condition.asset_id == 0 && current_balance_record->condition.slate_id )
         eval_state.adjust_vote( current_balance_record->condition.slate_id, -this->amount );

      if( asset_rec->is_market_issued() )
      {
         auto yield = current_balance_record->calculate_yield( eval_state.pending_state()->now(),
                                                               current_balance_record->balance,
                                                               asset_rec->collected_fees,
                                                               asset_rec->current_supply );
         if( yield.amount > 0 )
         {
            asset_rec->collected_fees       -= yield.amount;
            current_balance_record->balance += yield.amount;
            current_balance_record->deposit_date = eval_state.pending_state()->now();
            eval_state.yield_claimed[ current_balance_record->asset_id() ] += yield.amount;
            eval_state.pending_state()->store_asset_record( *asset_rec );
         }
      }

      current_balance_record->balance -= this->amount;
      current_balance_record->last_update = eval_state.pending_state()->now();
      eval_state.pending_state()->store_balance_record( *current_balance_record );

      if( asset_rec->withdrawal_fee != 0 && !eval_state.verify_authority( asset_rec->authority ) )
          eval_state.min_fees[ asset_rec->id ] = std::max( asset_rec->withdrawal_fee, eval_state.min_fees[ asset_rec->id ] );

      eval_state.add_balance( asset( this->amount, current_balance_record->condition.asset_id ) );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }
void withdraw_operation::evaluate_v3( transaction_evaluation_state& eval_state )
{ try {
   if( eval_state._current_state->get_head_block_num() < BTS_V0_4_15_FORK_BLOCK_NUM )
      return evaluate_v2( eval_state );

    if( this->amount <= 0 )
       FC_CAPTURE_AND_THROW( negative_deposit, (amount) );

   obalance_record current_balance_record = eval_state._current_state->get_balance_record( this->balance_id );

   if( !current_balance_record )
      FC_CAPTURE_AND_THROW( unknown_balance_record, (balance_id) );

   if( this->amount > current_balance_record->balance ) // Some withdraw conditions require extra checks (e.g. vesting condition)
      FC_CAPTURE_AND_THROW( insufficient_funds,
                            (current_balance_record)
                            (amount)
                            (current_balance_record->balance - amount) );

   switch( (withdraw_condition_types)current_balance_record->condition.type )
   {
      case withdraw_signature_type:
      {
         auto owner = current_balance_record->condition.as<withdraw_with_signature>().owner;
         if( !eval_state.check_signature( owner ) )
             FC_CAPTURE_AND_THROW( missing_signature, (owner) );
         break;
      }

      default:
         FC_CAPTURE_AND_THROW( invalid_withdraw_condition, (current_balance_record->condition) );
   }
   // update delegate vote on withdrawn account..

   if( current_balance_record->condition.asset_id == 0 && current_balance_record->condition.delegate_slate_id )
      eval_state.adjust_vote( current_balance_record->condition.delegate_slate_id, -this->amount );

   auto asset_rec = eval_state._current_state->get_asset_record( current_balance_record->condition.asset_id );
   FC_ASSERT( asset_rec.valid() );
   if( asset_rec->is_market_issued() )
   {
      auto yield = current_balance_record->calculate_yield_v1( eval_state._current_state->now(),
                                                               current_balance_record->balance,
                                                               asset_rec->collected_fees,
                                                               asset_rec->current_share_supply );

      if( yield.amount > 0 )
      {
         asset_rec->collected_fees       -= yield.amount;
         current_balance_record->balance += yield.amount;
         current_balance_record->deposit_date = eval_state._current_state->now();
         eval_state.yield[current_balance_record->condition.asset_id] += yield.amount;
         eval_state._current_state->store_asset_record( *asset_rec );
      }
   }

   current_balance_record->balance -= this->amount;
   current_balance_record->last_update = eval_state._current_state->now();

   eval_state._current_state->store_balance_record( *current_balance_record );
   eval_state.add_balance( asset(this->amount, current_balance_record->condition.asset_id) );
} FC_CAPTURE_AND_RETHROW( (*this) ) }