transaction_builder& transaction_builder::update_signing_key( const string& authorizing_account_name,
        const string& delegate_name,
        const public_key_type& signing_key )
{   try {
        const owallet_account_record authorizing_account_record = _wimpl->_wallet_db.lookup_account( authorizing_account_name );
        if( !authorizing_account_record.valid() )
            FC_THROW_EXCEPTION( unknown_account, "Unknown authorizing account name!" );

        const oaccount_record delegate_record = _wimpl->_blockchain->get_account_record( delegate_name );
        if( !delegate_record.valid() )
            FC_THROW_EXCEPTION( unknown_account, "Unknown delegate account name!" );

        trx.update_signing_key( delegate_record->id, signing_key );
        deduct_balance( authorizing_account_record->owner_address(), asset() );

        ledger_entry entry;
        entry.from_account = authorizing_account_record->active_key();
        entry.to_account = delegate_record->owner_key;
        entry.memo = "update block signing key";

        transaction_record.ledger_entries.push_back( entry );

        required_signatures.insert( authorizing_account_record->active_key() );
        return *this;
    }
    FC_CAPTURE_AND_RETHROW( (authorizing_account_name)(delegate_name)(signing_key) )
}
   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 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) ) }
 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) ) }
Exemple #6
0
string pretty_account( const oaccount_record& record, cptr client )
{
    if( !record.valid() ) return "No account found.\n";
    FC_ASSERT( client != nullptr );

    std::stringstream out;
    out << std::left;

    out << "Name: " << record->name << "\n";
    bool founder = record->registration_date == client->get_chain()->get_genesis_timestamp();
    string registered = !founder ? pretty_timestamp( record->registration_date ) : "Genesis (Keyhotee Founder)";
    out << "Registered: " << registered << "\n";
    out << "Last Updated: " << pretty_age( record->last_update ) << "\n";
    out << "Owner Key: " << std::string( record->owner_key ) << "\n";

    out << "Active Key History:\n";
    for( const auto& key : record->active_key_history )
    {
        out << "- " << std::string( key.second )
            << ", last used " << pretty_age( key.first ) << "\n";
    }

    if( record->is_delegate() )
    {
      const vector<account_record> delegate_records = { *record };
      out << "\n" << pretty_delegate_list( delegate_records, client ) << "\n";
    }
    else
    {
      out << "Not a delegate.\n";
    }

    if( !record->public_data.is_null() )
    {
      out << "Public Data:\n";
      out << fc::json::to_pretty_string( record->public_data ) << "\n";
    }

    return out.str();
}
transaction_builder& transaction_builder::update_asset( const string& symbol,
                                                        const optional<string>& name,
                                                        const optional<string>& description,
                                                        const optional<variant>& public_data,
                                                        const optional<double>& maximum_share_supply,
                                                        const optional<uint64_t>& precision )
{ try {
    const oasset_record asset_record = _wimpl->_blockchain->get_asset_record( symbol );
    FC_ASSERT( asset_record.valid() );

    const oaccount_record issuer_account_record = _wimpl->_blockchain->get_account_record( asset_record->issuer_account_id );
    if( !issuer_account_record.valid() )
        FC_THROW_EXCEPTION( unknown_account, "Unknown issuer account id!" );

    trx.update_asset( asset_record->id, name, description, public_data, maximum_share_supply, precision );
    deduct_balance( issuer_account_record->active_key(), asset() );

    ledger_entry entry;
    entry.from_account = issuer_account_record->active_key();
    entry.to_account = issuer_account_record->active_key();
    entry.memo = "update " + symbol + " asset";

    transaction_record.ledger_entries.push_back( entry );

    required_signatures.insert( issuer_account_record->active_key() );
    return *this;
} FC_CAPTURE_AND_RETHROW( (symbol)(name)(description)(public_data)(maximum_share_supply)(precision) ) }