Esempio n. 1
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) ) }
Esempio n. 2
0
   void release_escrow_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
      auto escrow_balance_record = eval_state.pending_state()->get_balance_record( this->escrow_id );
      FC_ASSERT( escrow_balance_record.valid() );

      if( this->amount_to_receiver < 0 )
         FC_CAPTURE_AND_THROW( negative_withdraw, (amount_to_receiver) );

      if( this->amount_to_sender < 0 )
         FC_CAPTURE_AND_THROW( negative_withdraw, (amount_to_sender) );

      if( !eval_state.check_signature( this->released_by ) )
         FC_ASSERT( false, "transaction not signed by releasor" );

      auto escrow_condition = escrow_balance_record->condition.as<withdraw_with_escrow>();
      auto total_released = uint64_t(amount_to_sender) + uint64_t(amount_to_receiver);

      FC_ASSERT( total_released <= escrow_balance_record->balance );
      FC_ASSERT( total_released >= amount_to_sender ); // check for addition overflow
      FC_ASSERT( total_released >= amount_to_receiver ); // check for addition overflow

      escrow_balance_record->balance -= total_released;
      auto asset_rec = eval_state.pending_state()->get_asset_record( escrow_balance_record->condition.asset_id );

      if( amount_to_sender > 0 )
          FC_ASSERT( asset_rec->address_is_whitelisted( escrow_condition.sender ) );
      if( amount_to_receiver > 0 )
          FC_ASSERT( asset_rec->address_is_whitelisted( escrow_condition.receiver ) );

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

      if( escrow_condition.sender == this->released_by )
      {
         FC_ASSERT( amount_to_sender == 0 );
         FC_ASSERT( amount_to_receiver <= escrow_balance_record->balance );

         if( !eval_state.check_signature( escrow_condition.sender ) && !authority_is_retracting)
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.sender) );

         balance_record new_balance_record( escrow_condition.receiver,
                                            asset( amount_to_receiver, escrow_balance_record->asset_id() ),
                                            escrow_balance_record->slate_id() );
         auto current_receiver_balance = eval_state.pending_state()->get_balance_record( new_balance_record.id());

         if( current_receiver_balance )
            current_receiver_balance->balance += amount_to_receiver;
         else
            current_receiver_balance = new_balance_record;

          eval_state.pending_state()->store_balance_record( *current_receiver_balance );
      }
      else if( escrow_condition.receiver == this->released_by )
      {
         FC_ASSERT( amount_to_receiver == 0 );
         FC_ASSERT( amount_to_sender <= escrow_balance_record->balance );

         if( !eval_state.check_signature( escrow_condition.receiver ) && !authority_is_retracting)
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.receiver) );

         balance_record new_balance_record( escrow_condition.sender,
                                            asset( amount_to_sender, escrow_balance_record->asset_id() ),
                                            escrow_balance_record->slate_id() );
         auto current_sender_balance = eval_state.pending_state()->get_balance_record( new_balance_record.id());

         if( current_sender_balance )
            current_sender_balance->balance += amount_to_sender;
         else
            current_sender_balance = new_balance_record;

         eval_state.pending_state()->store_balance_record( *current_sender_balance );
      }
      else if( escrow_condition.escrow == this->released_by )
      {
         if( !eval_state.check_signature( escrow_condition.escrow ) && !authority_is_retracting )
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.escrow) );
         // get a balance record for the receiver, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.receiver,
                                               asset( amount_to_receiver, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_receiver_balance = eval_state.pending_state()->get_balance_record( new_balance_record.id());

            if( current_receiver_balance )
               current_receiver_balance->balance += amount_to_receiver;
            else
               current_receiver_balance = new_balance_record;
            eval_state.pending_state()->store_balance_record( *current_receiver_balance );
         }
         //  get a balance record for the sender, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.sender,
                                               asset( amount_to_sender, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_sender_balance = eval_state.pending_state()->get_balance_record( new_balance_record.id());

            if( current_sender_balance )
               current_sender_balance->balance += amount_to_sender;
            else
               current_sender_balance = new_balance_record;
            eval_state.pending_state()->store_balance_record( *current_sender_balance );
         }
      }
      else if( address() == this->released_by )
      {
         if( !eval_state.check_signature( escrow_condition.sender ) && !authority_is_retracting)
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.sender) );
         if( !eval_state.check_signature( escrow_condition.receiver ) && !authority_is_retracting)
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.receiver) );
         // get a balance record for the receiver, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.receiver,
                                               asset( amount_to_receiver, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_receiver_balance = eval_state.pending_state()->get_balance_record( new_balance_record.id());

            if( current_receiver_balance )
               current_receiver_balance->balance += amount_to_receiver;
            else
               current_receiver_balance = new_balance_record;
            eval_state.pending_state()->store_balance_record( *current_receiver_balance );
         }
         //  get a balance record for the sender, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.sender,
                                               asset( amount_to_sender, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_sender_balance = eval_state.pending_state()->get_balance_record( new_balance_record.id());

            if( current_sender_balance )
               current_sender_balance->balance += amount_to_sender;
            else
               current_sender_balance = new_balance_record;
            eval_state.pending_state()->store_balance_record( *current_sender_balance );
         }
      }
      else
      {
          FC_ASSERT( false, "not released by a party to the escrow transaction" );
      }

      eval_state.pending_state()->store_balance_record( *escrow_balance_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }
   void release_escrow_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      FC_ASSERT( !"This operation is not enabled yet!" );

      auto escrow_balance_record = eval_state._current_state->get_balance_record( this->escrow_id );
      FC_ASSERT( escrow_balance_record.valid() );

      if( !eval_state.check_signature( this->released_by ) )
         FC_ASSERT( !"transaction not signed by releasor" );

      auto escrow_condition = escrow_balance_record->condition.as<withdraw_with_escrow>();
      auto total_released = amount_to_sender + amount_to_receiver;

      FC_ASSERT( total_released <= escrow_balance_record->balance );
      FC_ASSERT( total_released >= amount_to_sender ); // check for addition overflow

      escrow_balance_record->balance -= total_released;
      auto asset_rec = eval_state._current_state->get_asset_record( escrow_balance_record->condition.asset_id );
      if( asset_rec->is_restricted() )
      {
         FC_ASSERT( eval_state._current_state->get_authorization( escrow_balance_record->condition.asset_id, escrow_condition.receiver ) );
      }
      if( asset_rec->is_retractable() )
      {
         if( eval_state.verify_authority( asset_rec->authority ) )
         {
            //
         }
      }

      if( escrow_condition.sender == this->released_by )
      {
         FC_ASSERT( amount_to_sender == 0 );
         FC_ASSERT( amount_to_receiver <= escrow_balance_record->balance );

         if( !eval_state.check_signature( escrow_condition.sender ) )
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.sender) );

         balance_record new_balance_record( escrow_condition.receiver,
                                            asset( amount_to_receiver, escrow_balance_record->asset_id() ),
                                            escrow_balance_record->slate_id() );
         auto current_receiver_balance = eval_state._current_state->get_balance_record( new_balance_record.id());

         if( current_receiver_balance )
            current_receiver_balance->balance += amount_to_receiver;
         else
            current_receiver_balance = new_balance_record;

          eval_state._current_state->store_balance_record( *current_receiver_balance );
      }
      else if( escrow_condition.receiver == this->released_by )
      {
         FC_ASSERT( amount_to_receiver == 0 );
         FC_ASSERT( amount_to_sender <= escrow_balance_record->balance );

         if( !eval_state.check_signature( escrow_condition.receiver ) )
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.receiver) );

         balance_record new_balance_record( escrow_condition.sender,
                                            asset( amount_to_sender, escrow_balance_record->asset_id() ),
                                            escrow_balance_record->slate_id() );
         auto current_sender_balance = eval_state._current_state->get_balance_record( new_balance_record.id());

         if( current_sender_balance )
            current_sender_balance->balance += amount_to_sender;
         else
            current_sender_balance = new_balance_record;

         eval_state._current_state->store_balance_record( *current_sender_balance );
      }
      else if( escrow_condition.escrow == this->released_by )
      {
         if( !eval_state.check_signature( escrow_condition.escrow ) )
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.escrow) );
         // get a balance record for the receiver, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.receiver,
                                               asset( amount_to_receiver, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_receiver_balance = eval_state._current_state->get_balance_record( new_balance_record.id());

            if( current_receiver_balance )
               current_receiver_balance->balance += amount_to_receiver;
            else
               current_receiver_balance = new_balance_record;
            eval_state._current_state->store_balance_record( *current_receiver_balance );
         }
         //  get a balance record for the sender, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.sender,
                                               asset( amount_to_sender, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_sender_balance = eval_state._current_state->get_balance_record( new_balance_record.id());

            if( current_sender_balance )
               current_sender_balance->balance += amount_to_sender;
            else
               current_sender_balance = new_balance_record;
            eval_state._current_state->store_balance_record( *current_sender_balance );
         }
      }
      else if( address() == this->released_by )
      {
         if( !eval_state.check_signature( escrow_condition.sender ) )
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.sender) );
         if( !eval_state.check_signature( escrow_condition.receiver ) )
             FC_CAPTURE_AND_THROW( missing_signature, (escrow_condition.receiver) );
         // get a balance record for the receiver, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.receiver,
                                               asset( amount_to_receiver, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_receiver_balance = eval_state._current_state->get_balance_record( new_balance_record.id());

            if( current_receiver_balance )
               current_receiver_balance->balance += amount_to_receiver;
            else
               current_receiver_balance = new_balance_record;
            eval_state._current_state->store_balance_record( *current_receiver_balance );
         }
         //  get a balance record for the sender, create it if necessary and deposit funds
         {
            balance_record new_balance_record( escrow_condition.sender,
                                               asset( amount_to_sender, escrow_balance_record->asset_id() ),
                                               escrow_balance_record->slate_id() );
            auto current_sender_balance = eval_state._current_state->get_balance_record( new_balance_record.id());

            if( current_sender_balance )
               current_sender_balance->balance += amount_to_sender;
            else
               current_sender_balance = new_balance_record;
            eval_state._current_state->store_balance_record( *current_sender_balance );
         }
      }
      else
      {
          FC_ASSERT( !"not released by a party to the escrow transaction" );
      }

      eval_state._current_state->store_balance_record( *escrow_balance_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }