refactor synchronizer#2433
Conversation
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
There was a problem hiding this comment.
Copilot reviewed 12 out of 13 changed files in this pull request and generated no comments.
Files not reviewed (1)
- test/core/network/CMakeLists.txt: Language not supported
Comments suppressed due to low confidence (3)
test/mock/core/network/synchronizer_mock.hpp:19
- [nitpick] The refactor removes the boolean-based syncByBlockInfo and syncByBlockHeader methods in favor of void-returning notification methods. Please ensure that all tests and mocks depending on the old behavior are updated to use the new interface.
MOCK_METHOD(void, onBlockAnnounceHandshake, (const BlockInfo &, const PeerId &), (override));
test/core/network/synchronizer_test.cpp:1
- The entire synchronizer test file has been removed. Confirm that synchronizer-related functionality remains adequately exercised by other tests or that this removal is intentional.
/* Entire file removed */
core/network/impl/synchronizer_impl.hpp:271
- [nitpick] The new variables attached_roots_ and detached_roots_ are central to managing block roots. Consider adding inline documentation clarifying their specific roles and how they relate to the ancestry structure.
std::set<BlockInfo> attached_roots_;
| SL_WARN(log_, "sync hung up, restarting sync"); | ||
| known_blocks_.clear(); | ||
| generations_.clear(); | ||
| attached_roots_.clear(); |
There was a problem hiding this comment.
Some random thoughts. Maybe instead of relying on timer, it would be more straightforward to implement ttl containers for these data?
There was a problem hiding this comment.
This isn't TTL, it's workaround timeout which resets synchronizer state if it hangs, which isn't normal situation.
There was a problem hiding this comment.
so, in normal situation this container (and maybe others) will grow indefinetely?
| return VisitAncestryResult::STOP; | ||
| } | ||
| if (not block.data.body.has_value()) { | ||
| auto block_info = block.data.header.value().blockInfo(); |
There was a problem hiding this comment.
Used in 3 lines below
| auto remove_executing_blocks = | ||
| auto &known = known_blocks_.at(block_info.hash); | ||
| auto make_cb = [&] { | ||
| executing_blocks_.emplace(block_info); |
There was a problem hiding this comment.
block_info is captured by reference. make_cb is invoked after block execution, which happens in separate thread if am not mistaken. Can't we end up with dangling reference to block_info ?
There was a problem hiding this comment.
make_cb returns cb to use as arg to append/execute functions, so it's called before them
| continue; | ||
| } | ||
| if (auto known = entry(known_blocks_, block.hash)) { | ||
| if (not checkExtrinsicRoot(known->data.header.value(), *block.body)) { |
There was a problem hiding this comment.
Hopefully, we cannot skip extrinsic root validation if block was not known
There was a problem hiding this comment.
loadBlocks doesn't insert body into known_blocks_,
it requires header with extrinsic root to be known.
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
There was a problem hiding this comment.
Please, provide new set of tests for new mechanism of sync.
| return; | ||
| } | ||
| return res; | ||
| fetchTasks(); |
There was a problem hiding this comment.
Seems new unknown block will just be ignored.
There was a problem hiding this comment.
Handshake contains only block hash and number, not header.
If block is not in known_blocks_, it can either be already in db (block tree) or new unknown block.
| auto cb = [WEAK_SELF, peer_id, request, reason, busy{std::move(busy)}]( | ||
| outcome::result<BlocksResponse> response_res) mutable { | ||
| WEAK_LOCK(self); | ||
| busy.reset(); |
There was a problem hiding this comment.
Should fetching be decremented here?
There was a problem hiding this comment.
It's decremented.
busy.reset() -> ~MovableFinalAction -> --fetching
| from); | ||
| if (handler) { | ||
| handler(Error::WRONG_ORDER); | ||
| if (block.body.has_value()) { |
There was a problem hiding this comment.
Should we handle body in case of header absence?
There was a problem hiding this comment.
We add body to known_blocks_ if header is already there.
If response contains both header and body, header is added to known_blocks_ first
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
| BlocksRequest request{ | ||
| .fields = BlockAttribute::HEADER | BlockAttribute::JUSTIFICATION, | ||
| .from = root.hash, | ||
| .from = known_blocks_.at(root.hash).data.header.value().parent_hash, |
There was a problem hiding this comment.
.at() potential source of exception. Does it guaranteed known_blocks_ contains root.hash? Use op[] if yes, or add check up otherwise.
There was a problem hiding this comment.
.at() was used intentionally, because std::unordered_map::operator[] doesn't assert.
known_blocks_, attached_roots_, detached_roots_, and ancestry_ are assumed to be consistent,
but assert/exception will protect from breaking that consistency.
| if (request.direction == Direction::ASCENDING) { | ||
| std::ranges::reverse(blocks); | ||
| } |
There was a problem hiding this comment.
Are you sure this should be removed?
There was a problem hiding this comment.
It was moved to other place
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Signed-off-by: turuslan <turuslan.devbox@gmail.com> # Conflicts: # core/application/impl/app_configuration_impl.cpp
Signed-off-by: turuslan <turuslan.devbox@gmail.com>
Referenced issues
Description of the Change
ancestry_not removed, eachKnownBlockstores it'sancestry_iteratorfetchGrandpaForkfunctionsyncStatepeer arg, simplifysyncStatecallbacksyncByBlockInfo/syncByBlockHeaderambigous callbackNewHeadevent in timeline to check catch up statuscheckExtrinsicRoot--max-parallel-downloadsat least 1Sync
Possible Drawbacks