hyperledger/fabric · error

signature's OrdererBlockMetadata and OrdererBlockMetadata ex

Error message

signature's OrdererBlockMetadata and OrdererBlockMetadata extracted from block do not match

What it means

The OrdererBlockMetadata decoded from the block's SIGNATURES metadata is not identical (proto.Equal) to the OrdererBlockMetadata carried in the signature being verified. This means the signature is not bound to this block's metadata, so the block fails verification. It is an integrity/consistency check in the SmartBFT verifier.

Source

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

	// 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")
	}

	ordererMDFromBlock := &cb.OrdererBlockMetadata{}
	if err := proto.Unmarshal(signatureMetadata.Value, ordererMDFromBlock); err != nil {
		return errors.Wrap(err, "malformed orderer metadata in block")
	}

	// Ensure the block's OrdererBlockMetadata matches the signature.
	if !proto.Equal(ordererMDFromBlock, ordererMD) {
		return errors.Errorf("signature's OrdererBlockMetadata and OrdererBlockMetadata extracted from block do not match")
	}

	return nil
}

type consenterVerifier struct {
	logger        *flogging.FabricLogger
	channel       string
	policyManager policies.Manager
}

// Evaluate evaluates signed data and returns no error if signature is valid and satisfies the policy
func (cv *consenterVerifier) Evaluate(signatureSet []*protoutil.SignedData) error {
	policy, ok := cv.policyManager.GetPolicy(policies.ChannelOrdererWriters)
	if !ok {
		cv.logger.Errorf("[%s] Error: could not find policy %s in policy manager %v", cv.channel, policies.ChannelOrdererWriters, cv.policyManager)
		return errors.Errorf("could not find policy %s", policies.ChannelOrdererWriters)
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Use the signature produced for exactly this block (same seqNo and metadata); do not copy signatures across blocks
  2. Re-fetch the block and its signature bundle from the consensus/ledger source
  3. Check that no middleware or tooling rewrites block metadata after signing
  4. If seen repeatedly from one consenter, investigate that node for buggy or malicious behavior

Example fix

// before: signature taken from a cached map keyed only by height
sig := sigCache[block.Header.Number]
// after: key by block header hash / proposal digest
sig := sigCache[hex.EncodeToString(protoutil.BlockHeaderHash(block.Header))]
Defensive patterns

Strategy: try-catch

Validate before calling

// verify binding yourself before calling the API
sigMD, _ := protoutil.GetMetadataFromBlock(blk, cb.BlockMetadataIndex_SIGNATURES)
obm := &cb.OrdererBlockMetadata{}
if err := proto.Unmarshal(sigMD.Value, obm); err != nil { return err }
if !proto.Equal(obm, expectedOrdererMD) {
    return errors.New("signature not bound to this block's metadata")
}

Type guard

func signatureBoundToBlock(sigOrdererMD, blkOrdererMD *cb.OrdererBlockMetadata) bool {
    return proto.Equal(sigOrdererMD, blkOrdererMD)
}

Try / catch

if err := verifier.VerifyConsenterSig(blk, sig); err != nil {
    if strings.Contains(err.Error(), "do not match") {
        log.Warnf("signature/block binding failed for block %d; re-fetching block", blk.Header.Number)
        return reFetchBlockAndSignature(blk.Header.Number)
    }
    return err
}

Prevention

When it happens

Trigger: VerifyConsenterSig is given a signature whose attached OrdererBlockMetadata differs from the one embedded in the block — e.g. signature copied from a different block, or block metadata was altered after signing.

Common situations: Replay of signatures across blocks during Byzantine/malicious activity or buggy custom code; blocks assembled by hand in tests; mixing blocks from different channels/heights.

Related errors


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