Skip to content

refactor(x/sync): remove need for passing proof nodes to completeWorkItem #4064

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

alarso16
Copy link
Contributor

@alarso16 alarso16 commented Jul 9, 2025

Why this should be merged

As a part of the refactor to allow Firewood to use x/sync, we should remove any proof logic from sync manager. This moves finding the next key to request to the proof commit implementation, as well as parsing the proof from bytes.

How this works

The completeWorkItem function does not need to know the largest handled key, but rather the next key that needs retrieved. This is handled through a hook, since even on some non-error returns, it shouldn't be called (see implementation). Instead of passing in the DB to the Sync Manager, it will take this ProofClient

How this was tested

Unit tests.

Need to be documented in RELEASES.md?

No.

@alarso16 alarso16 added merkledb go Pull requests that update Go code labels Jul 9, 2025
@alarso16 alarso16 force-pushed the alarso16/move-next-key branch 2 times, most recently from 6936bbb to 4a3dae0 Compare July 9, 2025 16:41
@alarso16 alarso16 marked this pull request as ready for review July 9, 2025 16:42
@Copilot Copilot AI review requested due to automatic review settings July 9, 2025 16:42
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the completeWorkItem function in the x/sync package to simplify work item completion by removing the need to pass proof nodes and calculating the next key to fetch within the proof response handlers instead.

  • Moves next key calculation logic from completeWorkItem to handleRangeProofResponse and handleChangeProofResponse
  • Simplifies completeWorkItem function signature by removing ctx and proofOfLargestKey parameters
  • Adds test coverage for the findNextKey function with identical keys edge case

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
x/sync/manager.go Refactors proof response handlers to calculate next key before calling completeWorkItem and simplifies the completeWorkItem function signature
x/sync/sync_test.go Adds new test case for findNextKey function when start and end keys are identical

@alarso16 alarso16 force-pushed the alarso16/move-next-key branch 8 times, most recently from 86765a8 to ab1bd24 Compare July 15, 2025 18:51
@alarso16 alarso16 force-pushed the alarso16/move-next-key branch from ab1bd24 to c8e2fd9 Compare July 15, 2025 18:52
//
// Invariant: [lastReceivedKey] < [rangeEnd].
// If [rangeEnd] is Nothing it's considered > [lastReceivedKey].
func (c *xSyncClient) findNextKey(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Everything this function and below was completely unmodified.

"github.com/stretchr/testify/require"
)

func Test_Sync_FindNextKey_InSync(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These tests are unmodified besides initialization

Copy link
Contributor

Choose a reason for hiding this comment

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

These comments significantly reduce review time, ty for doing that!

@@ -12,3 +19,18 @@ type DB interface {
merkledb.ChangeProofer
merkledb.RangeProofer
}

type ProofClient interface {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any ideas for a better name?

Copy link
Contributor

Choose a reason for hiding this comment

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

SyncClient?

Copy link
Contributor

@joshua-kim joshua-kim Jul 16, 2025

Choose a reason for hiding this comment

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

What do we define this interface for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The x/sync manager should be able to work with other database implementations besides MerkleDB (specifically, Firewood). This is the smallest reasonable interface to allow other databases to hook in.

Copy link
Contributor

@rkuris rkuris left a comment

Choose a reason for hiding this comment

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

This looks fine to me, not sure why we are removing BranchFactor16. We support this in firewood as well, although it is not a runtime option, it's compile time. We could check and refuse to open if the feature isn't enabled in a future release. For now, I think we can just implement it without BranchFactor16 working.

@@ -12,3 +19,18 @@ type DB interface {
merkledb.ChangeProofer
merkledb.RangeProofer
}

type ProofClient interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

SyncClient?

Comment on lines +24 to +25
merkledb.Clearer
merkledb.MerkleRootGetter
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: naming: These are no longer merkledb interfaces, correct? Sure, they are implemented by merkledb but IIRC golang just lets you declare interfaces. If so, interfaces used by ProofClient (or SyncClient) should be maybe in a package named xsync or something.


stateSyncNodeIdx uint32
metrics SyncMetrics
}

// TODO remove non-config values out of this struct
type ManagerConfig struct {
DB DB
ProofClient ProofClient
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Does it make sense to just use ProofClient here so you aren't stuttering? Not sure if that makes sense.

RangeProofClient *p2p.Client
ChangeProofClient *p2p.Client
SimultaneousWorkLimit int
Log logging.Logger
TargetRoot ids.ID
BranchFactor merkledb.BranchFactor
Copy link
Contributor

Choose a reason for hiding this comment

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

What happened to this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to ProofClient

@@ -327,7 +315,7 @@ func (m *Manager) requestChangeProof(ctx context.Context, work *workItem) {

if work.localRootID == targetRootID {
// Start root is the same as the end root, so we're done.
m.completeWorkItem(ctx, work, work.end, targetRootID, nil)
m.completeWorkItem(work, work.end, targetRootID)
Copy link
Contributor

Choose a reason for hiding this comment

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

🏆 seems like not having context means we aren't doing any database work down there, which I think is good!

"github.com/stretchr/testify/require"
)

func Test_Sync_FindNextKey_InSync(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

These comments significantly reduce review time, ty for doing that!

@@ -12,3 +19,18 @@ type DB interface {
merkledb.ChangeProofer
merkledb.RangeProofer
}

type ProofClient interface {
Copy link
Contributor

@joshua-kim joshua-kim Jul 16, 2025

Choose a reason for hiding this comment

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

What do we define this interface for?

BranchFactor merkledb.BranchFactor
}

type xSyncClient struct {
Copy link
Contributor

@joshua-kim joshua-kim Jul 16, 2025

Choose a reason for hiding this comment

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

This abstraction feels very difficult to reason about and there doesn't seem to be a clear abstraction boundary defined - what is this type intended to represent and what is it's responsibility? It's not really a client - it doesn't make any requests, but seems to define handlers for how to interpret responses + you can interact with the underlying database it's coupled to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It isn't really a client, but I didn't know what to call it. The goal was to remove the dependence on database and proof implementation (specifically merkledb) from the sync manager. The x/sync manager in particular shouldn't depend on any specific database/proof implementation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
go Pull requests that update Go code merkledb
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

3 participants