BitShares-Core  6.1.0
BitShares blockchain implementation and command-line interface software
asset_object.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cryptonomex, Inc., and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
26 #include <graphene/chain/hardfork.hpp>
27 
28 #include <fc/io/raw.hpp>
29 #include <fc/uint128.hpp>
30 
31 namespace graphene { namespace chain {
32 
34 {
36  return 0;
38  return current_supply + force_settled_volume;
39 
40  fc::uint128_t volume = current_supply.value;
41  volume += force_settled_volume.value;
43  volume /= GRAPHENE_100_PERCENT;
44  return static_cast<uint64_t>(volume);
45 }
46 
47 void asset_bitasset_data_object::update_median_feeds( time_point_sec current_time,
48  time_point_sec next_maintenance_time )
49 {
50  bool after_core_hardfork_1270 = ( next_maintenance_time > HARDFORK_CORE_1270_TIME ); // call price caching issue
51  current_feed_publication_time = current_time;
52  vector<std::reference_wrapper<const price_feed_with_icr>> effective_feeds;
53  // find feeds that were alive at current_time
54  for( const pair<account_id_type, pair<time_point_sec,price_feed_with_icr>>& f : feeds )
55  {
56  if( (current_time - f.second.first).to_seconds() < options.feed_lifetime_sec &&
57  f.second.first != time_point_sec() )
58  {
59  effective_feeds.emplace_back(f.second.second);
61  }
62  }
63 
64  // If there are no valid feeds, or the number available is less than the minimum to calculate a median...
65  if( effective_feeds.size() < options.minimum_feeds )
66  {
67  //... don't calculate a median, and set a null feed
68  feed_cer_updated = false; // new median cer is null, won't update asset_object anyway,
69  // set to false for better performance
70  current_feed_publication_time = current_time;
72  if( after_core_hardfork_1270 )
73  {
74  // update data derived from MCR, ICR and etc
75  refresh_cache();
76  }
77  return;
78  }
79 
80  if( 1U == effective_feeds.size() )
81  {
82  if( median_feed.core_exchange_rate != effective_feeds.front().get().core_exchange_rate )
83  feed_cer_updated = true;
84  median_feed = effective_feeds.front();
85  // Note: perhaps can defer updating current_maintenance_collateralization for better performance
86  if( after_core_hardfork_1270 )
87  {
88  const auto& exts = options.extensions.value;
89  if( exts.maintenance_collateral_ratio.valid() )
90  median_feed.maintenance_collateral_ratio = *exts.maintenance_collateral_ratio;
91  if( exts.maximum_short_squeeze_ratio.valid() )
92  median_feed.maximum_short_squeeze_ratio = *exts.maximum_short_squeeze_ratio;
93  if( exts.initial_collateral_ratio.valid() )
94  median_feed.initial_collateral_ratio = *exts.initial_collateral_ratio;
95  // update data derived from MCR, ICR and etc
96  refresh_cache();
97  }
98  return;
99  }
100 
101  // *** Begin Median Calculations ***
102  price_feed_with_icr tmp_median_feed;
103  const auto median_itr = effective_feeds.begin() + ( effective_feeds.size() / 2 );
104 #define CALCULATE_MEDIAN_VALUE(r, data, field_name) \
105  std::nth_element( effective_feeds.begin(), median_itr, effective_feeds.end(), \
106  [](const price_feed_with_icr& a, const price_feed_with_icr& b) { \
107  return a.field_name < b.field_name; \
108  }); \
109  tmp_median_feed.field_name = median_itr->get().field_name;
110 
111 #define CHECK_AND_CALCULATE_MEDIAN_VALUE(r, data, field_name) \
112  if( options.extensions.value.field_name.valid() ) { \
113  tmp_median_feed.field_name = *options.extensions.value.field_name; \
114  } else { \
115  CALCULATE_MEDIAN_VALUE(r, data, field_name); \
116  }
117 
118  BOOST_PP_SEQ_FOR_EACH( CALCULATE_MEDIAN_VALUE, ~, (settlement_price)(core_exchange_rate) )
119  BOOST_PP_SEQ_FOR_EACH( CHECK_AND_CALCULATE_MEDIAN_VALUE, ~,
120  (maintenance_collateral_ratio)(maximum_short_squeeze_ratio)(initial_collateral_ratio) )
121 #undef CHECK_AND_CALCULATE_MEDIAN_VALUE
122 #undef CALCULATE_MEDIAN_VALUE
123  // *** End Median Calculations ***
124 
125  if( median_feed.core_exchange_rate != tmp_median_feed.core_exchange_rate )
126  feed_cer_updated = true;
127  median_feed = tmp_median_feed;
128  // Note: perhaps can defer updating current_maintenance_collateralization for better performance
129  if( after_core_hardfork_1270 )
130  {
131  // update data derived from MCR, ICR and etc
132  refresh_cache();
133  }
134 }
135 
136 void asset_bitasset_data_object::refresh_cache()
137 {
141  else // if ICR is not above MCR
143 }
144 
146 {
147  if( settlement_price.is_null() )
148  return price();
149  return ~settlement_price * ratio_type( initial_collateral_ratio, GRAPHENE_COLLATERAL_RATIO_DENOM );
150 }
151 
152 asset asset_object::amount_from_string(string amount_string) const
153 { try {
154  bool negative_found = false;
155  bool decimal_found = false;
156  for( const char c : amount_string )
157  {
158  if( isdigit( c ) )
159  continue;
160 
161  if( c == '-' && !negative_found )
162  {
163  negative_found = true;
164  continue;
165  }
166 
167  if( c == '.' && !decimal_found )
168  {
169  decimal_found = true;
170  continue;
171  }
172 
173  FC_THROW( (amount_string) );
174  }
175 
176  share_type satoshis = 0;
177 
178  share_type scaled_precision = asset::scaled_precision( precision );
179 
180  const auto decimal_pos = amount_string.find( '.' );
181  const string lhs = amount_string.substr( negative_found, decimal_pos );
182  if( !lhs.empty() )
183  satoshis += fc::safe<int64_t>(std::stoll(lhs)) *= scaled_precision;
184 
185  if( decimal_found )
186  {
187  const size_t max_rhs_size = std::to_string( scaled_precision.value ).substr( 1 ).size();
188 
189  string rhs = amount_string.substr( decimal_pos + 1 );
190  FC_ASSERT( rhs.size() <= max_rhs_size );
191 
192  while( rhs.size() < max_rhs_size )
193  rhs += '0';
194 
195  if( !rhs.empty() )
196  satoshis += std::stoll( rhs );
197  }
198 
199  FC_ASSERT( satoshis <= GRAPHENE_MAX_SHARE_SUPPLY );
200 
201  if( negative_found )
202  satoshis *= -1;
203 
204  return amount(satoshis);
205 } FC_CAPTURE_AND_RETHROW( (amount_string) ) }
206 
208 {
209  share_type scaled_precision = asset::scaled_precision( precision );
210 
211  string result = fc::to_string(amount.value / scaled_precision.value);
212  auto decimals = abs( amount.value % scaled_precision.value );
213  if( decimals )
214  {
215  if( amount < 0 && result == "0" )
216  result = "-0";
217  result += "." + fc::to_string(scaled_precision.value + decimals).erase(0,1);
218  }
219  return result;
220 }
221 
222 } } // namespace graphene::chain
223 
225  (current_supply)(confidential_supply)(accumulated_fees)(accumulated_collateral_fees)(fee_pool) )
226 
228  (asset_id)
229  (feeds)
230  (median_feed)
231  (current_feed)
235  (options)
244  )
245 
247 
#define CALCULATE_MEDIAN_VALUE(r, data, field_name)
#define GRAPHENE_COLLATERAL_RATIO_DENOM
Definition: config.hpp:113
asset_id_type asset_id
The asset this object belong to.
uint16_t maximum_short_squeeze_ratio
Definition: asset.hpp:189
contains properties that only apply to bitassets (market issued assets)
share_type force_settled_volume
This is the volume of this asset which has been force-settled this maintanence interval.
boost::rational< int32_t > ratio_type
Definition: types.hpp:150
Definition: api.cpp:48
#define FC_REFLECT_DERIVED_NO_TYPENAME(TYPE, INHERITS, MEMBERS)
Definition: reflect.hpp:357
share_type max_force_settlement_volume(share_type current_supply) const
Calculate the maximum force settlement volume per maintenance interval, given the current share suppl...
defines market parameters for margin positions, extended with an initial_collateral_ratio field ...
#define CHECK_AND_CALCULATE_MEDIAN_VALUE(r, data, field_name)
bool is_prediction_market
True if this asset implements a Prediction Market.
void update_median_feeds(time_point_sec current_time, time_point_sec next_maintenance_time)
static share_type scaled_precision(uint8_t precision)
Definition: asset.cpp:363
#define FC_THROW( ...)
Definition: exception.hpp:366
bool feed_cer_updated
Track whether core exchange rate in current feed has updated.
uint16_t maintenance_collateral_ratio
Definition: asset.hpp:186
The price struct stores asset prices in the BitShares system.
Definition: asset.hpp:108
#define GRAPHENE_100_PERCENT
Definition: config.hpp:102
uint8_t minimum_feeds
Minimum number of unexpired feeds required to extract a median feed from.
Definition: asset_ops.hpp:158
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
price_feed_with_icr current_feed
This is the currently active price feed, calculated from median_feed and other parameters.
tracks the asset information that changes frequentlyBecause the asset_object is very large it doesn&#39;t...
string amount_to_string(share_type amount) const
Convert an asset to a textual representation, i.e. "123.45".
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:86
uint32_t feed_lifetime_sec
Time before a price feed expires.
Definition: asset_ops.hpp:156
share_type individual_settlement_fund
Amount of collateral which is available for force settlement due to individual settlements.
price maintenance_collateralization() const
Definition: asset.cpp:342
tracks the parameters of an assetAll assets have a globally unique symbol name that controls how they...
std::string to_string(double)
Definition: string.cpp:73
bitasset_options options
The tunable options for BitAssets are stored in this field.
constexpr int64_t GRAPHENE_MAX_SHARE_SUPPLY(1000000000000000LL)
base for all database objects
Definition: object.hpp:61
flat_map< account_id_type, pair< time_point_sec, price_feed_with_icr > > feeds
bool is_null() const
Definition: asset.cpp:229
bool asset_cer_updated
Track whether core_exchange_rate in corresponding asset_object has updated.
time_point_sec current_feed_publication_time
This is the publication time of the oldest feed which was factored into current_feed.
share_type settlement_fund
Amount of collateral which is available for force settlement due to global settlement.
T value
Definition: safe.hpp:22
price_feed_with_icr median_feed
This is the median of values from the currently active feeds.
asset amount_from_string(string amount_string) const
price core_exchange_rate
Price at which automatically exchanging this asset for CORE from fee pool occurs (used for paying fee...
Definition: asset.hpp:183