Skip to content

Commit 8228ce7

Browse files
committed
feat: remove stale services from PI and correctly identify guarantee reporters across validator set rotations.
1 parent ae3d6cd commit 8228ce7

File tree

2 files changed

+45
-12
lines changed

2 files changed

+45
-12
lines changed

jam/state/transitions/accumulation/accumulation.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -740,12 +740,15 @@ def sort_fn(comm: Commitment):
740740
services.append(service_id)
741741

742742
pi = state.pi
743-
for s in services:
744-
pi_service = pi.services
745-
if s not in pi.services:
746-
pi.services[s] = ServiceStat.empty()
747-
748-
pi.services = pi_service
743+
744+
# Cleanup removed services from Pi
745+
pi_services_to_remove = []
746+
for s_id in pi.services.keys():
747+
if s_id not in state.delta:
748+
pi_services_to_remove.append(s_id)
749+
750+
for s_id in pi_services_to_remove:
751+
del pi.services[s_id]
749752

750753
state.pi = pi
751754

jam/state/transitions/statistics/statistics.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88

99
from jam.types.state.pi import ServiceStat
10-
from jam.utils.constants import EPOCH_LENGTH, SEGMENT_SIZE
10+
from jam.utils.constants import EPOCH_LENGTH, SEGMENT_SIZE, ROTATION_PERIOD
11+
from jam.state.transitions.report.guarantee_assignment import assign_fn
1112
from tsrkit_types import Uint
1213

1314

@@ -56,11 +57,40 @@ def transition(
5657
for preimage in block.extrinsic.preimages:
5758
pi_curr[author_index].pre_images_size += len(preimage.blob)
5859

59-
reporter_set = set([
60-
sig.validator_index
61-
for guarantee in block.extrinsic.guarantees
62-
for sig in guarantee.signatures
63-
])
60+
curr_mapping, _, prev_mapping, _ = assign_fn(state)
61+
62+
# Build map for remapping keys to current indices
63+
kappa_lookup = {v.ed25519: i for i, v in enumerate(state.kappa)}
64+
65+
reporter_set = set()
66+
for guarantee in block.extrinsic.guarantees:
67+
report_slot = guarantee.slot
68+
block_slot = block.header.slot
69+
70+
# Determine which mapping to use based on rotation
71+
is_current_rotation = (report_slot // ROTATION_PERIOD) == (block_slot // ROTATION_PERIOD)
72+
73+
mapping = curr_mapping if is_current_rotation else prev_mapping
74+
75+
assigned_validators = mapping.get(guarantee.report.core_index, [])
76+
77+
# Create a set for O(1) lookup of assigned validator indices
78+
assigned_validator_indices = {v for v in assigned_validators}
79+
80+
for sig in guarantee.signatures:
81+
# Check 1: Validator must be assigned to this core
82+
if sig.validator_index in assigned_validator_indices:
83+
# If prior rotation (epoch change), map lambda index to kappa index
84+
if not is_current_rotation and (report_slot // EPOCH_LENGTH) != (block_slot // EPOCH_LENGTH):
85+
# Get pubkey from Lambda (priot validator set)
86+
pubkey = state.lambda_[sig.validator_index].ed25519
87+
# Add to reporter set if the prior validaor still exists in Kappa
88+
# Find index in Kappa
89+
if pubkey in kappa_lookup:
90+
reporter_set.add(kappa_lookup[pubkey])
91+
else:
92+
reporter_set.add(sig.validator_index)
93+
6494
for validator_index in reporter_set:
6595
pi_curr[validator_index].guarantees += 1
6696

0 commit comments

Comments
 (0)