async fn verify_payload(
        &self,
        ctx: &ctx::Ctx,
        block_number: validator::BlockNumber,
        payload: &validator::Payload,
    ) -> ctx::Result<()> {
        let mut payloads = sync::lock(ctx, &self.block_payloads).await?.into_async();
        if let Some(payloads) = &mut *payloads {
            let block = to_fetched_block(block_number, payload).context("to_fetched_block")?;
            let n = block.number;
            payloads.send(block).await.context("payload_queue.send()")?;
            // Wait for the block to be processed, without waiting for it to be stored.
            // TODO(BFT-459): this is not ideal, because we don't check here whether the
            // processed block is the same as `payload`. It will work correctly
            // with the current implementation of EN, but we should make it more
            // precise when block reverting support is implemented.
            wait_for_local_block(ctx, &payloads.sync_state, n).await?;
        } else {
            let want = self.pool.wait_for_payload(ctx, block_number).await?;
            let got = Payload::decode(payload).context("Payload::decode(got)")?;
            if got != want {
                return Err(
                    anyhow::format_err!("unexpected payload: got {got:?} want {want:?}").into(),
                );
            }
        }
        Ok(())
    }
Verify that `payload` is a correct proposal for the block `block_number`.
* for the main node it checks whether the same block is already present in storage.
* for the EN validator
* if the block with this number was already applied, it checks that it was the
same block. It should always be true, because main node is the only proposer and
to propose a different block a hard fork is needed.
* otherwise, EN attempts to apply the received block. If the block was incorrect
the statekeeper is expected to crash the whole EN. Otherwise OK is returned.
core/node/consensus/src/storage/store.rs