-
Notifications
You must be signed in to change notification settings - Fork 47
Add bootnode component #327
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: main
Are you sure you want to change the base?
Conversation
|
Claude finished @ferranbt's task in 1m 54s —— View job Reviewing PR #327: Add bootnode component
SummaryThis PR adds a dedicated bootnode component instead of using one of the nodes as a bootnode. The changes refactor the bootnode setup to use a cleaner API with Changes reviewed:
Issues Found🔴 Critical: Nil Pointer DereferenceThe This will cause a panic at runtime. See inline comments for the suggested fix. What Looks Good
Recommendations
|
|
|
||
| e.Bootnode = &BootnodeRef{ | ||
| Service: "bootnode", | ||
| ID: bootnode.Enode.NodeID(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 Critical Bug: Nil pointer dereference
This line calls bootnode.Enode.NodeID(), but at this point bootnode.Enode is nil. The Enode field is only initialized inside the Apply() method (in components.go:1024), which hasn't been called yet.
This will cause a panic at runtime when UseBootnode() is invoked.
Suggested fix: The UseBootnode() method needs to eagerly initialize the EnodeAddr, similar to how the old code in recipe_opstack.go worked. Consider something like:
func (e *ExContext) UseBootnode() ComponentGen {
bootnode := &Bootnode{}
bootnode.Enode = e.Output.GetEnodeAddr() // Initialize eagerly
e.Bootnode = &BootnodeRef{
Service: "bootnode",
ID: bootnode.Enode.NodeID(),
}
return bootnode
}Then update Bootnode.Apply() to check if Enode is already set before calling ctx.Output.GetEnodeAddr():
func (b *Bootnode) Apply(ctx *ExContext) *Component {
component := NewComponent("bootnode")
if b.Enode == nil {
b.Enode = ctx.Output.GetEnodeAddr()
}
// ... rest of the method
}| func (b *Bootnode) Apply(ctx *ExContext) *Component { | ||
| component := NewComponent("bootnode") | ||
|
|
||
| b.Enode = ctx.Output.GetEnodeAddr() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This initialization needs to be conditional to support the UseBootnode() helper method. When UseBootnode() is used, the Enode is pre-initialized to establish the BootnodeRef before Apply() runs.
| b.Enode = ctx.Output.GetEnodeAddr() | |
| if b.Enode == nil { | |
| b.Enode = ctx.Output.GetEnodeAddr() | |
| } |
| } | ||
|
|
||
| func (e *ExContext) UseBootnode() ComponentGen { | ||
| bootnode := &Bootnode{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing initialization: Before calling bootnode.Enode.NodeID() on line 185, you need to initialize the Enode field:
| bootnode := &Bootnode{} | |
| bootnode := &Bootnode{} | |
| bootnode.Enode = e.Output.GetEnodeAddr() |
|
Claude finished @ferranbt's task in 2m 18s —— View job Reviewing PR #327: Add bootnode component
SummaryThis PR adds a dedicated Issues Found🔴 Bug: Component ordering issueIn See inline comment. 🔴 Bug: Enode key mismatchIn See inline comment. Previous Issue Status✅ The nil pointer dereference identified in the previous review was fixed in commit |
playground/recipe_opstack.go
Outdated
| Service: "op-geth", | ||
| ID: opGeth.Enode.NodeID(), | ||
| } | ||
| component.AddService(ctx, ctx.UseBootnode()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: The bootnode setup on line 91 occurs after RethEL is added on line 79. Since AddComponent() immediately calls Apply(ctx), ctx.Bootnode will be nil when RethEL.Apply() runs, meaning the --bootnodes flag will never be set for the L1 execution client.
Move ctx.UseBootnode() before line 79:
func (o *OpRecipe) Apply(ctx *ExContext) *Component {
component := NewComponent("op-recipe")
component.AddService(ctx, ctx.UseBootnode()) // Move here
component.AddComponent(ctx, &RethEL{})
// ...
}| func (b *Bootnode) Apply(ctx *ExContext) *Component { | ||
| component := NewComponent("bootnode") | ||
|
|
||
| b.Enode = ctx.Output.GetEnodeAddr() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: This unconditionally calls GetEnodeAddr(), which generates a new key each time (incrementing a sequence counter). However, UseBootnode() already calls GetEnodeAddr() to create the Enode and store the NodeID in ctx.Bootnode.
This means:
UseBootnode()generates key readme bullets formatting #1, stores its NodeID inctx.Bootnode.IDBootnode.Apply()generates key CLI could print services and their ports for clarity #2 (different!), usesenode-key-2.txt
Clients will connect to the NodeID from key #1, but the bootnode will be running with key #2.
Fix: Only generate if Enode is nil:
| b.Enode = ctx.Output.GetEnodeAddr() | |
| if b.Enode == nil { | |
| b.Enode = ctx.Output.GetEnodeAddr() | |
| } |
|
Claude finished @ferranbt's task in 1m 23s —— View job Reviewing PR #327: Add bootnode component
SummaryThis PR adds a dedicated Issues Found🔴 Bug 1: Component ordering - bootnode flag never set for L1 clientIn Impact: The Fix: Move func (o *OpRecipe) Apply(ctx *ExContext) *Component {
component := NewComponent("op-recipe")
component.AddService(ctx, ctx.UseBootnode()) // Move here FIRST
component.AddComponent(ctx, &RethEL{})
// ...
}🔴 Bug 2: Enode key mismatch - clients connect to wrong node IDIn Impact: Clients will try to connect to the node ID from key #1, but the bootnode service will be running with key #2. Fix: Only generate the enode if not already set: func (b *Bootnode) Apply(ctx *ExContext) *Component {
component := NewComponent("bootnode")
if b.Enode == nil {
b.Enode = ctx.Output.GetEnodeAddr()
}
// ...
}Previous Issue Status✅ The nil pointer dereference identified in the first review was fixed in commit NotesThese two bugs were identified in my previous review but have not been addressed yet. The inline comments from that review provide additional context. |
|
Claude finished @ferranbt's task in 1m 23s —— View job Reviewing PR #327: Add bootnode component
SummaryThis PR adds a dedicated Previous Issues Status✅ Bug 1 (Component ordering) - Fixed in commit Remaining Issues🔴 Bug: Enode key mismatch - clients connect to wrong node IDIn Since Impact: Clients (like RethEL) will try to connect using the NodeID from key #1, but the bootnode service will be running with key #2 from the overwritten enode. Fix: Add a nil check to preserve the pre-initialized enode: func (b *Bootnode) Apply(ctx *ExContext) *Component {
component := NewComponent("bootnode")
if b.Enode == nil {
b.Enode = ctx.Output.GetEnodeAddr()
}
// ...
}See inline comment. |
| func (b *Bootnode) Apply(ctx *ExContext) *Component { | ||
| component := NewComponent("bootnode") | ||
|
|
||
| b.Enode = ctx.Output.GetEnodeAddr() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: This unconditionally overwrites b.Enode, but UseBootnode() already initialized it at manifest.go:182 and stored the NodeID in ctx.Bootnode.ID.
Since GetEnodeAddr() increments a sequence counter, this generates a different key. Clients will connect using the NodeID from the first key, but the bootnode runs with the second key.
| b.Enode = ctx.Output.GetEnodeAddr() | |
| if b.Enode == nil { | |
| b.Enode = ctx.Output.GetEnodeAddr() | |
| } |
|
Claude finished @ferranbt's task in 1m 13s —— View job Reviewing PR #327: Add bootnode component
SummaryThis PR refactors the bootnode setup to use a dedicated Previous Issues Status✅ Nil pointer dereference - Fixed in commit Remaining Issue🔴 Bug: Enode key mismatchIn Impact: Clients connect using NodeID from key #1, but the bootnode runs with key #2. See inline comment for the fix. |
| func (b *Bootnode) Apply(ctx *ExContext) *Component { | ||
| component := NewComponent("bootnode") | ||
|
|
||
| b.Enode = ctx.Output.GetEnodeAddr() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Enode key mismatch
This unconditionally overwrites b.Enode, but UseBootnode() already initialized it at manifest.go:182 and stored its NodeID in ctx.Bootnode.ID.
Since GetEnodeAddr() increments a sequence counter (see artifacts.go:703), this generates a different key:
UseBootnode()→ key readme bullets formatting #1 (sequence=1), stores NodeID inctx.Bootnode.IDBootnode.Apply()→ key CLI could print services and their ports for clarity #2 (sequence=2), overwritesb.Enode
Impact: Clients (like RethEL) will try to connect using the NodeID from key #1, but the bootnode service runs with key #2.
| b.Enode = ctx.Output.GetEnodeAddr() | |
| if b.Enode == nil { | |
| b.Enode = ctx.Output.GetEnodeAddr() | |
| } |
This PR adds a custom bootnode component instead of having to use one of the nodes as bootnode.