Skip to content

Conversation

vedant-asati
Copy link
Contributor

Motivation
This goal of this pr is to include db related changes for backfill.
Backfill issue: #7753

Description

  • removed old backfillRange db repository
  • added new backfillState repo
  • added backfillRange singleton object

WIP

@vedant-asati vedant-asati requested a review from a team as a code owner July 25, 2025 12:36
@CLAassistant
Copy link

CLAassistant commented Jul 25, 2025

CLA assistant check
All committers have signed the CLA.

@matthewkeil matthewkeil changed the base branch from unstable to backfill July 28, 2025 05:42
Copy link
Member

@matthewkeil matthewkeil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job with this!! This was pretty tricky and you did awesome! A few things need touching up but you are off to a great start 🚀

Comment on lines 12 to 13
hasBlobs: ssz.Boolean || null,
columnIndices: new ListUintNum64Type(128) || null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cannot do union types like this with our ssz library. They will need to be handled a bit differently. Here are a couple of suggestions but you can also come up with another method if you prefer.

  • During deserialization. Have a non-nullable data type EpochBackfillStateSerialized (or called something similar like EpochBackfillStateWrapper) that lives in the DB and then on deserialization check the fork for the requested epoch and nullify as necessary and return EpochBackfillState
  • Creating additional fields for the presence of a data type like needsBlobs and needsColumns or perhaps storing the forkName on the type so it's interpreted correctly by the consumer

Comment on lines 43 to 52
async _get(epoch: Epoch): Promise<EpochBackfillState | null> {
const wrappedValue = await super.get(epoch);
if (!wrappedValue) return null;
return this.unwrapEpochBackfillState(wrappedValue, epoch);
}

async _put(epoch: Epoch, value: EpochBackfillState): Promise<void> {
const wrappedValue = this.wrapEpochBackfillState(value);
await super.put(epoch, wrappedValue);
}
Copy link
Contributor Author

@vedant-asati vedant-asati Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't override get and put functions as the function signatures aren't matching with the methods in parent class due to different types: EpochBackfillState and EpochBackfillStateWrapper. So, temporarily changed name to _get and _put.
This doesn't seem to be a good practice. What are your thoughts? What else can be done?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if @nflaig has any ideas on how to do this. Like perhaps massaging the schema a bit.

Copy link
Member

@matthewkeil matthewkeil Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can sort something so that we dont need to change the type to EpochBackfillState. So not needing blobs will just get interpreted correctly by the consumer depending on the epoch.... @wemeetagain might also have a suggestion

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another idea would be to add a field for DAType and that will be a

export const enum DAType = {
    PreData = "PreData",
    Blobs = "Blobs",
    Columns = "Columns",
};

We have this exported already by our BlockInput types so can refactor that to a better place in the code for reuse.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the reason we have EpochBackfillState type which deviates from repository type?

Copy link
Contributor Author

@vedant-asati vedant-asati Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the DB, we can't store EpochBackfillState with nullable fields as it is not compatible with ssz types. We need null in certain situations, for example, to differentiate between blobs' availability and when they are not even present i.e. pre-Deneb (hasBlobs: boolean | null).
So thought to store EpochBackfillStateWrapper in DB and convert it to EpochBackfillState while putting and getting as needed.

Copy link
Member

@nflaig nflaig Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we shouldn't even implement backfill for pre-fulu and only consider data columns, this might simplify things

Edit: even if we don't support pre-fulu we might still need to handle the case if we backfill outside of the DA period (~18 days) after which we only need to backfill sync blocks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use Optional ssz type which allows the value to be nullable

Copy link
Contributor Author

@vedant-asati vedant-asati Aug 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Added OptionalType, modified the unit tests, they're successfully passing.
Please check once.

columnIndices: number[] | null;
};

export class BackfillState extends Repository<Epoch, EpochBackfillStateWrapper> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using the term "state" here could be misleading, I'd rather call this BackfillTracker or BackfillProgress

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matthewkeil please confirm

Comment on lines 43 to 52
async _get(epoch: Epoch): Promise<EpochBackfillState | null> {
const wrappedValue = await super.get(epoch);
if (!wrappedValue) return null;
return this.unwrapEpochBackfillState(wrappedValue, epoch);
}

async _put(epoch: Epoch, value: EpochBackfillState): Promise<void> {
const wrappedValue = this.wrapEpochBackfillState(value);
await super.put(epoch, wrappedValue);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the reason we have EpochBackfillState type which deviates from repository type?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants