asset get_amount()const { return asset( amount, bid_index.order_price.quote_asset_id ); }
inline asset operator - ( const asset& l, const asset& r ) { return asset(l) -= r; }
DEF_TEST(StreamEmptyStreamMemoryBase, r) { SkDynamicMemoryWStream tmp; std::unique_ptr<SkStreamAsset> asset(tmp.detachAsStream()); REPORTER_ASSERT(r, nullptr == asset->getMemoryBase()); }
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) ) }
string pretty_delegate_list( const vector<account_record>& delegate_records, cptr client ) { if( delegate_records.empty() ) return "No delegates found.\n"; FC_ASSERT( client != nullptr ); std::stringstream out; out << std::left; out << std::setw( 6 ) << "ID"; out << std::setw( 32 ) << "NAME (* next in line)"; out << std::setw( 15 ) << "APPROVAL"; out << std::setw( 9 ) << "PRODUCED"; out << std::setw( 9 ) << "MISSED"; out << std::setw( 14 ) << "RELIABILITY"; out << std::setw( 9 ) << "PAY RATE"; out << std::setw( 20 ) << "PAY BALANCE"; out << std::setw( 10 ) << "LAST BLOCK"; out << "\n"; out << pretty_line( 124 ); out << "\n"; const auto current_slot_timestamp = blockchain::get_slot_start_time( blockchain::now() ); const auto head_block_timestamp = client->get_chain()->get_head_block().timestamp; const auto next_slot_time = std::max( current_slot_timestamp, head_block_timestamp + BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC ); const auto& active_delegates = client->get_chain()->get_active_delegates(); const auto next_slot_signee = client->get_chain()->get_slot_signee( next_slot_time, active_delegates ); const auto next_signee_name = next_slot_signee.name; const auto asset_record = client->get_chain()->get_asset_record( asset_id_type() ); FC_ASSERT( asset_record.valid() ); const auto share_supply = asset_record->current_share_supply; for( const auto& delegate_record : delegate_records ) { out << std::setw( 6 ) << delegate_record.id; const auto delegate_name = delegate_record.name; if( delegate_name != next_signee_name ) out << std::setw( 32 ) << pretty_shorten( delegate_name, 31 ); else out << std::setw( 32 ) << pretty_shorten( delegate_name, 29 ) + " *"; out << std::setw( 15 ) << pretty_percent( delegate_record.net_votes(), share_supply, 10 ); const auto num_produced = delegate_record.delegate_info->blocks_produced; const auto num_missed = delegate_record.delegate_info->blocks_missed; out << std::setw( 9 ) << num_produced; out << std::setw( 9 ) << num_missed; out << std::setw( 14 ) << pretty_percent( num_produced, num_produced + num_missed, 2 ); out << std::setw( 9 ) << pretty_percent( delegate_record.delegate_info->pay_rate, 100, 0 ); const auto pay_balance = asset( delegate_record.delegate_info->pay_balance ); out << std::setw( 20 ) << client->get_chain()->to_pretty_asset( pay_balance ); const auto last_block = delegate_record.delegate_info->last_block_num_produced; out << std::setw( 10 ) << ( last_block > 0 ? std::to_string( last_block ) : "NONE" ); out << "\n"; } return out.str(); }
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) ) }
asset balance_record::calculate_yield( fc::time_point_sec now, share_type amount, share_type yield_pool, share_type share_supply )const { if( amount <= 0 ) return asset(0, condition.asset_id); if( share_supply <= 0 ) return asset(0, condition.asset_id); if( yield_pool <= 0 ) return asset(0, condition.asset_id); auto elapsed_time = (now - deposit_date); if( elapsed_time <= fc::seconds( BTS_BLOCKCHAIN_MIN_YIELD_PERIOD_SEC ) ) return asset(0, condition.asset_id); fc::uint128 current_supply( share_supply - yield_pool ); if( current_supply <= 0) return asset(0, condition.asset_id); fc::uint128 fee_fund( yield_pool ); fc::uint128 amount_withdrawn( amount ); amount_withdrawn *= 1000000; // // numerator in the following expression is at most // BTS_BLOCKCHAIN_MAX_SHARES * 1000000 * BTS_BLOCKCHAIN_MAX_SHARES // thus it cannot overflow // fc::uint128 yield = (amount_withdrawn * fee_fund) / current_supply; /** * If less than 1 year, the 80% of yield are scaled linearly with time and 20% scaled by time^2, * this should produce a yield curve that is "80% simple interest" and 20% simulating compound * interest. */ if( elapsed_time < fc::seconds( BTS_BLOCKCHAIN_MAX_YIELD_PERIOD_SEC ) ) { fc::uint128 original_yield = yield; // discount the yield by 80% yield *= 8; yield /= 10; // // yield largest value in preceding multiplication is at most // BTS_BLOCKCHAIN_MAX_SHARES * 1000000 * BTS_BLOCKCHAIN_MAX_SHARES * 8 // thus it cannot overflow // fc::uint128 delta_yield = original_yield - yield; // yield == amount withdrawn / total usd * fee fund * fraction_of_year yield *= elapsed_time.to_seconds(); yield /= BTS_BLOCKCHAIN_MAX_YIELD_PERIOD_SEC; delta_yield *= elapsed_time.to_seconds(); delta_yield /= BTS_BLOCKCHAIN_MAX_YIELD_PERIOD_SEC; delta_yield *= elapsed_time.to_seconds(); delta_yield /= BTS_BLOCKCHAIN_MAX_YIELD_PERIOD_SEC; yield += delta_yield; } yield /= 1000000; if((yield > 0) && (yield < fc::uint128_t(yield_pool))) return asset( yield.to_uint64(), condition.asset_id ); return asset( 0, condition.asset_id ); }
/** When bidding on an asset you specify the asset you have and the price you would like * to sell it at. */ signed_transaction wallet::bid( const asset& amnt, const price& ratio ) { try { auto change_address = get_new_address(); signed_transaction trx; std::unordered_set<bts::address> req_sigs; asset total_in; asset amnt_with_fee = amnt; // TODO: add fee of .1% trx.inputs = my->collect_inputs( amnt_with_fee, total_in, req_sigs ); asset change = total_in - amnt; trx.outputs.push_back( trx_output( claim_by_bid_output( change_address, ratio ), amnt) ); trx.outputs.push_back( trx_output( claim_by_signature_output( change_address ), change) ); trx.sigs.clear(); my->sign_transaction( trx, req_sigs ); uint32_t trx_bytes = fc::raw::pack( trx ).size(); asset fee( my->_current_fee_rate * trx_bytes ); if( amnt.unit == asset::bts ) { if( total_in >= amnt + fee ) { change = change - fee; trx.outputs.back() = trx_output( claim_by_signature_output( change_address ), change ); if( change == asset() ) trx.outputs.pop_back(); // no change required } else { elog( "NOT ENOUGH TO COVER AMOUNT + FEE... GRAB MORE.." ); fee = fee + fee; // double the fee in this case to cover the growth req_sigs.clear(); total_in = asset(); trx.inputs = my->collect_inputs( amnt+fee, total_in, req_sigs ); change = total_in - amnt - fee; trx.outputs.back() = trx_output( claim_by_signature_output( change_address ), change ); if( change == asset() ) trx.outputs.pop_back(); // no change required } } else { if( change.amount == fc::uint128_t(0) ) trx.outputs.pop_back(); // no change required // TODO: this function should be recursive here, but having 2x the fee should be good enough, some // transactions may overpay in this case, but this can be optimized later to reduce fees.. for now fee = fee + fee; // double the fee in this case to cover the growth asset total_fee_in; auto extra_in = my->collect_inputs( fee, total_fee_in, req_sigs ); trx.inputs.insert( trx.inputs.end(), extra_in.begin(), extra_in.end() ); trx.outputs.push_back( trx_output( claim_by_signature_output( change_address ), total_fee_in - fee ) ); } trx.sigs.clear(); my->sign_transaction( trx, req_sigs ); my->_data.open_bids[ output_reference( trx.id(), 0 ) ] = trx.outputs[0]; return trx; } FC_RETHROW_EXCEPTIONS( warn, "${amnt} @ ${price}", ("amnt",amnt)("price",ratio) ) }
void wallet::dump() { std::cerr<<"===========================================================\n"; std::cerr<<"Unspent Outputs: \n"; for( auto itr = my->_unspent_outputs.begin(); itr != my->_unspent_outputs.end(); ++itr ) { std::cerr<<std::string(itr->first.trx_hash)<<":"<<int(itr->first.output_idx)<<"] "; std::cerr<<std::string(itr->second.get_amount())<<" "; std::cerr<<fc::variant(itr->second.claim_func).as_string()<<" "; switch( itr->second.claim_func ) { case claim_by_signature: std::cerr<< std::string(itr->second.as<claim_by_signature_output>().owner); break; default: std::cerr<<"??"; } std::cerr<<"\n"; } std::cerr<<"\n"; std::cerr<<"Open Bids: \n"; for( auto itr = my->_data.open_bids.begin(); itr != my->_data.open_bids.end(); ++itr ) { std::cerr<<std::string(itr->first.trx_hash)<<":"<<int(itr->first.output_idx)<<"] "; std::cerr<<std::string(itr->second.get_amount())<<" "; std::cerr<<fc::variant(itr->second.claim_func).as_string()<<" "; switch( itr->second.claim_func ) { case claim_by_bid: std::cerr<< std::string(itr->second.as<claim_by_bid_output>().ask_price); std::cerr<< " owner: "; std::cerr<< std::string(itr->second.as<claim_by_bid_output>().pay_address); std::cerr<< " min trade: "<< itr->second.as<claim_by_bid_output>().min_trade; break; default: std::cerr<<"??"; } std::cerr<<"\n"; } std::cerr<<"\nOpen Short Sells: \n"; for( auto itr = my->_data.open_short_sells.begin(); itr != my->_data.open_short_sells.end(); ++itr ) { std::cerr<<std::string(itr->first.trx_hash)<<":"<<int(itr->first.output_idx)<<"] "; std::cerr<<std::string(itr->second.get_amount())<<" "; std::cerr<<fc::variant(itr->second.claim_func).as_string()<<" "; switch( itr->second.claim_func ) { case claim_by_long: std::cerr<< std::string(itr->second.as<claim_by_long_output>().ask_price); std::cerr<< " owner: "; std::cerr<< std::string(itr->second.as<claim_by_long_output>().pay_address); std::cerr<< " min trade: "<< itr->second.as<claim_by_long_output>().min_trade; break; default: std::cerr<<"??"; } std::cerr<<"\n"; } std::cerr<<"\nOpen Margin Positions: \n"; for( auto itr = my->_data.open_shorts.begin(); itr != my->_data.open_shorts.end(); ++itr ) { std::cerr<<std::string(itr->first.trx_hash)<<":"<<int(itr->first.output_idx)<<"] "; std::cerr<<std::string(itr->second.get_amount())<<" "; std::cerr<<fc::variant(itr->second.claim_func).as_string()<<" "; switch( itr->second.claim_func ) { case claim_by_cover: { auto cover = itr->second.as<claim_by_cover_output>(); auto payoff = asset(cover.payoff_amount,cover.payoff_unit); auto payoff_threshold = asset(cover.payoff_amount*1.5,cover.payoff_unit); std::cerr<< std::string(payoff); std::cerr<< " owner: "; std::cerr<< std::string(itr->second.as<claim_by_cover_output>().owner); // this is the break even price... we actually need to cover at half the price? std::cerr<< " price: " << std::string(payoff_threshold / itr->second.get_amount()); break; } default: std::cerr<<"??"; } std::cerr<<"\n"; } std::cerr<<"===========================================================\n"; }
friend asset operator + ( const asset& a, const asset& b ) { FC_ASSERT( a.symbol == b.symbol ); return asset( a.amount + b.amount, a.symbol ); }
price market_order::get_highest_cover_price()const { try { FC_ASSERT( type == cover_order ); return asset( state.balance, market_index.order_price.quote_asset_id ) / asset( *collateral ); } FC_CAPTURE_AND_RETHROW() }
asset operator -()const { return asset( -amount, symbol ); }
gstTextureGuard gstTextureManager::NewTextureFromPath( const std::string& path, bool* is_mercator_imagery) { gstTextureGuard error_handle; if (path.empty()) { notify(NFY_WARN, "Bad texture path: %s", path.c_str()); return error_handle; } // handle URL first since it is not a valid file system path if (QString(path).startsWith("http://") || QString(path).startsWith("https://")) { return NewHTTPTexture(path); } QString base(khBasename(path)); bool is_mercator_imagery_project = khHasExtension(path, kMercatorImageryProjectSuffix); bool is_flat_projection_imagery_project = khHasExtension(path, kImageryProjectSuffix); if (is_mercator_imagery_project || is_flat_projection_imagery_project) { *is_mercator_imagery = is_mercator_imagery_project; Asset asset(AssetDefs::FilenameToAssetPath(path)); if (asset->type != AssetDefs::Imagery && asset->subtype != (*is_mercator_imagery ? kMercatorProjectSubtype : kProjectSubtype)) { notify(NFY_WARN, "Asset %s is not a valid imagery project", path.c_str()); return error_handle; } AssetVersion last_good_version(asset->GetLastGoodVersionRef()); if (!last_good_version) { notify(NFY_WARN, "Asset %s doesn't have a valid current version", path.c_str()); return error_handle; } std::string index_path = last_good_version->GetOutputFilename(0); if (khHasExtension(index_path, ".geindex")) { return NewGEIndexTexture(index_path); } else { return error_handle; } } bool is_flat_imagery_asset = base.contains(kImageryAssetSuffix); bool is_flat_terrain_asset = base.contains(kTerrainAssetSuffix); bool is_mercator_imagery_asset = base.contains(kMercatorImageryAssetSuffix); if (is_flat_imagery_asset || is_mercator_imagery_asset || is_flat_terrain_asset) { *is_mercator_imagery = is_mercator_imagery_asset; AssetVersion version(path); if (version && (version->type == AssetDefs::Terrain || version->type == AssetDefs::Imagery) && version->state == AssetDefs::Succeeded) { std::string kippath = version->GetOutputFilename(0); std::string kmppath = version->GetOutputFilename(1); return NewPYRTexture(kippath, kmppath); } } else { if (!khExists(path)) { notify(NFY_WARN, "Bad texture path: %s", path.c_str()); return error_handle; } if (base.endsWith(".gedb")) { *is_mercator_imagery = false; return NewGEDBTexture(path); } else if (base.endsWith(".kip") || base.endsWith(".ktp")) { std::string str = path; str += "/" + kHeaderXmlFile; gstTextureGuard texture = NewPYRTexture(str, std::string()); *is_mercator_imagery = texture->IsMercatorImagery(); return texture; } else if (base.endsWith(".xml")) { gstTextureGuard texture = NewPYRTexture(path, std::string()); *is_mercator_imagery = texture->IsMercatorImagery(); return texture; } } return error_handle; }
asset get_amount()const { return asset( amount, ask_index.order_price.base_asset_id ); }
price(const asset& base = asset(), const asset quote = asset()) : base(base),quote(quote){}
price price::max(asset_symbol_type base, asset_symbol_type quote) { return asset(share_type(STEEMIT_MAX_SHARE_SUPPLY), base) / asset(share_type(1), quote); }
//---------------------------------------------------------------------------------------- // ProcessNextAsset //---------------------------------------------------------------------------------------- bool AZPAMAssetMonitor::ProcessNextAsset() //Returns true if more assets are pending. { LogFunctionEnterExit; #if defined(InDnCS5) || defined(InDnCS5_5) const IExecutionContext* ec = GetExecutionContext(); ISession* gSession = ec->GetSession(); #endif if (mPendingAssetToUpdate.size()) { const PMString & assetId = mPendingAssetToUpdate[0]; ZPAssetIdUIDRefMapConstIter foundIter = mAssetIdUIDRefMap.find( assetId ); ZPAssetIdUIDRefMapConstIter endIter = mAssetIdUIDRefMap.end(); if( foundIter != endIter ) { UIDRef assetRef = foundIter->second; InterfacePtr<IManageableAsset> asset( assetRef, UseDefaultIID() ); ASSERT(asset); if( asset ) this->ProcessAsset( asset ); IZPLog_Str_( thisFileLA, enLT_DebugInfo, "Removing asset id : %s from pending update list", assetId.GrabCString()); mPendingAssetToUpdate.erase(mPendingAssetToUpdate.begin()); return true; //Come again for processing this list or fActiveList } } int activeListSize = fActiveList.size(); if( mCurrentIndex < activeListSize ) { UIDRef assetRef = fActiveList.at( mCurrentIndex ); //Is it valid? Is there any chance that UIDRef is not removed from the active list? InterfacePtr<IManageableAsset> asset( assetRef, UseDefaultIID() ); ASSERT(asset); this->ProcessAsset( asset ); ++mCurrentIndex; } bool toReturn = ( mCurrentIndex < activeListSize ); if (!toReturn && activeListSize > 0 ) { time_t nowTime = time(NULL); // check every 30 seconds #if 0//def DEBUG const int timeDelayBetweenRefresh = 10; //Save debugging time. #else InterfacePtr<const IWorkspace> iWorkspace(gSession->QueryWorkspace()); InterfacePtr<const IZPPrefs> zpPrefs( iWorkspace, UseDefaultIID() ); ASSERT(zpPrefs); const int timeDelayBetweenRefresh = zpPrefs->GetAssetMonitorAutoUpdateDuration(); ASSERT( timeDelayBetweenRefresh >= 10 ); #endif if (nowTime - mLastProcessingTime > timeDelayBetweenRefresh ) { //mCurrentIndex = 0; //Commented here to set it after a delay of 5 seconds. mResetIndexPending = true; mLastProcessingTime = nowTime; this->FetchInfoFromServer(); //Update cached info for monitored assets. } if( mResetIndexPending && nowTime - mLastProcessingTime > 5) //Wait for 5 seconds to get the response from server. { //Someday: better would be to listen the monitored assets for changes. mCurrentIndex = 0; //Reset for next processing. mResetIndexPending = false; } } return toReturn; }
price price::min(asset_symbol_type base, asset_symbol_type quote) { return asset(1, base) / asset(STEEMIT_MAX_SHARE_SUPPLY, quote); }
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 assetRelease() { asset().clear().all(); }
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 match_orders( std::vector<signed_transaction>& matched, asset::type quote, asset::type base ) { try { ilog( "match orders.." ); auto bids = _market_db.get_bids( quote, base ); auto asks = _market_db.get_asks( quote, base ); wlog( "asks: ${asks}", ("asks",asks) ); wlog( "bids: ${bids}", ("bids",bids) ); fc::optional<trx_output> ask_change; fc::optional<trx_output> bid_change; fc::optional<trx_output> cover_change; address bid_payout_address; fc::optional<asset> bid_payout; asset cover_collat; fc::optional<claim_by_cover_output> cover_payout; signed_transaction market_trx; market_trx.timestamp = fc::time_point::now(); /** asks are sorted from low to high, so we start * with the lowest ask, and check to see if there are * any bids that are greaterthan or equal to the ask, if * there are then either the full bid or full ask will be * filled. If the full bid is filled, then move on to the * next bid, and save the leftover ask. If the left over * ask is filled, then move to the next ask. * * When there are no more pairs that can be matched, exit * the loop and any partial payouts are made. */ auto ask_itr = asks.begin(); auto bid_itr = bids.rbegin(); while( ask_itr != asks.end() && bid_itr != bids.rend() ) { trx_output working_ask; trx_output working_bid; if( ask_change ) { working_ask = *ask_change; } else { working_ask = get_output( ask_itr->location ); } if( bid_change ) { working_bid = *bid_change; } else { working_bid = get_output( bid_itr->location); } claim_by_bid_output bid_claim = working_bid.as<claim_by_bid_output>(); if( working_ask.claim_func == claim_by_long ) { auto long_claim = working_ask.as<claim_by_long_output>(); if( long_claim.ask_price > bid_claim.ask_price ) { break; // exit the while loop, no more trades can occur } asset bid_amount = working_bid.get_amount() * bid_claim.ask_price; asset ask_amount = working_ask.get_amount() * long_claim.ask_price; FC_ASSERT( bid_amount.unit == ask_amount.unit ); auto trade_amount = std::min(bid_amount,ask_amount); ilog( "bid amount: ${b} @ ${bp} ask amount: ${a} @ ${ap}", ("b",bid_amount)("a",ask_amount)("bp",bid_claim.ask_price)("ap",long_claim.ask_price) ); asset bid_change_amount = working_bid.get_amount(); bid_change_amount -= trade_amount * bid_claim.ask_price; ilog( "bid change.. ${c}", ("c",bid_change_amount) ); asset ask_change_amount = working_ask.get_amount(); ask_change_amount -= trade_amount * long_claim.ask_price; ilog( "ask change.. ${c}", ("c",ask_change_amount) ); if( ask_change_amount != bid_change_amount && ask_change_amount != asset(0,working_bid.unit) ) { FC_ASSERT( !"At least one of the bid or ask should be completely filled", "", ("ask_change_amount",ask_change_amount)("bid_change_amount",bid_change_amount) ); } bid_payout_address = bid_claim.pay_address; auto bid_payout_amount = bid_amount - (bid_change_amount * bid_claim.ask_price); if( bid_payout ) { *bid_payout += bid_payout_amount; } else { bid_payout = bid_payout_amount; } if( cover_payout ) { cover_payout->payoff_amount += trade_amount.get_rounded_amount(); cover_collat += (trade_amount * long_claim.ask_price)*2; } else { cover_payout = claim_by_cover_output(); cover_payout->owner = long_claim.pay_address; cover_payout->payoff_unit = trade_amount.unit; cover_payout->payoff_amount = trade_amount.get_rounded_amount(); cover_collat = (trade_amount * long_claim.ask_price)*2; } if( bid_change_amount != asset(0, working_bid.unit) ) { // TODO: accumulate fractional parts, round at the end?.... working_bid.amount = bid_change_amount.get_rounded_amount(); bid_change = working_bid; elog( "we DID NOT fill the bid..." ); } else // we have filled the bid! { elog( "we filled the bid..." ); market_trx.inputs.push_back( bid_itr->location ); market_trx.outputs.push_back( trx_output( claim_by_signature_output( bid_claim.pay_address ), bid_payout->get_rounded_asset() ) ); bid_change.reset(); bid_payout.reset(); ++bid_itr; } if( ask_change_amount != asset( 0, working_bid.unit ) ) { working_ask.amount = ask_change_amount.get_rounded_amount(); ask_change = working_ask; } else // we have filled the ask! { market_trx.inputs.push_back( ask_itr->location ); market_trx.outputs.push_back( trx_output( *cover_payout, cover_collat ) ); ask_change.reset(); cover_payout.reset(); ++ask_itr; } } else if( working_ask.claim_func == claim_by_bid ) { FC_ASSERT( !"Not Implemented" ); claim_by_bid_output ask_claim = working_ask.as<claim_by_bid_output>(); if( ask_claim.ask_price > bid_claim.ask_price ) { break; } // TODO: implement straight trades.. } else { FC_ASSERT( !"Ask must either be a claim by bid or claim by long", "", ("ask", working_ask) ); } } // while( ... ) if( ask_change && ask_itr != asks.end() ) market_trx.inputs.push_back( ask_itr->location ); if( bid_change && bid_itr != bids.rend() ) market_trx.inputs.push_back( bid_itr->location ); if( ask_change ) { ilog( "ask_change: ${ask_change}", ("ask_change",ask_change) ); market_trx.outputs.push_back( *ask_change ); } if( bid_change ) { ilog( "bid_change: ${bid_change}", ("bid_change",bid_change) ); market_trx.outputs.push_back( *bid_change ); } if( bid_payout ) { ilog( "bid_payout ${payout}", ("payout",bid_payout) ); market_trx.outputs.push_back( trx_output( claim_by_signature_output( bid_payout_address ), *bid_payout ) ); } else { wlog ( "NO BID PAYOUT" ); } if( cover_payout ) { ilog( "cover_payout ${payout}", ("payout",cover_payout) ); market_trx.outputs.push_back( trx_output( *cover_payout, cover_collat ) ); } wlog( "Market Transaction: ${trx}", ("trx", market_trx) ); if( market_trx.inputs.size() ) { FC_ASSERT( market_trx.outputs.size() ); matched.push_back(market_trx); } //ilog( "done match orders.." ); } FC_RETHROW_EXCEPTIONS( warn, "", ("quote",quote)("base",base) ) }
string pretty_block_list( const vector<block_record>& block_records, cptr client ) { if( block_records.empty() ) return "No blocks found.\n"; FC_ASSERT( client != nullptr ); std::stringstream out; out << std::left; out << std::setw( 8 ) << "HEIGHT"; out << std::setw( 20 ) << "TIMESTAMP"; out << std::setw( 32 ) << "SIGNING DELEGATE"; out << std::setw( 8 ) << "# TXS"; out << std::setw( 8 ) << "SIZE"; out << std::setw( 16 ) << "TOTAL FEES"; out << std::setw( 8 ) << "LATENCY"; out << std::setw( 15 ) << "PROCESSING TIME"; out << "\n"; out << pretty_line( 115 ); out << "\n"; auto last_block_timestamp = block_records.front().timestamp; for( const auto& block_record : block_records ) { /* Print any missed slots */ const bool descending = last_block_timestamp > block_record.timestamp; while( last_block_timestamp != block_record.timestamp ) { if( descending ) last_block_timestamp -= BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC; else last_block_timestamp += BTS_BLOCKCHAIN_BLOCK_INTERVAL_SEC; if( last_block_timestamp == block_record.timestamp ) break; out << std::setw( 8 ) << "MISSED"; out << std::setw( 20 ) << pretty_timestamp( last_block_timestamp ); const auto slot_record = client->get_chain()->get_slot_record( last_block_timestamp ); FC_ASSERT( slot_record.valid() ); const auto delegate_record = client->get_chain()->get_account_record( slot_record->block_producer_id ); FC_ASSERT( delegate_record.valid() && delegate_record->is_delegate() ); out << std::setw( 32 ) << pretty_shorten( delegate_record->name, 31 ); out << std::setw( 8 ) << "N/A"; out << std::setw( 8 ) << "N/A"; out << std::setw( 16 ) << "N/A"; out << std::setw( 8 ) << "N/A"; out << std::setw( 15 ) << "N/A"; out << '\n'; } /* Print produced block */ out << std::setw( 8 ) << block_record.block_num; out << std::setw( 20 ) << pretty_timestamp( block_record.timestamp ); const auto& delegate_name = client->blockchain_get_block_signee( block_record.block_num ); out << std::setw( 32 ); if( FILTER_OUTPUT_FOR_TESTS ) out << "[redacted]"; else out << pretty_shorten( delegate_name, 31 ); out << std::setw( 8 ) << block_record.user_transaction_ids.size(); out << std::setw( 8 ) << block_record.block_size; out << std::setw( 16 ) << client->get_chain()->to_pretty_asset( asset( block_record.total_fees ) ); if( FILTER_OUTPUT_FOR_TESTS ) { out << std::setw( 8 ) << "[redacted]"; out << std::setw( 15 ) << "[redacted]"; } else { out << std::setw( 8 ) << block_record.latency.to_seconds(); out << std::setw( 15 ) << block_record.processing_time.count() / double( 1000000 ); } out << '\n'; } return out.str(); }
/// The unit price for an asset type A is defined to be a price such that for any asset m, m*A=m static price unit_price(asset_id_type a = asset_id_type()) { return price(asset(1, a), asset(1, a)); }
inline asset operator + ( const asset& l, const asset& r ) { return asset(l) += r; }
asset operator -()const { return asset( -amount, asset_id ); }
int main(int argc, char *argv[]) { try { khGetopt options; bool help = false; int argn; std::string assetroot; std::set<std::string> checkvols; std::string progname(argv[0]); options.flagOpt("help", help); options.flagOpt("?", help); options.opt<std::string>("assetroot", assetroot); if (!options.processAll(argc, argv, argn) || help) { usage(progname); } // override the assetroot first. That way theVolumeManager will // load the correct volume definitions if (assetroot.length()) { AssetDefs::OverrideAssetRoot(assetroot); } else { assetroot = AssetDefs::AssetRoot(); } // Double check the supplied volume list if (argn == argc) { usage(progname, "No volumes specified"); } else { uint numbad = 0; while (argn < argc) { std::string vol(argv[argn]); if (theVolumeManager.GetVolumeDef(vol) == 0) { notify(NFY_WARN, "No volume named '%s' found", vol.c_str()); ++numbad; } else { checkvols.insert(vol); } ++argn; } if (numbad) { notify(NFY_FATAL, "Unable to proceed"); } } // go do the real work std::vector<std::string> found; FindSources(assetroot, checkvols, found); for (std::vector<std::string>::const_iterator aref = found.begin(); aref != found.end(); ++aref) { Asset asset(*aref); if (!asset) { notify(NFY_WARN, "Unable to load asset for %s", aref->c_str()); } else { std::vector<std::string> infiles; asset->GetInputFilenames(infiles); fprintf(stdout, "%s\n", aref->c_str()); for (std::vector<std::string>::const_iterator i = infiles.begin(); i != infiles.end(); ++i) { fprintf(stdout, "\t%s\n", i->c_str()); } } } } catch (const std::exception &e) { notify(NFY_FATAL, "%s", e.what()); } catch (...) { notify(NFY_FATAL, "Unknown error"); } return 0; }
friend asset operator + ( const asset& a, const asset& b ) { FC_ASSERT( a.asset_id == b.asset_id ); return asset( a.amount + b.amount, a.asset_id ); }
time_point_sec last_account_update; time_point_sec created; bool mined = true; account_name_type recovery_account; account_name_type reset_account = STEEM_NULL_ACCOUNT; time_point_sec last_account_recovery; uint32_t comment_count = 0; uint32_t lifetime_vote_count = 0; uint32_t post_count = 0; bool can_vote = true; util::manabar voting_manabar; asset balance = asset( 0, STEEM_SYMBOL ); ///< total liquid shares held by this account asset savings_balance = asset( 0, STEEM_SYMBOL ); ///< total liquid shares held by this account /** * SBD Deposits pay interest based upon the interest rate set by witnesses. The purpose of these * fields is to track the total (time * sbd_balance) that it is held. Then at the appointed time * interest can be paid using the following equation: * * interest = interest_rate * sbd_seconds / seconds_per_year * * Every time the sbd_balance is updated the sbd_seconds is also updated. If at least * STEEM_MIN_COMPOUNDING_INTERVAL_SECONDS has past since sbd_last_interest_payment then * interest is added to sbd_balance. * * @defgroup sbd_data sbd Balance Data */
void lop(Queue<T>& queue) { asset(queue.length > 0); queue.offset = (queue.offset + 1) % length(queue.data); queue.length--; }