void burn_operation::evaluate( transaction_evaluation_state& eval_state )
   { try {
      if( message.size() )
          FC_ASSERT( amount.asset_id == 0 );

      if( amount.asset_id == 0 )
      {
          FC_ASSERT( amount.amount >= BTS_BLOCKCHAIN_MIN_BURN_FEE, "",
                     ("amount",amount)
                     ("BTS_BLOCKCHAIN_MIN_BURN_FEE",BTS_BLOCKCHAIN_MIN_BURN_FEE) );
      }

      oasset_record asset_rec = eval_state._current_state->get_asset_record( amount.asset_id );
      FC_ASSERT( asset_rec.valid() );
      FC_ASSERT( !asset_rec->is_market_issued() );

      asset_rec->current_share_supply -= this->amount.amount;
      eval_state.sub_balance( address(), this->amount );

      eval_state._current_state->store_asset_record( *asset_rec );

      if( account_id != 0 ) // you can offer burnt offerings to God if you like... otherwise it must be an account
      {
          // TODO: support burning to any OBJECT ID not just accounts
          const oaccount_record account_rec = eval_state._current_state->get_account_record( abs( this->account_id ) );
          FC_ASSERT( account_rec.valid() );
      }
      eval_state._current_state->store_burn_record( burn_record( burn_record_key( {account_id, eval_state.trx.id()} ),
                                                                 burn_record_value( {amount,message,message_signature} ) ) );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }
 void ad_operation::evaluate( transaction_evaluation_state& eval_state )const
 { try {
     if( this->amount.amount <= 0 )
         FC_CAPTURE_AND_THROW( negative_deposit, (amount) );
     
     FC_ASSERT( !message.empty() );
     
     FC_ASSERT( amount.asset_id == 0 );
     
     const size_t message_kb = (message.size() / 1024) + 1;
     const share_type required_fee = message_kb * BTS_BLOCKCHAIN_MIN_AD_FEE;
     
     FC_ASSERT( amount.amount >= required_fee, "Message of size ${s} KiB requires at least ${a} satoshis to be pay!",
               ("s",message_kb)("a",required_fee) );
     // half of the note fees goto collected fees(delegate pay), other go to ad owner
     eval_state.min_fees[amount.asset_id] += required_fee;
     
     FC_ASSERT( owner_account_id != 0 );
     const oaccount_record owner_account_rec = eval_state.pending_state()->get_account_record( abs( this->owner_account_id ) );
     FC_ASSERT( owner_account_rec.valid() );
     
     auto owner_address = owner_account_rec->active_address();
     auto ad_income_balance = eval_state.pending_state()->get_balance_record(withdraw_condition( withdraw_with_signature(owner_address), 0 ).get_address());
     if( !ad_income_balance )
         ad_income_balance = balance_record( owner_address, asset(0, 0), 0 );
     
     auto ad_pay = amount.amount - required_fee;
     ad_income_balance->balance += ad_pay;
     ad_income_balance->last_update = eval_state.pending_state()->now();
     ad_income_balance->deposit_date = eval_state.pending_state()->now();
     
     eval_state.pending_state()->store_balance_record( *ad_income_balance );
     
     eval_state.sub_balance( asset(ad_pay, amount.asset_id) );
     
     // checking the signature of the publisher.
     FC_ASSERT( publisher_account_id != 0 );
     const oaccount_record publisher_account_rec = eval_state.pending_state()->get_account_record( abs( this->publisher_account_id ) );
     FC_ASSERT( publisher_account_rec.valid() );
     
     eval_state.check_signature( publisher_account_rec->active_key() );
     
     ad_record record;
     record.index.account_id = owner_account_id;
     record.index.transaction_id = eval_state.trx.id();
     record.publisher_id = publisher_account_id;
     record.amount = amount;
     record.message = message;
     record.signer = message_signature;
     
     // the message must be signed by the claimed publisher account
     FC_ASSERT( publisher_account_rec->active_key() == record.signer_key() );
     
     FC_ASSERT( !eval_state.pending_state()->get_ad_record( record.index ).valid() );
     
     eval_state.pending_state()->store_ad_record( std::move( record ) );
 } FC_CAPTURE_AND_RETHROW( (*this) ) }
    void note_operation::evaluate( transaction_evaluation_state& eval_state )const
    { try {
#ifndef WIN32
#warning [HARDFORK] Remove this check after PLS_V0_1_0_FORK_BLOCK_NUM has passed
#endif
        FC_ASSERT( eval_state.pending_state()->get_head_block_num() >= PLS_V0_1_0_FORK_BLOCK_NUM );

        if( this->amount.amount <= 0 )
            FC_CAPTURE_AND_THROW( negative_deposit, (amount) );
        
        FC_ASSERT( !message->data.empty() );
        FC_ASSERT( amount.asset_id == 0 );
        
        const size_t message_kb = (message->data.size() / 1024) + 1;
        const share_type required_fee = message_kb * BTS_BLOCKCHAIN_MIN_NOTE_FEE;
        
        FC_ASSERT( amount.amount >= required_fee, "Message of size ${s} KiB requires at least ${a} satoshis to be burned!",
                  ("s",message_kb)("a",required_fee) );
        
        // 30% of the note fees goto collected fees(delegate pay), other go to the operation pool
        eval_state.min_fees[amount.asset_id] += amount.amount * 3 / 10;
        
        // TODO: instead of burn, the left will go to a fee pool attached to this operation.
        auto op_reward_record = eval_state.pending_state()->get_operation_reward_record(note_op_type);
        auto reward_fee = amount.amount - amount.amount * 3 / 10;
        op_reward_record->fees[amount.asset_id] += reward_fee;
        eval_state.sub_balance( asset(reward_fee, amount.asset_id) );
        eval_state.pending_state()->store_operation_reward_record( *op_reward_record );
        
        // the transaction check the signature of the owner
        const oaccount_record account_rec = eval_state.pending_state()->get_account_record( abs( this->owner_account_id ) );
        FC_ASSERT( account_rec.valid() );
        
        eval_state.check_signature( account_rec->active_key() );
        
        note_record record;
        record.index.account_id = owner_account_id;
        record.index.transaction_id = eval_state.trx.id();
        record.amount = amount;
        record.message = message;
        record.signer = message_signature;
        
        // verify the signature of the message, the message signer must be the account_id's active key
        FC_ASSERT( account_rec->active_key() == record.signer_key() );
        
        FC_ASSERT( !eval_state.pending_state()->get_note_record( record.index ).valid() );
        
        eval_state.pending_state()->store_note_record( std::move( record ) );
    } FC_CAPTURE_AND_RETHROW( (*this) ) }
   void burn_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
      if( this->amount.amount <= 0 )
         FC_CAPTURE_AND_THROW( negative_deposit, (amount) );

      if( !message.empty() )
          FC_ASSERT( amount.asset_id == 0 );

      if( amount.asset_id == 0 )
      {
          const size_t message_kb = (message.size() / 1024) + 1;
          const share_type required_fee = message_kb * BTS_BLOCKCHAIN_MIN_BURN_FEE;

          FC_ASSERT( amount.amount >= required_fee, "Message of size ${s} KiB requires at least ${a} satoshis to be burned!",
                     ("s",message_kb)("a",required_fee) );
      }

      oasset_record asset_rec = eval_state.pending_state()->get_asset_record( amount.asset_id );
      FC_ASSERT( asset_rec.valid() );
      FC_ASSERT( !asset_rec->is_market_issued() );

      asset_rec->current_supply -= this->amount.amount;
      eval_state.sub_balance( this->amount );

      eval_state.pending_state()->store_asset_record( *asset_rec );

      if( account_id != 0 ) // you can offer burnt offerings to God if you like... otherwise it must be an account
      {
          const oaccount_record account_rec = eval_state.pending_state()->get_account_record( abs( this->account_id ) );
          FC_ASSERT( account_rec.valid() );
      }

      burn_record record;
      record.index.account_id = account_id;
      record.index.transaction_id = eval_state.trx.id();
      record.amount = amount;
      record.message = message;
      record.signer = message_signature;

      FC_ASSERT( !eval_state.pending_state()->get_burn_record( record.index ).valid() );

      eval_state.pending_state()->store_burn_record( std::move( record ) );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }
