Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 30 additions & 19 deletions src/blockchain/fork_choice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ namespace lean {
if (not blocks_.contains(block_hash)) {
return std::nullopt;
}
return blocks_.at(block_hash).slot;
return blocks_.at(block_hash).message.block.slot;
}

Slot ForkChoiceStore::getHeadSlot() const {
return blocks_.at(head_).slot;
return blocks_.at(head_).message.block.slot;
}

const Config &ForkChoiceStore::getConfig() const {
Expand All @@ -100,28 +100,35 @@ namespace lean {
// If there is no very recent safe target, then vote for the k'th ancestor
// of the head
for (auto i = 0; i < JUSTIFICATION_LOOKBACK_SLOTS; ++i) {
if (blocks_.at(target_block_root).slot > blocks_.at(safe_target_).slot) {
target_block_root = blocks_.at(target_block_root).parent_root;
if (blocks_.at(target_block_root).message.block.slot
> blocks_.at(safe_target_).message.block.slot) {
target_block_root =
blocks_.at(target_block_root).message.block.parent_root;
} else {
break;
}
}

// If the latest finalized slot is very far back, then only some slots are
// valid to justify, make sure the target is one of those
while (not isJustifiableSlot(latest_finalized_.slot,
blocks_.at(target_block_root).slot)) {
target_block_root = blocks_.at(target_block_root).parent_root;
while (not isJustifiableSlot(
latest_finalized_.slot,
blocks_.at(target_block_root).message.block.slot)) {
target_block_root =
blocks_.at(target_block_root).message.block.parent_root;
}

return Checkpoint{
.root = target_block_root,
.slot = blocks_.at(target_block_root).slot,
.slot = blocks_.at(target_block_root).message.block.slot,
};
}

AttestationData ForkChoiceStore::produceAttestationData(Slot slot) const {
Checkpoint head_checkpoint{.root = head_, .slot = blocks_.at(head_).slot};
Checkpoint head_checkpoint{
.root = head_,
.slot = blocks_.at(head_).message.block.slot,
};

auto target_checkpoint = getAttestationTarget();

Expand Down Expand Up @@ -277,8 +284,8 @@ namespace lean {
// Consistency Check
//
// Validate checkpoint slots match block slots
auto &source_block = blocks_.at(data.source.root);
auto &target_block = blocks_.at(data.target.root);
auto &source_block = blocks_.at(data.source.root).message.block;
auto &target_block = blocks_.at(data.target.root).message.block;
if (source_block.slot != data.source.slot) {
return Error::INVALID_ATTESTATION;
}
Expand Down Expand Up @@ -507,7 +514,7 @@ namespace lean {
latest_finalized_ = post_state.latest_finalized;
}

blocks_.emplace(block_hash, block);
blocks_.emplace(block_hash, signed_block_with_attestation);
states_.emplace(block_hash, std::move(post_state));

// Process block body attestations
Expand Down Expand Up @@ -681,15 +688,16 @@ namespace lean {
anchor = std::min_element(blocks_.begin(),
blocks_.end(),
[](const auto &lhs, const auto &rhs) {
return lhs.second.slot < rhs.second.slot;
return lhs.second.message.block.slot
< rhs.second.message.block.slot;
})
->first;
}

// Remember the slot of the anchor once and reuse it during the walk.
//
// This avoids repeated lookups inside the inner loop.
const auto start_slot = blocks_.at(anchor).slot;
const auto start_slot = blocks_.at(anchor).message.block.slot;

// Prepare a table that will collect voting weight for each block.
//
Expand All @@ -711,9 +719,9 @@ namespace lean {
//
// This naturally handles partial views and ongoing sync.
while (blocks_.contains(current)
and blocks_.at(current).slot > start_slot) {
and blocks_.at(current).message.block.slot > start_slot) {
++weights[current];
current = blocks_.at(current).parent_root;
current = blocks_.at(current).message.block.parent_root;
}
}

Expand All @@ -724,7 +732,7 @@ namespace lean {
for (auto &[hash, block] : blocks_) {
// 1. Structural check: skip blocks without parents (e.g., purely
// genesis/orphans)
if (block.parent_root == BlockHash{}) {
if (block.message.block.parent_root == BlockHash{}) {
continue;
}

Expand All @@ -733,7 +741,7 @@ namespace lean {
continue;
}

children_map[block.parent_root].push_back(hash);
children_map[block.message.block.parent_root].push_back(hash);
}

// Now perform the greedy walk.
Expand Down Expand Up @@ -816,7 +824,10 @@ namespace lean {
latest_justified_ = Checkpoint::from(anchor_block);
latest_finalized_ = Checkpoint::from(anchor_block);

blocks_.emplace(anchor_root, std::move(anchor_block));
blocks_.emplace(anchor_root,
SignedBlockWithAttestation{
.message = {.block = std::move(anchor_block)},
});
SL_INFO(
logger_, "Anchor block {} at slot {}", anchor_root, anchor_block.slot);
states_.emplace(anchor_root, anchor_state);
Expand Down
2 changes: 1 addition & 1 deletion src/blockchain/fork_choice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ namespace lean {
*/
class ForkChoiceStore {
public:
using Blocks = std::unordered_map<BlockHash, Block>;
using Blocks = std::unordered_map<BlockHash, SignedBlockWithAttestation>;
using SignedAttestations =
std::unordered_map<ValidatorIndex, SignedAttestation>;

Expand Down
3 changes: 1 addition & 2 deletions src/blockchain/impl/fc_block_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ namespace lean::blockchain {
if (it == blocks.end()) {
return std::nullopt;
}
// TODO(turuslan): signature
return SignedBlockWithAttestation{.message = it->second};
return it->second;
}

void FCBlockTree::import(std::vector<SignedBlockWithAttestation> blocks) {}
Expand Down
Loading
Loading