19 FC_ASSERT(_head,
"cannot pop an empty fork database");
20 auto prev = _head->prev.lock();
21 FC_ASSERT(prev,
"popping head block would leave fork DB empty");
27 auto item = std::make_shared<fork_item>(std::move(b));
38 auto item = std::make_shared<fork_item>(b);
43 catch (
const unlinkable_block_exception&)
45 wlog(
"Pushing block to fork database that failed to link: ${id}, ${num}", (
"id", b.
id())(
"num", b.
block_num()));
46 wlog(
"Head: ${num}, ${id}", (
"num", _head->data.block_num())(
"id", _head->data.id()));
48 _unlinked_index.insert(item);
53 void fork_database::_push_block(
const item_ptr& item)
57 FC_ASSERT(item->num > std::max<int64_t>(0, int64_t(_head->num) - (_max_size)),
58 "attempting to push a block that is too old",
59 (
"item->num", item->num)(
"head", _head->num)(
"max_size", _max_size));
64 auto& index = _index.get<block_id>();
65 auto itr = index.find(item->previous_id());
66 SCORUM_ASSERT(itr != index.end(), unlinkable_block_exception,
"block does not link to known chain");
67 FC_ASSERT(!(*itr)->invalid);
72 if (!_head || item->num > _head->num)
82 void fork_database::_push_next(
const item_ptr& new_item)
84 auto& prev_idx = _unlinked_index.get<by_previous>();
86 auto itr = prev_idx.find(new_item->id);
87 while (itr != prev_idx.end())
93 itr = prev_idx.find(new_item->id);
104 auto& by_num_idx = _index.get<block_num>();
105 auto itr = by_num_idx.begin();
106 while (itr != by_num_idx.end())
108 if ((*itr)->num < std::max(int64_t(0), int64_t(_head->num) - _max_size))
109 by_num_idx.erase(itr);
112 itr = by_num_idx.begin();
116 auto& by_num_idx = _unlinked_index.get<block_num>();
117 auto itr = by_num_idx.begin();
118 while (itr != by_num_idx.end())
120 if ((*itr)->num < std::max(int64_t(0), int64_t(_head->num) - _max_size))
121 by_num_idx.erase(itr);
124 itr = by_num_idx.begin();
131 auto& index = _index.get<block_id>();
132 auto itr = index.find(
id);
133 if (itr != index.end())
135 auto& unlinked_index = _unlinked_index.get<block_id>();
136 auto unlinked_itr = unlinked_index.find(
id);
137 return unlinked_itr != unlinked_index.end();
142 auto& index = _index.get<block_id>();
143 auto itr = index.find(
id);
144 if (itr != index.end())
146 auto& unlinked_index = _unlinked_index.get<block_id>();
147 auto unlinked_itr = unlinked_index.find(
id);
148 if (unlinked_itr != unlinked_index.end())
149 return *unlinked_itr;
157 std::vector<item_ptr>
result;
158 auto itr = _index.get<block_num>().find(num);
159 while (itr != _index.get<block_num>().end())
161 if ((*itr)->num == num)
172 std::pair<fork_database::branch_type, fork_database::branch_type>
179 std::pair<branch_type, branch_type>
result;
180 auto first_branch_itr = _index.get<block_id>().find(first);
181 FC_ASSERT(first_branch_itr != _index.get<block_id>().end());
182 auto first_branch = *first_branch_itr;
184 auto second_branch_itr = _index.get<block_id>().find(second);
185 FC_ASSERT(second_branch_itr != _index.get<block_id>().end());
186 auto second_branch = *second_branch_itr;
188 while (first_branch->data.block_num() > second_branch->data.block_num())
190 result.first.push_back(first_branch);
191 first_branch = first_branch->prev.lock();
192 FC_ASSERT(first_branch);
194 while (second_branch->data.block_num() > first_branch->data.block_num())
196 result.second.push_back(second_branch);
197 second_branch = second_branch->prev.lock();
198 FC_ASSERT(second_branch);
200 while (first_branch->data.previous != second_branch->data.previous)
202 result.first.push_back(first_branch);
203 result.second.push_back(second_branch);
204 first_branch = first_branch->prev.lock();
205 FC_ASSERT(first_branch);
206 second_branch = second_branch->prev.lock();
207 FC_ASSERT(second_branch);
209 if (first_branch && second_branch)
211 result.first.push_back(first_branch);
212 result.second.push_back(second_branch);
216 FC_CAPTURE_AND_RETHROW((first)(second))
221 std::shared_ptr<fork_item> next =
head();
222 if (block_num > next->num)
223 return std::shared_ptr<fork_item>();
225 while (next.get() !=
nullptr && next->num > block_num)
226 next = next->prev.lock();
233 if (blocks.size() == 1)
235 if (blocks.size() == 0)
236 return std::shared_ptr<fork_item>();
247 _index.get<block_id>().erase(
id);
std::vector< item_ptr > fetch_block_by_number(uint32_t n) const
std::shared_ptr< fork_item > push_block(const signed_block &b)
std::shared_ptr< fork_item > fetch_block(const block_id_type &id) const
std::shared_ptr< fork_item > fetch_block_on_main_branch_by_number(uint32_t block_num) const
void set_max_size(uint32_t s)
bool is_known_block(const block_id_type &id) const
std::pair< branch_type, branch_type > fetch_branch_from(block_id_type first, block_id_type second) const
void remove(block_id_type b)
void set_head(std::shared_ptr< fork_item > h)
void start_block(signed_block b)
std::shared_ptr< fork_item > head() const
std::shared_ptr< fork_item > walk_main_branch_to_num(uint32_t block_num) const
#define SCORUM_ASSERT(expr, exc_type, FORMAT,...)
std::shared_ptr< fork_item > item_ptr
fc::ripemd160 block_id_type