Skip to content

Commit

Permalink
justification queue (#1904)
Browse files Browse the repository at this point in the history
Signed-off-by: turuslan <[email protected]>
  • Loading branch information
turuslan authored Dec 29, 2023
1 parent db22581 commit fabe411
Show file tree
Hide file tree
Showing 32 changed files with 745 additions and 214 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

cmake_minimum_required(VERSION 3.12)

if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.27")
cmake_policy(SET CMP0144 NEW)
endif()

find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
Expand Down
3 changes: 0 additions & 3 deletions cmake/functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ function(addtest_part test_name)
target_sources(${test_name} PUBLIC
${ARGN}
)
target_link_libraries(${test_name}
GTest::gtest
)
endfunction()

# conditionally applies flag. If flag is supported by current compiler, it will be added to compile options.
Expand Down
1 change: 1 addition & 0 deletions core/consensus/grandpa/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_library(grandpa
impl/vote_tracker_impl.cpp
impl/vote_crypto_provider_impl.cpp
impl/grandpa_impl.cpp
impl/verified_justification_queue.cpp
impl/voting_round_impl.cpp
impl/votes_cache.cpp
impl/environment_impl.cpp
Expand Down
9 changes: 9 additions & 0 deletions core/consensus/grandpa/authority_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ namespace kagome::consensus::grandpa {
const primitives::BlockInfo &block,
IsBlockFinalized finalized) const = 0;

/// Find previous scheduled change with justification
using ScheduledParentResult =
outcome::result<std::pair<primitives::BlockInfo, AuthoritySetId>>;
virtual ScheduledParentResult scheduledParent(
primitives::BlockInfo block) const = 0;

/// Find possible scheduled changes with justification
virtual std::vector<primitives::BlockInfo> possibleScheduled() const = 0;

/**
* Warp synced to `block` with `authorities`.
*/
Expand Down
28 changes: 28 additions & 0 deletions core/consensus/grandpa/i_verified_justification_queue.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright Quadrivium LLC
* All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <cstdint>

namespace kagome::consensus::grandpa {
struct GrandpaJustification;

using AuthoritySetId = uint64_t;

/// Finalize scheduled change after finalizing it's parent.
class IVerifiedJustificationQueue {
public:
virtual ~IVerifiedJustificationQueue() = default;

/// Add verified justification
virtual void addVerified(AuthoritySetId set,
GrandpaJustification justification) = 0;

/// Warp sync
virtual void warp() = 0;
};
} // namespace kagome::consensus::grandpa
67 changes: 67 additions & 0 deletions core/consensus/grandpa/impl/authority_manager_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,71 @@ namespace kagome::consensus::grandpa {
}
indexer_.put(block, {value, std::nullopt}, true);
}

AuthorityManager::ScheduledParentResult AuthorityManagerImpl::scheduledParent(
primitives::BlockInfo block) const {
std::unique_lock lock{mutex_};
OUTCOME_TRY(authoritiesOutcome(block, true));
auto skip = true;
while (true) {
auto r = indexer_.get(block);
if (not r) {
break;
}
if (not skip and not r->inherit) {
if (not r->value) {
break;
}
if (r->value->state) {
break;
}
if (not r->value->forced_target) {
return std::make_pair(block, r->value->next_set_id - 1);
}
} else {
skip = false;
}
if (not r->prev) {
break;
}
block = *r->prev;
}
return AuthorityManagerError::NOT_FOUND;
}

std::vector<primitives::BlockInfo> AuthorityManagerImpl::possibleScheduled()
const {
std::unique_lock lock{mutex_};
for (auto &hash : block_tree_->getLeaves()) {
if (auto r = block_tree_->getBlockHeader(hash)) {
auto &block = r.value();
std::ignore = authoritiesOutcome({block.number, hash}, true);
}
}
std::vector<primitives::BlockInfo> possible;
auto finalized = block_tree_->getLastFinalized();
auto last = finalized;
auto r = indexer_.get(last);
if (not r) {
return possible;
}
if (r->inherit) {
if (not r->prev) {
return possible;
}
last = *r->prev;
r = indexer_.get(last);
if (not r) {
return possible;
}
}
for (auto it = indexer_.map_.upper_bound(finalized);
it != indexer_.map_.end();
++it) {
if (not it->second.inherit and it->second.prev == last) {
possible.emplace_back(it->first);
}
}
return possible;
}
} // namespace kagome::consensus::grandpa
5 changes: 5 additions & 0 deletions core/consensus/grandpa/impl/authority_manager_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ namespace kagome::consensus::grandpa {
const primitives::BlockInfo &target_block,
IsBlockFinalized finalized) const override;

