Dev Update #7

Hi,
In my last update, our beacon-APIs endpoints merged; you can check them out in the API browser. Since then, the priority has been on the following three things:

  • I got my guide merged on how to run a beacon node on Lighthouse.
  • Worked my way through the Rust book
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
    .
  • Had the kickoff meeting for the endpoints implementation into Lighthouse, with NC and sproul.

We decided to start with the implementation of sync_committee_rewardsbecause it is the most straightforward API. The implementation can be roughly divided into the following parts:

  1. API handler - compute_sync_committe_rewards
  2. Load data using chain from BeaconChain<T>
    2.1 Load a block with chain.get_blinded_block(block_root)
    2.2 Load a state with chain.get_state(state_root, None)
    2.3 Convert a slot into the canonical block root from that slot with block_id.root(&chain)
  3. Compute rewards by calling functions from consensus/state_processing

Next, we will examine how these three parts could be implemented. The following sections are the first draft and could be changed massively in the next dev updates.

API handler

pub fn compute_sync_committee_rewards<T: BeaconChainTypes>(
    chain: &BeaconChain<T>,
    state: BeaconState<T::EthSpec>,
    block: SignedBlindedBeaconBlock<T::EthSpec>,
) -> Result<SyncCommitteeRewards, Error> {

    let get_lighthouse_sync_committee_rewards = warp::path("lighthouse")
    .and(warp::path("analysis"))
    .and(warp::path("sync_committee_rewards"))
    .and(warp::query::<eth2::lighthouse::SyncCommitteeRewardsQuery>())
    .and(warp::path::end())
    .and(chain_filter.clone())
    .and(log_filter.clone())
    .and_then(|query, chain, log| {
        blocking_json_task(move || sync_committee_rewards::get_sync_committee_rewards(query, chain, log))
    });
}

Load data

This section consists of three subsections, to load a block, to load a state, and to convert a slot into the canonical block root.

Load a block

pub fn get_blinded_block(
    &self,
    block_root: &Hash256,
) -> Result<Option<SignedBlindedBeaconBlock<T::EthSpec>>, Error> {
    Ok(self.store.get_blinded_block(block_root)?)
}

Load a slot

pub fn get_state(
    &self,
    state_root: &Hash256,
    slot: Option<Slot>,
) -> Result<Option<BeaconState<T::EthSpec>>, Error> {
    Ok(self.store.get_state(state_root, slot)?)
}

Convert a slot into the canonical block root

// TBD

Compute rewards

pub fn compute_sync_aggregate_rewards<T: EthSpec>(
    state: &BeaconState<T>,
    spec: &ChainSpec,
) -> Result<(u64, u64), BlockProcessingError> {
    let total_active_balance = state.get_total_active_balance()?;
    let total_active_increments =
        total_active_balance.safe_div(spec.effective_balance_increment)?;
    let total_base_rewards = BaseRewardPerIncrement::new(total_active_balance, spec)?
        .as_u64()
        .safe_mul(total_active_increments)?;
    let max_participant_rewards = total_base_rewards
        .safe_mul(SYNC_REWARD_WEIGHT)?
        .safe_div(WEIGHT_DENOMINATOR)?
        .safe_div(T::slots_per_epoch())?;
    let participant_reward = max_participant_rewards.safe_div(T::SyncCommitteeSize::to_u64())?;
    let proposer_reward = participant_reward
        .safe_mul(PROPOSER_WEIGHT)?
        .safe_div(WEIGHT_DENOMINATOR.safe_sub(PROPOSER_WEIGHT)?)?;
    Ok((participant_reward, proposer_reward))
}

Next steps

Sync_committee_rewards includes some back and forth with sproul to fully get the implementation right. Once approved, we can move on to either the block_rewardsor attestation_rewards.