BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet 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();
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)
232  (current_feed_publication_time)
233  (current_maintenance_collateralization)
234  (current_initial_collateralization)
235  (options)
236  (force_settled_volume)
237  (is_prediction_market)
238  (settlement_price)
239  (settlement_fund)
240  (individual_settlement_debt)
241  (individual_settlement_fund)
242  (asset_cer_updated)
243  (feed_cer_updated)
244  )
245 
247 
GRAPHENE_MAX_SHARE_SUPPLY
constexpr int64_t GRAPHENE_MAX_SHARE_SUPPLY(1000000000000000LL)
graphene::chain::price_feed_with_icr::initial_collateral_ratio
uint16_t initial_collateral_ratio
Definition: asset_object.hpp:234
graphene::chain::asset_bitasset_data_object::settlement_price
price settlement_price
Definition: asset_object.hpp:311
FC_CAPTURE_AND_RETHROW
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
GRAPHENE_COLLATERAL_RATIO_DENOM
#define GRAPHENE_COLLATERAL_RATIO_DENOM
Definition: config.hpp:113
uint128.hpp
graphene::chain::asset_bitasset_data_object::update_median_feeds
void update_median_feeds(time_point_sec current_time, time_point_sec next_maintenance_time)
Definition: asset_object.cpp:47
fc::to_string
std::string to_string(double)
Definition: string.cpp:73
graphene::protocol::price_feed::core_exchange_rate
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
asset_object.hpp
graphene::protocol::price
The price struct stores asset prices in the BitShares system.
Definition: asset.hpp:108
graphene::protocol::bitasset_options::maximum_force_settlement_volume
uint16_t maximum_force_settlement_volume
Definition: asset_ops.hpp:168
database.hpp
graphene::protocol::asset::scaled_precision
static share_type scaled_precision(uint8_t precision)
Definition: asset.cpp:363
FC_THROW
#define FC_THROW( ...)
Definition: exception.hpp:366
graphene::protocol::price_feed::maintenance_collateralization
price maintenance_collateralization() const
Definition: asset.cpp:342
graphene::chain::asset_bitasset_data_object::force_settled_volume
share_type force_settled_volume
This is the volume of this asset which has been force-settled this maintanence interval.
Definition: asset_object.hpp:294
graphene::chain::asset_object::amount_to_string
string amount_to_string(share_type amount) const
Convert an asset to a textual representation, i.e. "123.45".
Definition: asset_object.cpp:207
graphene::chain::asset_object
tracks the parameters of an asset
Definition: asset_object.hpp:75
graphene::protocol::bitasset_options::feed_lifetime_sec
uint32_t feed_lifetime_sec
Time before a price feed expires.
Definition: asset_ops.hpp:156
graphene::chain::asset_bitasset_data_object::current_maintenance_collateralization
price current_maintenance_collateralization
Definition: asset_object.hpp:283
graphene::protocol::price_feed::settlement_price
price settlement_price
Definition: asset.hpp:180
GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION
#define GRAPHENE_IMPLEMENT_EXTERNAL_SERIALIZATION(type)
Definition: types.hpp:86
graphene::chain::asset_object::amount_from_string
asset amount_from_string(string amount_string) const
Definition: asset_object.cpp:152
graphene::chain::asset_bitasset_data_object::max_force_settlement_volume
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...
Definition: asset_object.cpp:33
graphene::chain::asset_object::precision
uint8_t precision
Maximum number of digits after the decimal point (must be <= 12)
Definition: asset_object.hpp:133
graphene::chain::asset_dynamic_data_object
tracks the asset information that changes frequently
Definition: asset_object.hpp:56
graphene::protocol::price_feed::maximum_short_squeeze_ratio
uint16_t maximum_short_squeeze_ratio
Definition: asset.hpp:189
graphene::protocol::price::is_null
bool is_null() const
Definition: asset.cpp:229
FC_REFLECT_DERIVED_NO_TYPENAME
#define FC_REFLECT_DERIVED_NO_TYPENAME(TYPE, INHERITS, MEMBERS)
Definition: reflect.hpp:357
graphene::chain::asset_bitasset_data_object
contains properties that only apply to bitassets (market issued assets)
Definition: asset_object.hpp:255
graphene::chain::asset_bitasset_data_object::median_feed
price_feed_with_icr median_feed
This is the median of values from the currently active feeds.
Definition: asset_object.hpp:270
CHECK_AND_CALCULATE_MEDIAN_VALUE
#define CHECK_AND_CALCULATE_MEDIAN_VALUE(r, data, field_name)
graphene::chain::price_feed_with_icr::get_initial_collateralization
price get_initial_collateralization() const
Definition: asset_object.cpp:145
FC_ASSERT
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
Definition: exception.hpp:345
graphene::protocol::price_feed::maintenance_collateral_ratio
uint16_t maintenance_collateral_ratio
Definition: asset.hpp:186
graphene::chain::asset_bitasset_data_object::current_feed_publication_time
time_point_sec current_feed_publication_time
This is the publication time of the oldest feed which was factored into current_feed.
Definition: asset_object.hpp:274
graphene::chain::asset_object::amount
asset amount(share_type a) const
Helper function to get an asset object with the given amount in this asset's type.
Definition: asset_object.hpp:114
graphene::chain::asset_bitasset_data_object::feed_cer_updated
bool feed_cer_updated
Track whether core exchange rate in current feed has updated.
Definition: asset_object.hpp:376
graphene::chain::price_feed_with_icr
defines market parameters for margin positions, extended with an initial_collateral_ratio field
Definition: asset_object.hpp:229
graphene::protocol::asset
Definition: asset.hpp:31
graphene::chain::asset_bitasset_data_object::feeds
flat_map< account_id_type, pair< time_point_sec, price_feed_with_icr > > feeds
Definition: asset_object.hpp:268
fc::safe::value
T value
Definition: safe.hpp:28
graphene::chain::asset_bitasset_data_object::current_initial_collateralization
price current_initial_collateralization
Definition: asset_object.hpp:288
graphene::protocol::ratio_type
boost::rational< int32_t > ratio_type
Definition: types.hpp:150
CALCULATE_MEDIAN_VALUE
#define CALCULATE_MEDIAN_VALUE(r, data, field_name)
GRAPHENE_100_PERCENT
#define GRAPHENE_100_PERCENT
Definition: config.hpp:102
graphene
Definition: api.cpp:48
graphene::protocol::bitasset_options::extensions
extension< ext > extensions
Definition: asset_ops.hpp:173
graphene::chain::asset_bitasset_data_object::options
bitasset_options options
The tunable options for BitAssets are stored in this field.
Definition: asset_object.hpp:263
graphene::db::object
base for all database objects
Definition: object.hpp:61
raw.hpp
fc::safe
Definition: safe.hpp:26
graphene::protocol::bitasset_options::minimum_feeds
uint8_t minimum_feeds
Minimum number of unexpired feeds required to extract a median feed from.
Definition: asset_ops.hpp:158