Skip to content

dynamic reconfig utils#647

Open
MayRosenbaum wants to merge 2 commits intohyperledger:mainfrom
MayRosenbaum:dynamic_reconfig_utils
Open

dynamic reconfig utils#647
MayRosenbaum wants to merge 2 commits intohyperledger:mainfrom
MayRosenbaum:dynamic_reconfig_utils

Conversation

@MayRosenbaum
Copy link
Contributor

@MayRosenbaum MayRosenbaum commented Feb 25, 2026

This PR adds utility functions to determine whether an admin restart is required.
Relevant issues #442 #504 #487 #445

@MayRosenbaum MayRosenbaum force-pushed the dynamic_reconfig_utils branch 2 times, most recently from 66f6113 to 6311754 Compare February 25, 2026 13:41
Copy link

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 introduces helper utilities in the config package to support dynamic reconfiguration flows by deciding whether a node can apply a config update without an admin restart (and by detecting party eviction), plus a small helper to build a new Configuration from a config block.

Changes:

  • Added IsPartyEvicted/FindParty helpers for membership/eviction checks.
  • Added IsNodeConfigChangeRestartRequired to detect restart-required config changes (endpoint/TLS/sign cert).
  • Added Configuration.BuildNewConfiguration and a new unit test file for the reconfig utilities.

Reviewed changes

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

File Description
config/reconfig.go New exported utility functions/interfaces for eviction detection and restart-required decisions.
config/reconfig_test.go New tests for the reconfig utilities.
config/config.go Adds BuildNewConfiguration helper to construct a new config from a config block.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +34 to +36
func TestIsNodeConfigChangeRestartRequired(t *testing.T) {
// Test Router
currRouterConfig := &protos.RouterNodeConfig{
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

This test covers address/TLS/sign-cert changes, but it doesn't cover the error branches of IsNodeConfigChangeRestartRequired (nil args, type mismatch). Add test cases for these conditions to prevent regressions.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

True, do it

Comment on lines +807 to +810
consensusMetadata, err := ReadConsensusMetadataFromConfigBlock(block)
if err != nil {
return nil, errors.Errorf("failed applying new config, failed to read consensusMetadata from last config block, block number is %d", block.Header.Number)
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

BuildNewConfiguration uses block.Header.Number in the error message, but there is no nil check for block (or block.Header). Add validation up front to avoid panics if callers pass a nil/invalid block.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

True, first protect against a nil block, then,
True, protect against that, use block.GetHeader(),

Comment on lines +796 to +800
// BuildNewConfiguration builds a new configuration based on current configuration and block
func (config *Configuration) BuildNewConfiguration(block *common.Block) (*Configuration, error) {
if config == nil {
return nil, errors.New("failed applying new config, current configuration is nil")
}
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

BuildNewConfiguration is new behavior in config/config.go, but there are no tests exercising it. Please add unit tests for the success case and failure cases (e.g., invalid block / unmarshal error).

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

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

True, test it!

@MayRosenbaum MayRosenbaum force-pushed the dynamic_reconfig_utils branch from 0f26370 to 0c5aaea Compare February 26, 2026 08:45
Signed-off-by: May.Buzaglo <May.Buzaglo@ibm.com>
Signed-off-by: May.Buzaglo <May.Buzaglo@ibm.com>
@tock-ibm tock-ibm force-pushed the dynamic_reconfig_utils branch from 0c5aaea to cc803de Compare February 26, 2026 13:23
Comment on lines +807 to +810
consensusMetadata, err := ReadConsensusMetadataFromConfigBlock(block)
if err != nil {
return nil, errors.Errorf("failed applying new config, failed to read consensusMetadata from last config block, block number is %d", block.Header.Number)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

True, first protect against a nil block, then,
True, protect against that, use block.GetHeader(),

Comment on lines +796 to +800
// BuildNewConfiguration builds a new configuration based on current configuration and block
func (config *Configuration) BuildNewConfiguration(block *common.Block) (*Configuration, error) {
if config == nil {
return nil, errors.New("failed applying new config, current configuration is nil")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

True, test it!

Comment on lines +39 to +41
// FindParty returns the PartyConfig associated with the given partyID from the shared configuration.
// It returns nil if the party is not found and returns error if the provided configuration is nil or incomplete.
func FindParty(partyID types.PartyID, config *Configuration) (*config_protos.PartyConfig, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can be package private?

Comment on lines +19 to +28
type NodeConfig interface {
GetHost() string
GetPort() uint32
GetTlsCert() []byte
}

type NodeConfigWithSign interface {
NodeConfig
GetSignCert() []byte
}
Copy link
Contributor

Choose a reason for hiding this comment

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

document how this will be used, reference the protos

Copy link
Contributor

Choose a reason for hiding this comment

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

Explicitly say, router and assembler are.... consenter and batcher are... etc

Comment on lines +802 to +805
newConfig := &Configuration{
LocalConfig: config.LocalConfig,
SharedConfig: &protos.SharedConfig{},
}
Copy link
Contributor

Choose a reason for hiding this comment

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

move that next to where you use it, below

SharedConfig: &protos.SharedConfig{},
}

consensusMetadata, err := ReadConsensusMetadataFromConfigBlock(block)
Copy link
Contributor

Choose a reason for hiding this comment

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

There must be a utility that returns func myFunc(block) (*protos.SharedConfig, error) somewhere...

Comment on lines +85 to +87
if currOK && !bytes.Equal(extendedCurrConfig.GetSignCert(), extendedNewConfig.GetSignCert()) {
return true, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Leave a comment that we may need to match the public key, so that we can do dynamic instead of restart in some cases when the private key & public key do not change

// - sign certificate (this is checked if both configs implement NodeConfigWithSign)
//
// Both arguments must represent the same node type and be non-nil.
func IsNodeConfigChangeRestartRequired(currentConfig, newConfig NodeConfig) (bool, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

add a logger to the function and log what you find with Info, super useful

Comment on lines +34 to +36
func TestIsNodeConfigChangeRestartRequired(t *testing.T) {
// Test Router
currRouterConfig := &protos.RouterNodeConfig{
Copy link
Contributor

Choose a reason for hiding this comment

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

True, do it

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