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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Build artifacts
build/
build*
cmake-build-*/

# Prerequisites
Expand Down
5 changes: 5 additions & 0 deletions include/lantern/consensus/fork_choice.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ struct lantern_fork_choice_root_index_entry {
typedef struct lantern_fork_choice {
bool initialized;
bool has_anchor;
LanternRoot anchor_root;
uint64_t anchor_slot;
LanternConfig config;
uint32_t seconds_per_slot;
uint32_t intervals_per_slot;
Expand Down Expand Up @@ -164,6 +166,7 @@ int lantern_fork_choice_restore_checkpoints(
LanternForkChoice *store,
const LanternCheckpoint *latest_justified,
const LanternCheckpoint *latest_finalized);
int lantern_fork_choice_prune_states(LanternForkChoice *store);

int lantern_fork_choice_accept_new_votes(LanternForkChoice *store);
int lantern_fork_choice_update_safe_target(LanternForkChoice *store);
Expand Down Expand Up @@ -192,6 +195,8 @@ int lantern_fork_choice_set_block_state(
const LanternState *lantern_fork_choice_block_state(
const LanternForkChoice *store,
const LanternRoot *root);
const LanternRoot *lantern_fork_choice_anchor_root(const LanternForkChoice *store);
int lantern_fork_choice_anchor_slot(const LanternForkChoice *store, uint64_t *out_slot);
const LanternCheckpoint *lantern_fork_choice_latest_justified(const LanternForkChoice *store);
const LanternCheckpoint *lantern_fork_choice_latest_finalized(const LanternForkChoice *store);
const LanternRoot *lantern_fork_choice_safe_target(const LanternForkChoice *store);
Expand Down
85 changes: 85 additions & 0 deletions src/consensus/fork_choice.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ void lantern_fork_choice_reset(LanternForkChoice *store) {

store->initialized = false;
store->has_anchor = false;
zero_root(&store->anchor_root);
store->anchor_slot = 0;
store->has_head = false;
store->has_safe_target = false;
zero_root(&store->head);
Expand Down Expand Up @@ -636,6 +638,21 @@ const LanternState *lantern_fork_choice_block_state(
return entry->has_state ? &entry->state : NULL;
}

const LanternRoot *lantern_fork_choice_anchor_root(const LanternForkChoice *store) {
if (!store || !store->has_anchor) {
return NULL;
}
return &store->anchor_root;
}

int lantern_fork_choice_anchor_slot(const LanternForkChoice *store, uint64_t *out_slot) {
if (!store || !store->has_anchor || !out_slot) {
return -1;
}
*out_slot = store->anchor_slot;
return 0;
}

int lantern_fork_choice_set_anchor(
LanternForkChoice *store,
const LanternBlock *anchor_block,
Expand Down Expand Up @@ -682,6 +699,8 @@ int lantern_fork_choice_set_anchor_with_state(
size_t previous_block_len = store->block_len;
LanternCheckpoint previous_justified = store->latest_justified;
LanternCheckpoint previous_finalized = store->latest_finalized;
LanternRoot previous_anchor_root = store->anchor_root;
uint64_t previous_anchor_slot = store->anchor_slot;
LanternRoot previous_head = store->head;
bool previous_has_head = store->has_head;
LanternRoot previous_safe_target = store->safe_target;
Expand Down Expand Up @@ -715,11 +734,15 @@ int lantern_fork_choice_set_anchor_with_state(
store->safe_target = root;
store->has_safe_target = true;
store->has_anchor = true;
store->anchor_root = root;
store->anchor_slot = anchor_block->slot;
uint64_t anchor_intervals = anchor_block->slot * store->intervals_per_slot;
store->time_intervals = anchor_intervals;
if (anchor_state && lantern_fork_choice_set_block_state(store, &root, anchor_state) != 0) {
store->latest_justified = previous_justified;
store->latest_finalized = previous_finalized;
store->anchor_root = previous_anchor_root;
store->anchor_slot = previous_anchor_slot;
store->head = previous_head;
store->has_head = previous_has_head;
store->safe_target = previous_safe_target;
Expand Down Expand Up @@ -1070,6 +1093,68 @@ int lantern_fork_choice_restore_checkpoints(
return 0;
}

int lantern_fork_choice_prune_states(LanternForkChoice *store) {
if (!store || !store->initialized || !store->has_anchor || !store->has_head) {
return -1;
}
if (store->block_len == 0 || !store->states) {
return 0;
}
if (store->state_cap < store->block_len) {
return -1;
}
if (root_is_zero(&store->latest_finalized.root)) {
return 0;
}

size_t head_index = 0;
size_t finalized_index = 0;
if (!map_lookup(store, &store->head, &head_index)
|| !map_lookup(store, &store->latest_finalized.root, &finalized_index)) {
return -1;
}
if (head_index >= store->block_len || finalized_index >= store->block_len) {
return -1;
}

uint8_t *canonical = calloc(store->block_len, sizeof(*canonical));
if (!canonical) {
return -1;
}

bool found_finalized = false;
size_t current = head_index;
while (current < store->block_len) {
canonical[current] = 1u;
if (current == finalized_index) {
found_finalized = true;
break;
}
size_t parent_index = store->blocks[current].parent_index;
if (parent_index == SIZE_MAX || parent_index >= store->block_len) {
break;
}
current = parent_index;
}

if (!found_finalized) {
free(canonical);
return -1;
}

for (size_t i = 0; i < store->block_len; ++i) {
struct lantern_fork_choice_state_entry *entry = &store->states[i];
if (!entry->has_state || canonical[i] != 0u) {
continue;
}
lantern_state_reset(&entry->state);
entry->has_state = false;
}

free(canonical);
return 0;
}

static int find_start_index(
const LanternForkChoice *store,
const LanternRoot *start_root,
Expand Down
Loading
Loading