-
-
Notifications
You must be signed in to change notification settings - Fork 457
refactor: reorder payload status constants #9176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: unstable
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,9 +41,9 @@ export enum ExecutionStatus { | |
| * Spec: gloas/fork-choice.md#constants | ||
| */ | ||
| export enum PayloadStatus { | ||
| PENDING = 0, | ||
| EMPTY = 1, | ||
| FULL = 2, | ||
| EMPTY = 0, | ||
| FULL = 1, | ||
| PENDING = 2, | ||
|
nflaig marked this conversation as resolved.
Comment on lines
+44
to
+46
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tend to prefer PascalCase for these but not a hill I'm willing to die on
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these are spec constants, I'd rather keep them as is we just defined them as a single enum |
||
| } | ||
|
nflaig marked this conversation as resolved.
|
||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,11 +30,12 @@ const ZERO_HASH_HEX = toRootHex(Buffer.alloc(32, 0)); | |
| /** Pre-Gloas: single element, FULL index (for backward compatibility) */ | ||
| type PreGloasVariantIndex = number; | ||
| /** | ||
| * Post-Gloas: array length is 2 or 3 | ||
| * - Length 2: [PENDING_INDEX, EMPTY_INDEX] when payload hasn't arrived yet | ||
| * - Length 3: [PENDING_INDEX, EMPTY_INDEX, FULL_INDEX] when payload has arrived | ||
| * Post-Gloas: always length 3, indexed by PayloadStatus enum value | ||
| * - [EMPTY_INDEX, FULL_INDEX | undefined, PENDING_INDEX] | ||
| * - PayloadStatus.EMPTY=0, PayloadStatus.FULL=1, PayloadStatus.PENDING=2 | ||
| * - FULL starts as undefined until execution payload arrives | ||
| */ | ||
| type GloasVariantIndices = [number, number] | [number, number, number]; | ||
| type GloasVariantIndices = [number, number | undefined, number]; | ||
| type VariantIndices = PreGloasVariantIndex | GloasVariantIndices; | ||
|
|
||
| export class ProtoArray { | ||
|
|
@@ -49,10 +50,10 @@ export class ProtoArray { | |
| /** | ||
| * Maps block root to array of node indices for each payload status variant | ||
| * | ||
| * Array structure: [PENDING, EMPTY, FULL] where indices correspond to PayloadStatus enum values | ||
| * - number[0] = PENDING variant index (PayloadStatus.PENDING = 0) | ||
| * - number[1] = EMPTY variant index (PayloadStatus.EMPTY = 1) | ||
| * - number[2] = FULL variant index (PayloadStatus.FULL = 2) | ||
| * Array structure: [EMPTY, FULL, PENDING] indexed by PayloadStatus enum values | ||
| * - number[0] = EMPTY variant index (PayloadStatus.EMPTY = 0) | ||
| * - number[1] = FULL variant index (PayloadStatus.FULL = 1), undefined until payload arrives | ||
| * - number[2] = PENDING variant index (PayloadStatus.PENDING = 2) | ||
| * | ||
| * Note: undefined array elements indicate that variant doesn't exist for this block | ||
| */ | ||
|
|
@@ -143,7 +144,7 @@ export class ProtoArray { | |
| }); | ||
| } | ||
|
|
||
| // Gloas: return the specified variant, or PENDING if not specified | ||
| // Gloas: return the specified variant | ||
| return variantOrArr[payloadStatus]; | ||
| } | ||
|
|
||
|
|
@@ -441,11 +442,11 @@ export class ProtoArray { | |
| // Check if parent exists by getting variants array | ||
| const parentVariants = this.indices.get(block.parentRoot); | ||
| if (parentVariants != null) { | ||
| const anyParentIndex = Array.isArray(parentVariants) ? parentVariants[0] : parentVariants; | ||
| const anyParentIndex = Array.isArray(parentVariants) ? parentVariants[PayloadStatus.PENDING] : parentVariants; | ||
| const anyParentNode = this.nodes[anyParentIndex]; | ||
|
|
||
| if (!isGloasBlock(anyParentNode)) { | ||
| // Fork transition: parent is pre-Gloas, so it only has FULL variant at variants[0] | ||
| // Fork transition: parent is pre-Gloas, so it only has FULL variant | ||
| parentIndex = anyParentIndex; | ||
| } else { | ||
| // Both blocks are Gloas: determine which parent payload status to extend | ||
|
|
@@ -481,9 +482,9 @@ export class ProtoArray { | |
| const emptyIndex = this.nodes.length; | ||
| this.nodes.push(emptyNode); | ||
|
|
||
| // Store both variants in the indices array | ||
| // [PENDING, EMPTY, undefined] - FULL will be added later if payload arrives | ||
| this.indices.set(block.blockRoot, [pendingIndex, emptyIndex]); | ||
| // Store variants indexed by PayloadStatus enum values | ||
| // [EMPTY=0, FULL=1(undefined), PENDING=2] - FULL set when payload arrives | ||
| this.indices.set(block.blockRoot, [emptyIndex, undefined, pendingIndex]); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what if the spec changes the constant again? variants[EMPTY] = emptyIndex;
variants[PENDING] = pendingIndex; |
||
|
|
||
| // Update bestChild pointers | ||
| if (parentIndex !== undefined) { | ||
|
|
@@ -603,7 +604,7 @@ export class ProtoArray { | |
| const fullIndex = this.nodes.length; | ||
| this.nodes.push(fullNode); | ||
|
|
||
| // Add FULL variant to the indices array | ||
| // Append FULL variant to the indices array | ||
| variants[PayloadStatus.FULL] = fullIndex; | ||
|
|
||
| // Update bestChild for PENDING node (may now prefer FULL over EMPTY) | ||
|
|
@@ -937,32 +938,26 @@ export class ProtoArray { | |
| * Get payload status tiebreaker for fork choice comparison | ||
| * Spec: gloas/fork-choice.md#new-get_payload_status_tiebreaker | ||
| * | ||
| * For PENDING nodes: always returns 0 | ||
| * For EMPTY/FULL variants from slot n-1: implements tiebreaker logic based on should_extend_payload | ||
| * For older blocks: returns node.payloadStatus | ||
| * For PENDING or not-previous-slot: returns node.payloadStatus | ||
| * For EMPTY/FULL from slot n-1: returns hardcoded tiebreaker values per spec | ||
| * - EMPTY → 1, FULL+extend → 2, FULL+!extend → 0 | ||
| * | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment change seems important and non-relevant to the PR. Same with the comment on L#949 and L#954-L#955
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah this is strange I agree, it seems like the tiebreaker uses different values, maybe @ensi321 can take a look at this, it's bit strange I think the constant values for EMPTY, PENDING, FULL, were initially chosen so they match the tiebreaker, but now they no longer do
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, they were chosen because they are in lexicographical order for tiebreaker. Now we change it to be aligned with data.index value.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this comment is too detailed and can cause a lot overthinking. Just think about 0 < 1 < 2 when comparing two nodes. 1 means EMPTY These numbers are not 1:1 mapped to |
||
| * Note: pre-gloas logic won't reach here. Pre-Gloas blocks have different roots, so they are always resolved by the weight and root tiebreaker before reaching here. | ||
| * Note: pre-gloas logic won't reach here. Pre-Gloas blocks have different roots, | ||
| * so they are always resolved by the weight and root tiebreaker before reaching here. | ||
| */ | ||
| private getPayloadStatusTiebreaker(node: ProtoNode, currentSlot: Slot, proposerBoostRoot: RootHex | null): number { | ||
| // PENDING nodes always return PENDING (no tiebreaker needed) | ||
| // PENDING=0, EMPTY=1, FULL=2 | ||
| if (node.payloadStatus === PayloadStatus.PENDING) { | ||
| // PENDING or not from previous slot: return raw PayloadStatus value | ||
| if (node.payloadStatus === PayloadStatus.PENDING || node.slot + 1 !== currentSlot) { | ||
| return node.payloadStatus; | ||
| } | ||
|
|
||
| // For Gloas: check if from previous slot | ||
| if (node.slot + 1 !== currentSlot) { | ||
| return node.payloadStatus; | ||
| } | ||
|
|
||
| // For previous slot blocks in Gloas, decide between FULL and EMPTY | ||
| // based on should_extend_payload | ||
| // Previous slot EMPTY/FULL: use spec-defined tiebreaker values (not PayloadStatus enum values) | ||
| // Spec: return 1 for EMPTY, 2 for FULL+extend, 0 for FULL+!extend | ||
| if (node.payloadStatus === PayloadStatus.EMPTY) { | ||
| return PayloadStatus.EMPTY; | ||
| return 1; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feels weird to not be returning the enum here when the value will be the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see #9176 (comment) |
||
| } | ||
| // FULL - check should_extend_payload | ||
| const shouldExtend = this.shouldExtendPayload(node.blockRoot, proposerBoostRoot); | ||
| return shouldExtend ? PayloadStatus.FULL : PayloadStatus.PENDING; | ||
| return this.shouldExtendPayload(node.blockRoot, proposerBoostRoot) ? 2 : 0; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -1060,7 +1055,7 @@ export class ProtoArray { | |
| }); | ||
| } | ||
|
|
||
| // For Gloas, PENDING variant (index 0) is always the smallest since it's inserted first | ||
| // For Gloas, PENDING has the smallest node index since it's pushed to this.nodes first | ||
| const finalizedIndex = Array.isArray(variants) ? variants[PayloadStatus.PENDING] : variants; | ||
|
|
||
| if (finalizedIndex < this.pruneThreshold) { | ||
|
|
@@ -1397,7 +1392,7 @@ export class ProtoArray { | |
| * Gloas: Returns (root, payloadStatus) based on actual node state | ||
| */ | ||
| getAncestor(blockRoot: RootHex, ancestorSlot: Slot): ProtoNode { | ||
| // Get any variant to check the block (use variants[0]) | ||
| // Get any variant to check the block (PENDING for Gloas, FULL for pre-Gloas) | ||
| const variantOrArr = this.indices.get(blockRoot); | ||
| if (variantOrArr == null) { | ||
| throw new ForkChoiceError({ | ||
|
|
@@ -1406,13 +1401,11 @@ export class ProtoArray { | |
| }); | ||
| } | ||
|
|
||
| const blockIndex = Array.isArray(variantOrArr) ? variantOrArr[0] : variantOrArr; | ||
| const blockIndex = Array.isArray(variantOrArr) ? variantOrArr[PayloadStatus.PENDING] : variantOrArr; | ||
| const block = this.nodes[blockIndex]; | ||
|
|
||
| // If block is at or before queried slot, return PENDING variant (or FULL for pre-Gloas) | ||
| // If block is at or before queried slot, return any variant (PENDING for Gloas, FULL for pre-Gloas) | ||
| if (block.slot <= ancestorSlot) { | ||
| // For pre-Gloas: only FULL exists at variants[0] | ||
| // For Gloas: PENDING is at variants[0] | ||
| return block; | ||
| } | ||
|
|
||
|
|
@@ -1428,7 +1421,7 @@ export class ProtoArray { | |
| }); | ||
| } | ||
|
|
||
| let parentIndex = Array.isArray(parentVariants) ? parentVariants[0] : parentVariants; | ||
| let parentIndex = Array.isArray(parentVariants) ? parentVariants[PayloadStatus.PENDING] : parentVariants; | ||
| let parentBlock = this.nodes[parentIndex]; | ||
|
|
||
| // Walk backwards while parent.slot > ancestorSlot | ||
|
|
@@ -1444,7 +1437,7 @@ export class ProtoArray { | |
| }); | ||
| } | ||
|
|
||
| parentIndex = Array.isArray(nextParentVariants) ? nextParentVariants[0] : nextParentVariants; | ||
| parentIndex = Array.isArray(nextParentVariants) ? nextParentVariants[PayloadStatus.PENDING] : nextParentVariants; | ||
| parentBlock = this.nodes[parentIndex]; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.