# Block Abstraction Design
### Introduction
Currently beacon blocks are passed as a raw `*ethpb.SignedBeaconBlock` object around our codebase as of mainnet currently. However for Altair the underlying block structure will be modified to add in support for sync committees.
### Problem
Currently all functions and methods in prysm expect a raw `*ethpb.SignedBeaconBlock` object to use and process. This creates a problem for us as now we have to account for a new data type `ethpb.SignedBeaconBlockAltair`. For the merge there will be another breaking change to the underlying block type as we have to add in the execution payload.
### Potential Solutions
#### 1) Copy all Functions Manually
For each new block type, we copy all methods that are used to processing blocks manually for each new type. Main advantage would be very easy to do, as it would simply be a copy and paste for each new type. However the disadvantages are numerous
-> This makes modifying any code very brittle. You would need to modify multiple copies of the code so that it stays consistent.
-> Adds in a lot of boiler plate code that needs to be maintained.
-> Generally ugly in the code with a lot of if else conditionals.
### 2) Abstract Block With an Interface
Instead of providing a block type to each function we provide an interface. This interface will expose individual fields of a block. This allows *general* methods/functions to still be able to process different block types. The only case where we do have to specially handle would be block processing routines.
Advantages
-> Reduces any required code duplication significantly.
-> Allows multiple methods to be re-used for different types. This requires only methods which are accessing *custom* fields to expose the raw type.
Disadvantages
-> Will require a bit more work as all methods will have to be replaced with new block type.
#### Tentative Design for 2)
```go
type SignedBlockInterface interface {
Block BlockInterface
Signature [96]byte
}
type BlockInterface interface {
Slot uint64
ProposerIndex uint64
BlockBody BodyInterface
HashTreeRoot ([32]byte,error)
}
type BodyInterface interface {
Deposits []*ethpb.Deposit
Attestations []*ethpb.Attestation
HashTreeRoot ([32]byte,error)
}
```
The above interfaces are a tentative design on how a blocks functionality can be abstracted and used across the repo. A raw block object can be wrapped in a custom go struct which will conform to the interface.
There have been some initial work done in this PR :
https://github.com/prysmaticlabs/prysm/pull/8766
Some initial concerns about the approach being abandoned were to do with worries on type assertions and messing around with `interface{}`. This was given a reason for proceeding with code duplication (approach 1).
However the current approach described in 2) differs from previous efforts to conform to an interface. This has the advantage of being type safe, as any ability for the underlying object to conform to the inerface is enforced at compile time. Also it avoids the requirement of conforming to a proto objects interface. Instead we can have our own custom interface which we can use across the repo.
In order to differ the underlying types, and add in support for altair objects, we could use composition to differentiate methods introduced in altair and future forks. This will allow us to appropriately select the correct method to use for each particular underlying type without large amounts of duplication.