Skip to content
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

Migration from Raft to BFT test #4561

Merged
merged 4 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
487 changes: 187 additions & 300 deletions integration/raft/migration_test.go

Large diffs are not rendered by default.

75 changes: 69 additions & 6 deletions orderer/common/msgprocessor/maintenancefilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ package msgprocessor

import (
"bytes"
"time"

"github.com/SmartBFT-Go/consensus/pkg/types"
tock-ibm marked this conversation as resolved.
Show resolved Hide resolved

"github.com/golang/protobuf/proto"
cb "github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric-protos-go/orderer"
protoetcdraft "github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
"github.com/hyperledger/fabric-protos-go/orderer/smartbft"
"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/configtx"
Expand Down Expand Up @@ -45,7 +48,6 @@ func NewMaintenanceFilter(support MaintenanceFilterSupport, bccsp bccsp.BCCSP) *
permittedTargetConsensusTypes: make(map[string]bool),
bccsp: bccsp,
}
mf.permittedTargetConsensusTypes["etcdraft"] = true
mf.permittedTargetConsensusTypes["BFT"] = true
tock-ibm marked this conversation as resolved.
Show resolved Hide resolved
return mf
}
Expand Down Expand Up @@ -117,7 +119,7 @@ func (mf *MaintenanceFilter) inspect(configEnvelope *cb.ConfigEnvelope, ordererC
}

// ConsensusType.Type can only change in maintenance-mode, and only within the set of permitted types.
// Note: only solo to etcdraft transitions are supported.
// Note: only etcdraft to BFT transitions are supported.
if ordererConfig.ConsensusType() != nextOrdererConfig.ConsensusType() {
if ordererConfig.ConsensusState() == orderer.ConsensusType_STATE_NORMAL {
return errors.Errorf("attempted to change consensus type from %s to %s, but current config ConsensusType.State is not in maintenance mode",
Expand All @@ -133,10 +135,15 @@ func (mf *MaintenanceFilter) inspect(configEnvelope *cb.ConfigEnvelope, ordererC
ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())
}

if nextOrdererConfig.ConsensusType() == "etcdraft" {
updatedMetadata := &protoetcdraft.ConfigMetadata{}
if nextOrdererConfig.ConsensusType() == "BFT" {
tock-ibm marked this conversation as resolved.
Show resolved Hide resolved
updatedMetadata := &smartbft.Options{}
if err := proto.Unmarshal(nextOrdererConfig.ConsensusMetadata(), updatedMetadata); err != nil {
return errors.Wrap(err, "failed to unmarshal etcdraft metadata configuration")
return errors.Wrap(err, "failed to unmarshal BFT metadata configuration")
}

_, err := validateBFTMetadataOptions(1, updatedMetadata)
Copy link
Contributor

Choose a reason for hiding this comment

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

Either

  • remove the first return value, because it is not used here, and the id can be hard coded, or
  • move the function consensus/smartbft/configFromMetadataOptions to a package consensus/smartbft/util and make it public. This would break the import cycle. I prefer this option, this way we don't duplicate code.

if updatedMetadata.XXX_unrecognized != nil || err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

what is this XXX field thing check? This is prorobuf implementation specific, isn't it?

Once we upgrade the protobuf version, we might not have this field anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's right, we can skip this check, err check is enough.

Copy link
Contributor

Choose a reason for hiding this comment

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

True, the XXX fields are not required to preserve backwards compatibility going forward, so we better not use them.

Copy link
Contributor

Choose a reason for hiding this comment

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

verifying with validateBFTMetadataOptions should be enough, but see comment on verifying the consenters map as well.

return errors.New("invalid BFT metadata configuration")
}
}

Expand Down Expand Up @@ -197,3 +204,59 @@ func (mf *MaintenanceFilter) ensureConsensusTypeChangeOnly(configEnvelope *cb.Co

return nil
}

func validateBFTMetadataOptions(selfID uint64, options *smartbft.Options) (types.Configuration, error) {
tock-ibm marked this conversation as resolved.
Show resolved Hide resolved
var err error

config := types.DefaultConfig
config.SelfID = selfID

if options == nil {
return config, errors.New("config metadata options field is nil")
}

config.RequestBatchMaxCount = options.RequestBatchMaxCount
config.RequestBatchMaxBytes = options.RequestBatchMaxBytes
if config.RequestBatchMaxInterval, err = time.ParseDuration(options.RequestBatchMaxInterval); err != nil {
return config, errors.Wrap(err, "bad config metadata option RequestBatchMaxInterval")
}
config.IncomingMessageBufferSize = options.IncomingMessageBufferSize
config.RequestPoolSize = options.RequestPoolSize
if config.RequestForwardTimeout, err = time.ParseDuration(options.RequestForwardTimeout); err != nil {
return config, errors.Wrap(err, "bad config metadata option RequestForwardTimeout")
}
if config.RequestComplainTimeout, err = time.ParseDuration(options.RequestComplainTimeout); err != nil {
return config, errors.Wrap(err, "bad config metadata option RequestComplainTimeout")
}
if config.RequestAutoRemoveTimeout, err = time.ParseDuration(options.RequestAutoRemoveTimeout); err != nil {
return config, errors.Wrap(err, "bad config metadata option RequestAutoRemoveTimeout")
}
if config.ViewChangeResendInterval, err = time.ParseDuration(options.ViewChangeResendInterval); err != nil {
return config, errors.Wrap(err, "bad config metadata option ViewChangeResendInterval")
}
if config.ViewChangeTimeout, err = time.ParseDuration(options.ViewChangeTimeout); err != nil {
return config, errors.Wrap(err, "bad config metadata option ViewChangeTimeout")
}
if config.LeaderHeartbeatTimeout, err = time.ParseDuration(options.LeaderHeartbeatTimeout); err != nil {
return config, errors.Wrap(err, "bad config metadata option LeaderHeartbeatTimeout")
}
config.LeaderHeartbeatCount = options.LeaderHeartbeatCount
if config.CollectTimeout, err = time.ParseDuration(options.CollectTimeout); err != nil {
return config, errors.Wrap(err, "bad config metadata option CollectTimeout")
}
config.SyncOnStart = options.SyncOnStart
config.SpeedUpViewChange = options.SpeedUpViewChange

config.LeaderRotation = false
config.DecisionsPerLeader = 0

if err = config.Validate(); err != nil {
return config, errors.Wrap(err, "config validation failed")
}

if options.RequestMaxBytes == 0 {
config.RequestMaxBytes = config.RequestBatchMaxBytes
}

return config, nil
}
Loading