# Week 8 Hi everyone, Rupam here. This week I moved forward with the next step on our roadmap for implementing light client support in Prysm, which is adding corresponding `full_node.md` changes from Capella and Deneb. This is a pretty long and complicated task and I've started with implementing a function to calculate field roots of the `BeaconBlockBody` struct in Prysm. ## Implementation The `BeaconBlockBody` struct in Prysm looks like this: ```go type BeaconBlockBody struct { version int randaoReveal [field_params.BLSSignatureLength]byte eth1Data *eth.Eth1Data graffiti [field_params.RootLength]byte proposerSlashings []*eth.ProposerSlashing attesterSlashings []*eth.AttesterSlashing attesterSlashingsElectra []*eth.AttesterSlashingElectra attestations []*eth.Attestation attestationsElectra []*eth.AttestationElectra deposits []*eth.Deposit voluntaryExits []*eth.SignedVoluntaryExit syncAggregate *eth.SyncAggregate executionPayload interfaces.ExecutionData executionPayloadHeader interfaces.ExecutionData blsToExecutionChanges []*eth.SignedBLSToExecutionChange blobKzgCommitments [][]byte } ``` Depending on the fork version, the number of fields changes like: * 8 for Phase0 * 9 for Altair * 10 for Bellatrix * 11 for Capella * 12 for Deneb * 12 for Electra The implementation of the field root calculating function should be in a way so that it can calculate field roots irrespective of the fork. The first step to make then would be this: ```go var fieldRoots [][]byte switch blockBody.version { version.Phase0: fieldRoots = make([][]byte, 8) case version.Altair: fieldRoots = make([][]byte, 9) case version.Bellatrix: fieldRoots = make([][]byte, 10) case version.Capella: fieldRoots = make([][]byte, 11) case version.Deneb: fieldRoots = make([][]byte, 12) case version.Electra: fieldRoots = make([][]byte, 12) default: return nil, fmt.Errorf("unknown block body version %s", version.String(blockBody.version)) } ``` This makes sure that the number of fields changes according to the fork. Now take into account fields like `attesterSlashingsElectra` and `attestationsElectra` which are particular to only Electra and newer forks. They can be tackled the following way: ```go if blockBody.version < version.Electra { attesterSlashingsRoot, err := ssz.SliceRoot(blockBody.attesterSlashings, field_params.MaxAttesterSlashings) if err != nil { return nil, errors.Wrap(err, "could not compute attester slashings merkleization") } fieldRoots[4] = attesterSlashingsRoot[:] } else { attesterSlashingsElectraRoot, err := ssz.SliceRoot(blockBody.attesterSlashingsElectra, field_params.MaxAttesterSlashingsElectra) if err != nil { return nil, errors.Wrap(err, "could not compute attester slashings electra merkleization") } fieldRoots[4] = attesterSlashingsElectraRoot[:] } ``` Since `attesterSlashings` will only be used for forks older than Electra and `attesterSlashingsElectra` will only be used for Electra and newer forks, we add a simple `if-else` statement which checks for the fork version and populates the `fieldRoots` list accordingly. This week I managed to do it upto the `voluntaryExits` field. Next week I will probably be wrapping this up and moving forward with the next steps. You can find my PR here: https://github.com/prysmaticlabs/prysm/pull/14278