hyperledger/fabric · error

consenter metadata in OrdererBlockMetadata doesn't match pro

Error message

consenter metadata in OrdererBlockMetadata doesn't match proposal

What it means

VerifyConsenterSig converts the proposal back into a block via ProposalToBlock and then validates the block's structure. This error means the proposal bytes could not be converted into a well-formed block — the proposal is malformed at the structural level (bad header, data, or metadata encoding), so no signature over it can be trusted.

Source

Thrown at orderer/consensus/smartbft/verifier.go:411

	if err := proto.Unmarshal(sig.IdentifierHeader, sigHdr); err != nil {
		return errors.Wrap(err, "malformed signature header")
	}
	if identityID != uint64(sigHdr.Identifier) {
		v.Logger.Warnf("Expected identity %d but got %d", identityID,
			sigHdr.Identifier)
		return errors.Errorf("identity in signature header does not match expected identity")
	}

	// Ensure orderer block metadata's consenter MD matches the proposal
	ordererMD := &cb.OrdererBlockMetadata{}
	if err := proto.Unmarshal(sig.OrdererBlockMetadata, ordererMD); err != nil {
		return errors.Wrap(err, "malformed orderer metadata in signature")
	}

	if !bytes.Equal(ordererMD.ConsenterMetadata, prop.Metadata) {
		v.Logger.Warnf("Expected consenter metadata %s but got %s in proposal",
			base64.StdEncoding.EncodeToString(ordererMD.ConsenterMetadata), base64.StdEncoding.EncodeToString(prop.Metadata))
		return errors.Errorf("consenter metadata in OrdererBlockMetadata doesn't match proposal")
	}

	block, err := ProposalToBlock(prop)
	if err != nil {
		v.Logger.Warnf("got malformed proposal: %v", err)
		return err
	}

	// Ensure Metadata slice is of the right size
	if len(block.Metadata.Metadata) != len(cb.BlockMetadataIndex_name) {
		return errors.Errorf("block metadata is of size %d but should be of size %d",
			len(block.Metadata.Metadata), len(cb.BlockMetadataIndex_name))
	}

	signatureMetadata := &cb.Metadata{}
	if err := proto.Unmarshal(block.Metadata.Metadata[cb.BlockMetadataIndex_SIGNATURES], signatureMetadata); err != nil {
		return errors.Wrap(err, "malformed signature metadata")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Reject the proposal and let the BFT layer force a view change / new proposal from a healthy leader.
  2. Ensure all ordering nodes run the same Fabric version so ProposalToBlock encoding is uniform.
  3. Inspect network/TLS integrity between orderers if corruption recurs (packet-level issues, proxies).
  4. If it follows a crash-recovery, rebuild the node's consensus state from the ledger or re-provision it.

Example fix

// before: proposal with missing header bytes
prop.Header = nil // ProposalToBlock fails -> error
// after: proposer always fills complete block fields
prop.Header = protoutil.MarshalOrPanic(&cb.Header{Number: blockNum, PreviousHash: prevHash, DataHash: dataHash})
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := ProposalToBlock(prop); err != nil {
    return fmt.Errorf("proposal is structurally invalid: %w", err)
}

Try / catch

err := verifier.VerifyConsenterSig(sig, id)
if err != nil {
    // malformed proposal: reject and force a new proposal from the leader
    if errors.Is(err, ErrMalformedProposal) || strings.Contains(err.Error(), "malformed") {
        triggerViewChange()
    }
    return err
}

Prevention

When it happens

Trigger: VerifyConsenterSig -> verifySignatureIsBoundToProposal: ProposalToBlock(prop) returns an error (e.g. the proposal's Header/Data/Metadata fields are missing, wrong length, or fail internal unmarshalling). Triggered by a corrupted or hand-crafted proposal arriving in a BFT message, or a proposal produced by incompatible code.

Common situations: Corrupted network payloads between orderers; version skew where one node encodes proposals differently; tampered or fuzzed messages; storage corruption of persisted proposals after restart.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/afdc1e3b8982c653. Report an issue: GitHub.