52 _my->_irr_block_id = bsp->id;
53 _my->_irr_block_timestamp = bsp->block->timestamp;
54 }
FC_LOG_AND_DROP((
"Failed to signal irreversible block for finality status"));
60 _my->_speculative_trxs.clear();
61 }
FC_LOG_AND_DROP((
"Failed to signal block start for finality status"));
66 _my->signal_applied_transaction(trace, ptrx);
67 }
FC_LOG_AND_DROP((
"Failed to signal applied transaction for finality status"));
72 _my->signal_accepted_block(bsp);
73 }
FC_LOG_AND_DROP((
"Failed to signal accepted block for finality status"));
81 bool modified =
false;
82 if (trace->producer_block_id) {
83 block_id = *trace->producer_block_id;
104 if (!trace->receipt)
return;
108 if (trace->scheduled)
return;
111 if (!trace->producer_block_id) {
119 const auto& trx_id = trace->id;
131 .trx_expiry = ptrx->expiration(),
133 .block_id = block_id,
164 obj.block_id = block_id;
166 obj.forked_out =
false;
171 "CODE ERROR: Should not have speculative transactions that have not already"
172 "been identified prior to the block being accepted. trx id: ${trx_id}",
173 (
"trx_id", trx_id) );
184 chain::deque<
decltype(
_storage.
index().project<0>(indx.begin()))> trxs;
188 for (
const auto& trx_iter : trxs) {
197 chain::deque<
decltype(
_storage.
index().project<0>(indx.begin()))> remove_trxs;
200 auto success_iter = indx.lower_bound(boost::make_tuple(
true,
fc::time_point{}));
203 const auto success_end = indx.upper_bound(boost::make_tuple(
true, success_expiry));
204 for (; success_iter != success_end; ++success_iter) {
205 remove_trxs.push_back(
_storage.
index().project<0>(success_iter));
209 const auto fail_end = indx.upper_bound(boost::make_tuple(
false, fail_expiry));
211 for (
auto fail_iter = indx.begin(); fail_iter != fail_end; ++fail_iter) {
212 remove_trxs.push_back(
_storage.
index().project<0>(fail_iter));
215 for (
const auto& trx_iter : remove_trxs) {
218 return !remove_trxs.empty();
223 if (remaining_storage > 0) {
227 auto percentage = [](
uint64_t mem) {
229 return (mem * pcnt)/100;
233 ilog(
"Finality Status exceeded max storage (${max_storage}GB) need to free up ${storage_to_free} GB",
235 (
"storage_to_free",storage_to_free/1024/1024/1024));
236 const auto& block_indx =
_storage.
index().get<by_block_num>();
237 const auto& status_expiry_indx =
_storage.
index().get<by_status_expiry>();
238 using index_iter_type =
decltype(
_storage.
index().project<0>(block_indx.begin()));
239 chain::deque<index_iter_type> remove_trxs;
241 auto reduce_storage = [&storage_to_free,&remove_trxs,&storage=this->
_storage](
auto iter) {
242 storage_to_free -= iter->memory_size();
243 remove_trxs.push_back(storage.index().project<0>(iter));
248 auto oldest_failure_iter = status_expiry_indx.begin();
250 const auto oldest_failure_end = status_expiry_indx.lower_bound( std::make_tuple(
true,
fc::time_point{} ) );
252 while (storage_to_free > 0) {
253 auto oldest_block_iter = block_indx.upper_bound(block_upper_bound);
254 if (oldest_block_iter == block_indx.end()) {
255 FC_ASSERT( oldest_failure_iter != oldest_failure_end,
256 "CODE ERROR: can not free more storage, but still exceeding limit. "
257 "Total entries: ${total_entries}, storage memory to free: ${storage}, "
258 "entries slated for removal: ${remove_entries}",
260 (
"storage", storage_to_free)
261 (
"remove_entries", remove_trxs.size()));
262 for (; oldest_failure_iter != oldest_failure_end && storage_to_free > 0; ++oldest_failure_iter) {
263 reduce_storage(oldest_failure_iter);
266 "CODE ERROR: can not free more storage, but still exceeding limit. "
267 "Total entries: ${total_entries}, storage memory to free: ${storage}, "
268 "entries slated for removal: ${remove_entries}",
270 (
"storage", storage_to_free)
271 (
"remove_entries", remove_trxs.size()));
275 const auto block_num = oldest_block_iter->block_num();
277 earliest_block = block_num;
279 block_upper_bound = block_num;
281 for (; oldest_block_iter != block_indx.end() && oldest_block_iter->block_num() == block_num; ++oldest_block_iter) {
282 reduce_storage(oldest_block_iter);
285 for (; oldest_failure_iter != oldest_failure_upper_bound; ++oldest_failure_iter) {
286 reduce_storage(oldest_failure_iter);
291 for (
const auto& trx_iter : remove_trxs) {
296 ilog(
"Finality Status dropped ${trx_count} transactions, which were removed from block # ${block_num_start} to block # ${block_num_end}",
297 (
"trx_count", remove_trxs.size())(
"block_num_start", earliest_block)(
"block_num_end", block_upper_bound) );
300 ilog(
"Finality Status dropped ${trx_count} transactions, all were failed transactions", (
"trx_count", remove_trxs.size()) );
307 return { .head_id = _my->_head_block_id, .head_block_timestamp = _my->_head_block_timestamp, .irr_id = _my->_irr_block_id, .irr_block_timestamp = _my->_irr_block_timestamp, .earliest_tracked_block_id = _my->_earliest_tracked_block_id };
311 auto iter = _my->_storage.find(
id);
312 if (iter == _my->_storage.index().cend()) {
317 if (!iter->is_in_block()) {
322 status = iter->forked_out ?
"FORKED_OUT" :
"LOCALLY_APPLIED";
326 const auto block_num = iter->block_num();
328 status = (block_num > lib) ?
"IN_BLOCK" :
"IRREVERSIBLE";
334 return _my->_storage.memory_size();
341 auto success_iter = indx.lower_bound(boost::make_tuple(
true,
fc::time_point{}));
342 if (success_iter != indx.cend()) {
tracks the size of storage allocated to its underlying multi_index
void erase(const Key &key)
size_t memory_size() const
std::pair< typename primary_index_type::iterator, bool > insert(typename ContainerType::value_type obj)
void modify(typename primary_index_type::iterator itr, Lam lam)
const ContainerType & index() const
primary_index_type::iterator find(const Key &key)
block_timestamp(uint32_t s=0)
fc::time_point to_time_point() const
void signal_block_start(uint32_t block_num)
void signal_applied_transaction(const chain::transaction_trace_ptr &trace, const chain::packed_transaction_ptr &ptrx)
trx_finality_status_processing(uint64_t max_storage, const fc::microseconds &success_duration, const fc::microseconds &failure_duration)
void signal_accepted_block(const chain::block_state_ptr &bsp)
size_t get_storage_memory_size() const
std::optional< trx_state > get_trx_state(const chain::transaction_id_type &id) const
void signal_irreversible_block(const chain::block_state_ptr &bsp)
~trx_finality_status_processing()
chain_state get_chain_state() const
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
#define FC_LOG_AND_DROP(...)
std::shared_ptr< transaction_trace > transaction_trace_ptr
std::shared_ptr< const packed_transaction > packed_transaction_ptr
bool is_onblock(const transaction_trace &tt)
std::shared_ptr< block_state > block_state_ptr
constexpr uint32_t no_block_num
unsigned __int64 uint64_t
trx_finality_status_processing_impl(uint64_t max_storage, const fc::microseconds &success_duration, const fc::microseconds &failure_duration)
void signal_accepted_block(const chain::block_state_ptr &bsp)
void signal_applied_transaction(const chain::transaction_trace_ptr &trace, const chain::packed_transaction_ptr &ptrx)
void determine_earliest_tracked_block_id()
const uint64_t _max_storage
chain::block_timestamp_type _irr_block_timestamp
chain::block_id_type _earliest_tracked_block_id
chain::block_id_type _head_block_id
chain::block_timestamp_type _head_block_timestamp
const fc::microseconds _success_duration
fc::tracked_storage< finality_status_multi_index > _storage
chain::block_id_type _irr_block_id
bool status_expiry_of_trxs(const fc::time_point &now)
const fc::microseconds _failure_duration
uint32_t _last_proc_block_num
std::deque< chain::transaction_id_type > _speculative_trxs
tracks status related to a transaction in the blockchain
chain::block_id_type block_id
chain::block_timestamp_type block_timestamp