# Speculative Availability
**What do we want to achieve?**: Start requesting availability chunks even before the candidate get backed on chain
## Pull backable candidates from prospective parachain
### Design
#### approach-1 to get backable candidates
for each active leaf call [request_backable_candidates](https://github.com/paritytech/polkadot-sdk/blob/a48307b7f0c40225aa8b6fcfecf7cedb6a41d6c2/polkadot/node/core/provisioner/src/lib.rs#L483)
- get availability cores from runtime. it will have all cores. occupied, scheduled and free.
- to have the correct core index we need to pass unmodified availability cores to the request_backable_candidates function.
- request_backable_candidates function will process all the cores including occupied cores which we are already processing in the existing logic.
- may be we can remove existing logic to process occupied core.
```Rust
let availability_cores = get_availability_cores(sender, leaf).await?;
let backable_candidates = request_backable_candidates(&availability_cores, bitfield?, &new_head, sender).await.unwrap();
```
##### Open question:
- how to find correct bitfield to pass in request_backable_candidates in approach-1
#### approach-2 to get backable candidates
for each active leaf
- fetch claim queue. and find the scheduled cores at 0th depth for parachains.
- for each parachain, get backable candidates from prospective parachain subsystem..
```Rust
let tcq = transpose_claim_queue(fetch_claim_queue(sender, leaf).await?.0);
let mut selected_candidates: HashMap<paraId, Vec<(CandidateHash, Hash)>> = HashMap::with_capacity(tcq.len());
for (para, cores_at_depth) in tcq {
if let Some(cores) = cores_at_depth.get(&0) {
let empty = HashSet::new(); // empty ancestors
let candidates = get_backable_candidates(leaf, para, empty, cores.len() as u32, sender).await.unwrap();
selected_candidates.insert(para, candidates);
}
}
let (tx, rx) = oneshot::channel();
sender.send_message(CandidateBackingMessage::GetBackableCandidates(selected_candidates, tx)).await;
let backable_candidates = rx.await?;
```
##### Open question:
- What would be the correct `ancestors` to pass in [get_backable_candidates](https://github.com/paritytech/polkadot-sdk/blob/a48307b7f0c40225aa8b6fcfecf7cedb6a41d6c2/polkadot/node/core/provisioner/src/lib.rs#L635) in approach-2.
---
Now as we have the backable candidates, we can request candidate receipt from candidate backing subsystem.
call [add_cores](https://github.com/paritytech/polkadot-sdk/blob/a48307b7f0c40225aa8b6fcfecf7cedb6a41d6c2/polkadot/node/network/availability-distribution/src/requester/mod.rs#L184) method that will start fetch task.
## Implementation detail
- to start the fetch task we need to have `FetchTaskConfig` value. currently `occupied core` provide below values for that.
- candidate hash
- group index
- relay parent (can be different from active leaf)
- erasure root
- how we can modify the code to set above values?
- we can create new structure that store all 4 values that core provides currently.
- modify the FetchTaskConfig::new function to accept this new struct instead of OccupiedCore, so that we can pass all those values for scheduled core as well.
---
---
---
## Push from Prospective Parachain to Availability distribution
**NOTE**: As Robert suggested, we will focus on pull approach only.
- Currently the availability subsystem start requesting availability chunks for the backed candidates when the subsystem receive the active leave update signal.
- In addition to that, we can also send a overseer message from prospective parachain subsystem to availability subsystem that would notify about the backable candidate and availability subsystem can start requesting availability chunk for the candidate even before the candidate gets backed on chain.

### Design
- Message coming from prospective parachain to availability distribution will contain **candidate hash** and **parachain id**.
- iterate over all the active leaves, for each leaf
- request backable candidate(candidate receipt) from candidate backing subsystem, So that we can have the erasure root, core-index.
- we can fetch the claim queue using runtime method call. that will give us the info about which cores will be assigned to the parachains for the next relay chain block.
- figure out group index using the core index.
- send request to the responsible validator group.
- try one by one validator from group untill we find the valid chunk.
- validate using erasure root.
- add to availability store only if the chunk is valid.
### Questions
- Should we request the candidate receipt from para-validators to know the erasure root?
- How/when/from where does the block author get the candidate receipt?
- If we reqestiing erasure coding root (candidate receipt) off-chain is there a possible place for attack vector return wrong data?