Beispiel #5
0
   void add_collateral_operation::evaluate( transaction_evaluation_state& eval_state )
   {
        FC_ASSERT(!"Not implemented for this DAC.\n");
      if( this->cover_index.order_price == price() )
         FC_CAPTURE_AND_THROW( zero_price, (cover_index.order_price) );

      if( this->amount == 0 ) 
         FC_CAPTURE_AND_THROW( zero_amount );

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

      asset delta_amount  = this->get_amount();
      eval_state.sub_balance( address(), delta_amount );

      // update collateral and call price
      auto current_cover   = eval_state._current_state->get_collateral_record( this->cover_index );
      if( NOT current_cover )
         FC_CAPTURE_AND_THROW( unknown_market_order, (cover_index) );

      current_cover->collateral_balance += delta_amount.amount;

      // changing the payoff balance changes the call price... so we need to remove the old record
      // and insert a new one.
      eval_state._current_state->store_collateral_record( this->cover_index, collateral_record() ); 

      auto new_call_price = asset(current_cover->payoff_balance, delta_amount.asset_id) /
                            asset((current_cover->collateral_balance*3)/4, 0);

      eval_state._current_state->store_collateral_record( market_index_key( new_call_price, this->cover_index.owner),
                                                          *current_cover );

      auto market_stat = eval_state._current_state->get_market_status( cover_index.order_price.quote_asset_id, cover_index.order_price.base_asset_id );
      FC_ASSERT( market_stat, "this should be valid for there to even be a position to cover" );
      market_stat->ask_depth += delta_amount.amount;

      eval_state._current_state->store_market_status( *market_stat );
   }
   void deposit_operation::evaluate( transaction_evaluation_state& eval_state )const
   { try {
       if( this->amount <= 0 )
          FC_CAPTURE_AND_THROW( negative_deposit, (amount) );

       switch( withdraw_condition_types( this->condition.type ) )
       {
          case withdraw_signature_type:
          case withdraw_multisig_type:
          case withdraw_escrow_type:
             break;
          default:
             FC_CAPTURE_AND_THROW( invalid_withdraw_condition, (*this) );
       }

       const balance_id_type deposit_balance_id = this->balance_id();

       obalance_record cur_record = eval_state.pending_state()->get_balance_record( deposit_balance_id );
       if( !cur_record.valid() )
       {
          cur_record = balance_record( this->condition );
          if( this->condition.type == withdraw_escrow_type )
             cur_record->meta_data = variant_object("creating_transaction_id", eval_state.trx.id() );
       }

       if( cur_record->balance == 0 )
       {
          cur_record->deposit_date = eval_state.pending_state()->now();
       }
       else
       {
          fc::uint128 old_sec_since_epoch( cur_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 * cur_record->balance) + (new_sec_since_epoch * this->amount);
          avg /= (cur_record->balance + this->amount);

          cur_record->deposit_date = time_point_sec( avg.to_integer() );
       }

       cur_record->balance += this->amount;
       eval_state.sub_balance( asset( this->amount, cur_record->asset_id() ) );

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

       cur_record->last_update = eval_state.pending_state()->now();

       const oasset_record asset_rec = eval_state.pending_state()->get_asset_record( cur_record->condition.asset_id );
       FC_ASSERT( asset_rec.valid() );

       if( asset_rec->is_market_issued() )
       {
           FC_ASSERT( cur_record->condition.slate_id == 0 );
       }

       const auto& owners = cur_record->owners();
       for( const address& owner : owners )
       {
           FC_ASSERT( asset_rec->address_is_whitelisted( owner ) );
       }

       eval_state.pending_state()->store_balance_record( *cur_record );
   } FC_CAPTURE_AND_RETHROW( (*this) ) }