{"record":{"id":"3a7e752cc4794e8c","repo":"hyperledger/fabric","slug":"block-validation-policy-should-be-a-signature-poli","errorCode":null,"errorMessage":"block validation policy should be a signature policy: %v but it is %v instead","messagePattern":"block validation policy should be a signature policy: (.+?) but it is (.+?) instead","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/consensus/smartbft/configverifier.go","lineNumber":166,"sourceCode":"\t}\n\n\texpectedConfigPol := &common.Policy{\n\t\tType:  int32(common.Policy_SIGNATURE),\n\t\tValue: protoutil.MarshalOrPanic(sp),\n\t}\n\n\tif len(conf.ChannelGroup.Groups[\"Orderer\"].Policies) == 0 {\n\t\treturn fmt.Errorf(\"empty policies in 'Orderer' group\")\n\t}\n\n\tif conf.ChannelGroup.Groups[\"Orderer\"].Policies[\"BlockValidation\"] == nil {\n\t\treturn fmt.Errorf(\"block validation policy is not found in the policies of 'Orderer' group\")\n\t}\n\n\tactualPolicy := conf.ChannelGroup.Groups[\"Orderer\"].Policies[\"BlockValidation\"].Policy\n\n\tif !proto.Equal(expectedConfigPol, actualPolicy) {\n\t\treturn fmt.Errorf(\"block validation policy should be a signature policy: %v but it is %v instead\", expectedConfigPol, actualPolicy)\n\t}\n\n\tconsensusTypeConfigValue := conf.ChannelGroup.Groups[\"Orderer\"].Values[\"ConsensusType\"]\n\n\tif consensusTypeConfigValue == nil {\n\t\treturn fmt.Errorf(\"missing consensus type property in config\")\n\t}\n\n\tconsensusTypeValue := &protosorderer.ConsensusType{}\n\tif err := proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue); err != nil {\n\t\treturn fmt.Errorf(\"invalid consensus type property in config: %v\", err)\n\t}\n\n\tconfigOptions := &smartbft.Options{}\n\tif err := proto.Unmarshal(consensusTypeValue.Metadata, configOptions); err != nil {\n\t\treturn fmt.Errorf(\"invalid options encoded in consensus metadata: %v\", err)\n\t}\n","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/consensus/smartbft/configverifier.go#L148-L184","documentation":"SmartBFT's config verifier requires the channel's 'Orderer' group to define a 'BlockValidation' policy that exactly matches the expected signature policy computed for the current consenters. If the policy stored in config differs from the expected SignaturePolicyEnvelope (proto comparison fails), config update validation is rejected. This prevents a misconfigured or malicious config update from weakening block validation.","triggerScenarios":"verifyConfigUpdateMsg -> checkConsentersMatchPolicy runs on every proposed config update; it fires when the Orderer group's Policies[\"BlockValidation\"].Policy is not proto.Equal to the expected signature policy derived from the consenters/policy template.","commonSituations":"Hand-edited or generated channel config where BlockValidation was replaced with an ImplicitMeta policy; channel creation tooling that omitted or altered the policy; migrating config from a chain that did not set this policy; merging config templates incorrectly.","solutions":["Regenerate the BlockValidation policy using the canonical template (causal/default orderer config template) so it is an exact proto match of the expected signature policy","Inspect the two policies logged in the error and align field-by-field (principals, n_out_of, t_out_of) with the expected value","Re-create the config update with an up-to-date configtxgen / channel template version instead of hand-editing the policy","Verify the Orderer group in configtx.yaml does not override or delete the BlockValidation policy"],"exampleFix":"// before (config has an ImplicitMeta or altered signature policy under Orderer.Policies.BlockValidation)\n\"BlockValidation\": {\"Policy\": {\"Type\": 1, \"Value\": <different sigpolicy>}}\n// after\n\"BlockValidation\": {\"Policy\": {\"Type\": 1, \"Value\": <expected SignaturePolicyEnvelope matching the current consenters, e.g. a majority n-out-of of the orderer MSP members>}}","handlingStrategy":"validation","validationCode":"expected, _ := proto.Marshal(expectedBlockValidationPolicy)\nactualBytes := conf.ChannelGroup.Groups[\"Orderer\"].Policies[\"BlockValidation\"].GetPolicy()\nif !proto.Equal(expectedBlockValidationPolicy, actualBytes) {\n    return fmt.Errorf(\"BlockValidation policy mismatch: got %v, want %v\", actualBytes, expectedBlockValidationPolicy)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always generate orderer group policies from the current Fabric config template, never hand-edit","Run configtxlator to diff proposed config against the current one before submitting","Keep BlockValidation policy in sync whenever consenters change"],"tags":["hyperledger-fabric","smartbft","config-validation","signature-policy"],"backgroundTag":"invalid-config-value","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}