Skip to content

Prune the pool after a reconfig when the config is installed late - #729

Merged
HagarMeir merged 1 commit into
hyperledger:mainfrom
HagarMeir:prune-after-async-reconfig
Oct 22, 2026
Merged

HagarMeir merged 1 commit into
hyperledger:mainfrom
HagarMeir:prune-after-async-reconfig

Conversation

@HagarMeir

Copy link
Copy Markdown
Contributor

Fixes #728.

Problem

Consensus.reconfig prunes the request pool, then starts the new controller. Controller.Start stored the verification sequence the Verifier reported at that moment. If the application installs the new config asynchronously and the switch lands during the prune or before Controller.Start, the prune ran against the old config while the controller stored the new sequence. MaybePruneRevokedRequests then never saw a change, so requests that are invalid under the new config stayed in the pool.

Change

  • Consensus.reconfig reads VerificationSequence() before Pool.Prune and passes it through startComponents to Controller.Start.
  • Controller.Start takes the sequence as a parameter instead of reading the Verifier. A switch that lands during or after the prune is then detected, and the pool is pruned on the next decision, sync or view change.
  • The initial Consensus.Start passes the Verifier's current sequence, so its behaviour is unchanged.

Controller is in internal/, so the new parameter changes no public API.

Test

  • The test app has a new revokeDuringPrune option. It delays revoking clients after a reconfig is delivered until the next VerifyRequest, which is the prune in reconfig.
  • TestPoolPrunedAfterAsyncReconfig: a follower holds a request from a client that the reconfig revokes. The test checks that the request is still in the pool after the reconfig, and that the next decision removes it.
  • Without the fix in Controller.Start, the new test fails because the request is never removed.

Run locally: golangci-lint (pinned version, 0 issues), go vet ./..., and go test -race -count=1 ./..., including the integration suite.

Written by Claude (AI assistant) on behalf of Hagar Meir.

🤖 Generated with Claude Code

pfi79
pfi79 previously approved these changes Oct 22, 2026
@pfi79
pfi79 force-pushed the prune-after-async-reconfig branch from dd76d7d to a725f87 Compare October 22, 2026 13:34
@HagarMeir
HagarMeir force-pushed the prune-after-async-reconfig branch from a725f87 to 50130f9 Compare October 22, 2026 15:01
Consensus.reconfig prunes the request pool and then starts the new
controller, and Controller.Start stored the verification sequence the
Verifier reported at that moment. If the application installs the new
config asynchronously and the switch lands during the prune or before
Controller.Start, the prune used the old config while the controller
stored the new sequence. MaybePruneRevokedRequests then never saw a
change, and requests that are invalid under the new config stayed in
the pool.

Read the verification sequence before the prune in reconfig and start
the controller with it, so a switch that lands later is detected and
pruned on the next decision, sync or view change. The initial Start
passes the Verifier's current sequence, as before.

The test app can now delay revoking clients until the prune during
reconfig, and TestPoolPrunedAfterAsyncReconfig checks that the next
decision removes the revoked request.

Fixes hyperledger#728

Written by Claude (AI assistant) on behalf of Hagar Meir.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Hagar Meir <hagar.meir@ibm.com>
@HagarMeir
HagarMeir merged commit a677bb4 into hyperledger:main Oct 22, 2026
6 checks passed
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.

Request pool may not be pruned after a reconfig when the application installs the new config asynchronously

2 participants