Skip to content

Commit

Permalink
Raft to BFT migration: draft
Browse files Browse the repository at this point in the history
Signed-off-by: May Rosenbaum <[email protected]>
  • Loading branch information
MayRosenbaum committed Jan 4, 2024
1 parent e2f1c5e commit 1647161
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 66 deletions.
88 changes: 82 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"

"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,7 @@ func NewMaintenanceFilter(support MaintenanceFilterSupport, bccsp bccsp.BCCSP) *
permittedTargetConsensusTypes: make(map[string]bool),
bccsp: bccsp,
}
mf.permittedTargetConsensusTypes["etcdraft"] = true
// mf.permittedTargetConsensusTypes["etcdraft"] = true
mf.permittedTargetConsensusTypes["BFT"] = true
return mf
}
Expand Down Expand Up @@ -117,7 +120,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,11 +136,17 @@ func (mf *MaintenanceFilter) inspect(configEnvelope *cb.ConfigEnvelope, ordererC
ordererConfig.ConsensusType(), nextOrdererConfig.ConsensusType())
}

if nextOrdererConfig.ConsensusType() == "etcdraft" {
updatedMetadata := &protoetcdraft.ConfigMetadata{}
if nextOrdererConfig.ConsensusType() == "BFT" {
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)
if updatedMetadata.XXX_unrecognized != nil || err != nil {
return errors.New("invalid BFT metadata configuration")
}
//fmt.Printf("##########the bft metadata is: %+v########\n", updatedMetadata)
}

logger.Infof("[channel: %s] consensus-type migration: about to change from %s to %s",
Expand Down Expand Up @@ -170,10 +179,21 @@ func (mf *MaintenanceFilter) ensureConsensusTypeChangeOnly(configEnvelope *cb.Co
}

if len(configUpdate.WriteSet.Values) > 0 {
//jsonObj, err := json.MarshalIndent(configUpdate, "", " ")
//err = os.WriteFile("configUpdate.json", jsonObj, 0644)
//if err != nil {
// fmt.Println("Error writing JSON to file:", err)
//}
return errors.Errorf("config update contains changes to values in group %s", channelconfig.ChannelGroupKey)
}

if len(configUpdate.WriteSet.Groups) > 1 {
//jsonObj, err := json.MarshalIndent(configUpdate.WriteSet, "", " ")
//err = os.WriteFile("configChangeMaintenanceTest.json", jsonObj, 0644)
//if err != nil {
// fmt.Println("Error writing JSON to file:", err)
//}
//fmt.Printf("------configUpdate.WriteSet.Groups is: %+v, len is: %v\n", configUpdate.WriteSet.Groups, len(configUpdate.WriteSet.Groups))
return errors.New("config update contains changes to more than one group")
}

Expand All @@ -197,3 +217,59 @@ func (mf *MaintenanceFilter) ensureConsensusTypeChangeOnly(configEnvelope *cb.Co

return nil
}

func validateBFTMetadataOptions(selfID uint64, options *smartbft.Options) (types.Configuration, error) {
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

0 comments on commit 1647161

Please sign in to comment.