ScheduledParentResult scheduledParent(
primitives::BlockInfo block) const override;

std::vector<primitives::BlockInfo> possibleScheduled() const override;

void warp(const primitives::BlockInfo &block,
const primitives::BlockHeader &header,
const AuthoritySet &authorities) override;
Expand Down
10 changes: 4 additions & 6 deletions core/consensus/grandpa/impl/environment_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "blockchain/block_tree.hpp"
#include "consensus/grandpa/authority_manager.hpp"
#include "consensus/grandpa/has_authority_set_change.hpp"
#include "consensus/grandpa/i_verified_justification_queue.hpp"
#include "consensus/grandpa/justification_observer.hpp"
#include "consensus/grandpa/movable_round_state.hpp"
#include "consensus/grandpa/voting_round_error.hpp"
Expand All @@ -39,6 +40,7 @@ namespace kagome::consensus::grandpa {
std::shared_ptr<network::GrandpaTransmitter> transmitter,
std::shared_ptr<parachain::IApprovedAncestor> approved_ancestor,
LazySPtr<JustificationObserver> justification_observer,
std::shared_ptr<IVerifiedJustificationQueue> verified_justification_queue,
std::shared_ptr<dispute::DisputeCoordinator> dispute_coordinator,
std::shared_ptr<runtime::ParachainHost> parachain_api,
std::shared_ptr<parachain::BackingStore> backing_store,
Expand All @@ -50,6 +52,7 @@ namespace kagome::consensus::grandpa {
transmitter_{std::move(transmitter)},
approved_ancestor_(std::move(approved_ancestor)),
justification_observer_(std::move(justification_observer)),
verified_justification_queue_(std::move(verified_justification_queue)),
dispute_coordinator_(std::move(dispute_coordinator)),
parachain_api_(std::move(parachain_api)),
backing_store_(std::move(backing_store)),
Expand Down Expand Up @@ -393,12 +396,7 @@ namespace kagome::consensus::grandpa {

outcome::result<void> EnvironmentImpl::finalize(
VoterSetId id, const GrandpaJustification &grandpa_justification) {
primitives::Justification justification;
OUTCOME_TRY(enc, scale::encode(grandpa_justification));
justification.data.put(enc);
OUTCOME_TRY(block_tree_->finalize(grandpa_justification.block_info.hash,
justification));

verified_justification_queue_->addVerified(id, grandpa_justification);
return outcome::success();
}

Expand Down
4 changes: 4 additions & 0 deletions core/consensus/grandpa/impl/environment_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ namespace kagome::parachain {
}

namespace kagome::consensus::grandpa {
class IVerifiedJustificationQueue;

class EnvironmentImpl : public Environment,
public std::enable_shared_from_this<EnvironmentImpl> {
Expand All @@ -51,6 +52,8 @@ namespace kagome::consensus::grandpa {
std::shared_ptr<network::GrandpaTransmitter> transmitter,
std::shared_ptr<parachain::IApprovedAncestor> approved_ancestor,
LazySPtr<JustificationObserver> justification_observer,
std::shared_ptr<IVerifiedJustificationQueue>
verified_justification_queue,
std::shared_ptr<dispute::DisputeCoordinator> dispute_coordinator,
std::shared_ptr<runtime::ParachainHost> parachain_api,
std::shared_ptr<parachain::BackingStore> backing_store,
Expand Down Expand Up @@ -124,6 +127,7 @@ namespace kagome::consensus::grandpa {
std::shared_ptr<network::GrandpaTransmitter> transmitter_;
std::shared_ptr<parachain::IApprovedAncestor> approved_ancestor_;
LazySPtr<JustificationObserver> justification_observer_;
std::shared_ptr<IVerifiedJustificationQueue> verified_justification_queue_;
std::shared_ptr<dispute::DisputeCoordinator> dispute_coordinator_;
std::shared_ptr<runtime::ParachainHost> parachain_api_;
std::shared_ptr<parachain::BackingStore> backing_store_;
Expand Down
51 changes: 30 additions & 21 deletions core/consensus/grandpa/impl/grandpa_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,16 +1314,9 @@ namespace kagome::consensus::grandpa {
});
}

void GrandpaImpl::verifyJustification(
outcome::result<void> GrandpaImpl::verifyJustification(
const GrandpaJustification &justification,
const AuthoritySet &authorities,
std::shared_ptr<std::promise<outcome::result<void>>> promise_res) {
REINVOKE(*internal_thread_context_,
verifyJustification,
justification,
authorities,
std::move(promise_res));

const AuthoritySet &authorities) {
auto voters = VoterSet::make(authorities).value();
MovableRoundState state;
state.round_number = justification.round_number;
Expand All @@ -1340,8 +1333,7 @@ namespace kagome::consensus::grandpa {
primitives::BlockInfo{}, voters, environment_),
scheduler_,
state);
promise_res->set_value(
round->validatePrecommitJustification(justification));
return round->validatePrecommitJustification(justification);
}

void GrandpaImpl::applyJustification(
Expand All @@ -1351,7 +1343,33 @@ namespace kagome::consensus::grandpa {
applyJustification,
justification,
std::move(callback));
auto round_opt = selectRound(justification.round_number, std::nullopt);
auto authorities_opt = authority_manager_->authorities(
justification.block_info, IsBlockFinalized{false});
if (not authorities_opt) {
callbackCall(std::move(callback),
VotingRoundError::NO_KNOWN_AUTHORITIES_FOR_BLOCK);
return;
}
auto &authority_set = authorities_opt.value();
auto round_opt = selectRound(justification.round_number, authority_set->id);
if (not round_opt
and std::pair{authority_set->id, justification.round_number}
< std::pair{current_round_->voterSetId(),
current_round_->roundNumber()}) {
auto r = verifyJustification(justification, *authority_set);
if (r.has_error()) {
SL_WARN(logger_,
"verify justification block {} set {} round {}: {}",
justification.block_info.number,
authority_set->id,
justification.round_number,
r.error());
} else {
r = environment_->finalize(authority_set->id, justification);
}
callbackCall(std::move(callback), std::move(r));
return;
}
std::shared_ptr<VotingRound> round;
bool need_to_make_round_current = false;
if (round_opt.has_value()) {
Expand All @@ -1365,15 +1383,6 @@ namespace kagome::consensus::grandpa {
return;
}

auto authorities_opt = authority_manager_->authorities(
justification.block_info, IsBlockFinalized{false});
if (!authorities_opt) {
callbackCall(std::move(callback),
VotingRoundError::NO_KNOWN_AUTHORITIES_FOR_BLOCK);
return;
}
auto &authority_set = authorities_opt.value();

auto prev_round_opt =
selectRound(justification.round_number - 1, authority_set->id);

Expand Down
6 changes: 2 additions & 4 deletions core/consensus/grandpa/impl/grandpa_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,9 @@ namespace kagome::consensus::grandpa {
/**
* Check justification votes signatures, ancestry and threshold.
*/
void verifyJustification(
outcome::result<void> verifyJustification(
const GrandpaJustification &justification,
const AuthoritySet &authorities,
std::shared_ptr<std::promise<outcome::result<void>>> promise_res)
override;
const AuthoritySet &authorities) override;

/**
* Selects round that corresponds for justification, checks justification,
Expand Down
Loading

0 comments on commit fabe411

Please sign in to comment.