# Week 14
Hi everyone, Rupam here. This week I fully implemented the `block_to_light_client_header` function along with its tests from CL specs into Prysm upto Deneb in this [PR](https://github.com/prysmaticlabs/prysm/pull/14433). This is a pretty important function because its used in the implementation of `create_light_client_bootstrap`. Now you might think that `create_light_client_bootstrap` is already implemented in Prysm, how come we didn't need `block_to_light_client_header` for that before? Well, as I said in my last update, `create_light_client_bootstrap` implementation in Prysm doesn't follow the `dev` branch of CL specs as reference and follows [this](https://github.com/ethereum/consensus-specs/blob/3d235740e5f1e641d3b160c8688f26e7dc5a1894/specs/altair/light-client/full-node.md#create_light_client_bootstrap) instead. From what I realised, this makes it harder to implement the function for newer forks. I confirmed this with Etan too and he said the same.
We still had the `create_light_client_bootstrap` function implemented for the newer forks somehow and as I expected they are pretty much wrong as far as the specs go. Radek also opened a [PR](https://github.com/prysmaticlabs/prysm/pull/14434) to refactor some light client structs and functions for better readability and while reviewing his PR I noticed there are infact a lot of light client functions which do not follow the `dev` branch as reference. Although they are **NOT inherently wrong**, it is harder to update them for newer forks as all the newer forks follow the `dev` branch. So I have decided to take up the work of updating all the functions to follow the `dev` branch in my next PR.
## (If it works then don't touch it) Why Upgrade Then?
Consider the `block_to_light_client_header` implementation of Deneb from `dev` branch:
```python
def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader:
epoch = compute_epoch_at_slot(block.message.slot)
if epoch >= CAPELLA_FORK_EPOCH:
payload = block.message.body.execution_payload
execution_header = ExecutionPayloadHeader(
parent_hash=payload.parent_hash,
fee_recipient=payload.fee_recipient,
state_root=payload.state_root,
receipts_root=payload.receipts_root,
logs_bloom=payload.logs_bloom,
prev_randao=payload.prev_randao,
block_number=payload.block_number,
gas_limit=payload.gas_limit,
gas_used=payload.gas_used,
timestamp=payload.timestamp,
extra_data=payload.extra_data,
base_fee_per_gas=payload.base_fee_per_gas,
block_hash=payload.block_hash,
transactions_root=hash_tree_root(payload.transactions),
withdrawals_root=hash_tree_root(payload.withdrawals),
)
# [New in Deneb:EIP4844]
if epoch >= DENEB_FORK_EPOCH:
execution_header.blob_gas_used = payload.blob_gas_used
execution_header.excess_blob_gas = payload.excess_blob_gas
execution_branch = ExecutionBranch(
compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_GINDEX))
else:
# Note that during fork transitions, `finalized_header` may still point to earlier forks.
# While Bellatrix blocks also contain an `ExecutionPayload` (minus `withdrawals_root`),
# it was not included in the corresponding light client data. To ensure compatibility
# with legacy data going through `upgrade_lc_header_to_capella`, leave out execution data.
execution_header = ExecutionPayloadHeader()
execution_branch = ExecutionBranch()
return LightClientHeader(
beacon=BeaconBlockHeader(
slot=block.message.slot,
proposer_index=block.message.proposer_index,
parent_root=block.message.parent_root,
state_root=block.message.state_root,
body_root=hash_tree_root(block.message.body),
),
execution=execution_header,
execution_branch=execution_branch,
)
```
The `execution_header` has 2 new fields compared to Altair, `blob_gas_used` and `excess_blob_gas`. These fields are not set in our Prysm implementation making it incorrect. However there are no new changes mentioned in the `create_light_client_bootstrap` function in Deneb. Now there's the catch. The `create_light_client_bootstrap` is only defined in Altair as follows:
```python
def create_light_client_bootstrap(state: BeaconState,
block: SignedBeaconBlock) -> LightClientBootstrap:
assert compute_epoch_at_slot(state.slot) >= ALTAIR_FORK_EPOCH
assert state.slot == state.latest_block_header.slot
header = state.latest_block_header.copy()
header.state_root = hash_tree_root(state)
assert hash_tree_root(header) == hash_tree_root(block.message)
return LightClientBootstrap(
header=block_to_light_client_header(block),
current_sync_committee=state.current_sync_committee,
current_sync_committee_branch=CurrentSyncCommitteeBranch(
compute_merkle_proof(state, current_sync_committee_gindex_at_slot(state.slot))),
)
```
The `block_to_light_client_header` function is called inside which itself changes over forks. Hence it is necessary to update the `create_light_client_bootstrap` function to follow the `dev` branch even though it is not explicitly mentioned. Right now I have not looked deeper into the other functions so I don't know if they have this issue too. However updating all of them to use the `dev` branch will solve this problem before even needing to search for them. I will be opening a PR soon to address these.