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

Add support for ConsensusTypeBFT in the orderer.go #62

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
91 changes: 91 additions & 0 deletions configtx/orderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ import (
"time"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-config/configtx/internal/policydsl"
"github.com/hyperledger/fabric-config/configtx/orderer"
"github.com/hyperledger/fabric-protos-go/common"

Choose a reason for hiding this comment

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

this is already imported with alias cb

Copy link
Author

Choose a reason for hiding this comment

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

changed

cb "github.com/hyperledger/fabric-protos-go/common"
mspa "github.com/hyperledger/fabric-protos-go/msp"
ob "github.com/hyperledger/fabric-protos-go/orderer"
eb "github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
sb "github.com/hyperledger/fabric-protos-go/orderer/smartbft"
)

const (
Expand All @@ -38,6 +42,9 @@ type Orderer struct {
Kafka orderer.Kafka
EtcdRaft orderer.EtcdRaft
Organizations []Organization

Choose a reason for hiding this comment

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

Add line comments on these, and update the comment on the type, above, only EtcdRaft and BFT are supported.

SmartBFT *sb.Options

Choose a reason for hiding this comment

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

SmartBFT -> SmartBFTOptions

Copy link
Author

@dviejokfs dviejokfs Jan 18, 2024

Choose a reason for hiding this comment

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

are you sure? in Fabric 3.0 it's SmartBFT

Copy link
Author

Choose a reason for hiding this comment

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

image

I think we need to be consistent

ConsenterMapping []common.Consenter

Choose a reason for hiding this comment

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

There aren't any unit tests that cover these new objects, please add them. See the coverage of EtcdRaft as an example. In other words, everywhere you find orderer.ConsensusTypeEtcdRaft in tests, add a BFT test case.

// MaxChannels is the maximum count of channels an orderer supports.
MaxChannels uint64
// Capabilities is a map of the capabilities the orderer supports.
Expand Down Expand Up @@ -821,6 +828,36 @@ func addOrdererValues(ordererGroup *cb.ConfigGroup, o Orderer) error {
if consensusMetadata, err = marshalEtcdRaftMetadata(o.EtcdRaft); err != nil {
return fmt.Errorf("marshaling etcdraft metadata for orderer type '%s': %v", orderer.ConsensusTypeEtcdRaft, err)
}
case orderer.ConsensusTypeBFT:

Choose a reason for hiding this comment

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

There are many other places where case orderer.ConsensusTypeEtcdRaft: exists but case orderer.ConsensusTypeBFT: does not. For example: func (o *OrdererGroup) Configuration() (Orderer, error)

Please scan the project for any function that uses case orderer.ConsensusTypeEtcdRaft: and see whether BFT needs to be applied there as well.

Copy link
Author

Choose a reason for hiding this comment

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

done

consenterMapping := []*cb.Consenter{}
for _, consenter := range o.ConsenterMapping {
consenterMapping = append(consenterMapping, &cb.Consenter{
Id: consenter.Id,
Host: consenter.Host,
Port: consenter.Port,
MspId: consenter.MspId,
Identity: consenter.Identity,
ClientTlsCert: consenter.ClientTlsCert,
ServerTlsCert: consenter.ServerTlsCert,
})
}
consentersProto, err := proto.Marshal(&cb.Orderers{
ConsenterMapping: consenterMapping,
})
if err != nil {
return fmt.Errorf("marshaling consenters for orderer type '%s': %v", orderer.ConsensusTypeBFT, err)
}

ordererGroup.Values["Orderers"] = &cb.ConfigValue{
Value: consentersProto,
ModPolicy: "Admins",
}
// addValue(ordererGroup, channelconfig.OrderersValue(consenterProtos), channelconfig.AdminsPolicyKey)
if consensusMetadata, err = MarshalBFTOptions(o.SmartBFT); err != nil {
return fmt.Errorf("consenter options read failed with error %s for orderer type %s", err, orderer.ConsensusTypeBFT)
}
// Overwrite policy manually by computing it from the consenters
encodeBFTBlockVerificationPolicy(o.ConsenterMapping, ordererGroup)
default:
return fmt.Errorf("unknown orderer type '%s'", o.OrdererType)
}
Expand All @@ -838,6 +875,14 @@ func addOrdererValues(ordererGroup *cb.ConfigGroup, o Orderer) error {
return nil
}

// MarshalBFTOptions serializes smartbft options.
func MarshalBFTOptions(op *sb.Options) ([]byte, error) {
if copyMd, ok := proto.Clone(op).(*sb.Options); ok {
return proto.Marshal(copyMd)
}

Choose a reason for hiding this comment

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

why is the op object cloned before it is marshalled?
marshalling creates a deep copy, this is unnecessary.

Copy link
Author

Choose a reason for hiding this comment

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

solved

return nil, errors.New("consenter options type mismatch")
}

// setOrdererPolicies adds *cb.ConfigPolicies to the passed Orderer *cb.ConfigGroup's Policies map.
// It checks that the BlockValidation policy is defined alongside the standard policy checks.
func setOrdererPolicies(cg *cb.ConfigGroup, policyMap map[string]Policy, modPolicy string) error {
Expand Down Expand Up @@ -1060,3 +1105,49 @@ func blockDataHashingStructureValue() *standardConfigValue {
},
}
}

func encodeBFTBlockVerificationPolicy(consenterProtos []common.Consenter, ordererGroup *cb.ConfigGroup) error {
Copy link

@tock-ibm tock-ibm Oct 25, 2023

Choose a reason for hiding this comment

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

This is copied from Fabric right?
I think it would have been preferable to import it from Fabric, however, unfortunately, Fabric itself uses fabric-config in the integration tests.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, then how do you prefer to resolve it?

Copy link
Author

Choose a reason for hiding this comment

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

any news @tock-ibm ?

n := len(consenterProtos)
f := (n - 1) / 3

var identities []*mspa.MSPPrincipal
var pols []*cb.SignaturePolicy
for i, consenter := range consenterProtos {
pols = append(pols, &cb.SignaturePolicy{
Type: &cb.SignaturePolicy_SignedBy{
SignedBy: int32(i),
},
})
principalBytes, err := proto.Marshal(&mspa.SerializedIdentity{Mspid: consenter.MspId, IdBytes: consenter.Identity})
if err != nil {
return err
}
identities = append(identities, &mspa.MSPPrincipal{
PrincipalClassification: mspa.MSPPrincipal_IDENTITY,
Principal: principalBytes,
})
}

quorumSize := computeBFTQuorum(n, f)
sp := &cb.SignaturePolicyEnvelope{
Rule: policydsl.NOutOf(int32(quorumSize), pols),
Identities: identities,
}
policyValue, err := proto.Marshal(sp)
if err != nil {
return err
}
ordererGroup.Policies[BlockValidationPolicyKey] = &cb.ConfigPolicy{
// Inherit modification policy
ModPolicy: ordererGroup.Policies[BlockValidationPolicyKey].ModPolicy,
Policy: &cb.Policy{
Type: int32(cb.Policy_SIGNATURE),
Value: policyValue,
},
}
return nil
}

func computeBFTQuorum(totalNodes, faultyNodes int) int {
return int(math.Ceil(float64(totalNodes+faultyNodes+1) / 2))
}
3 changes: 3 additions & 0 deletions configtx/orderer/orderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ const (
// ConsensusTypeEtcdRaft identifies the Raft-based consensus implementation.
ConsensusTypeEtcdRaft = "etcdraft"

// ConsensusTypeBFT identifies the SmartBFT-based consensus implementation.
ConsensusTypeBFT = "BFT"

Choose a reason for hiding this comment

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

There are no unit tests which use this constant


// KafkaBrokersKey is the common.ConfigValue type key name for the KafkaBrokers message.
// Deprecated: the kafka consensus type is no longer supported
KafkaBrokersKey = "KafkaBrokers"
Expand Down