hyperledger / hyperledger/fabric-x-sdk
Surface CONFIG blocks through the parser
- Dominant language
- Go
- Stars
- 3
- Forks
- 5
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 9
Description
## Context
`blocks/fabric/parser.go` and `blocks/fabricx/parser.go` both parse a `HeaderType_CONFIG` envelope
into `nil, nil` (`ParseTx`'s "skip config transactions" branch), and the caller just skips it — no
log, no error, no signal at all. A channel reconfiguration (new org, rotated CA) flowing through
`network.Synchronizer` today produces an ordinary-looking `Block{Number: N, Transactions: []}` with
nothing distinguishing it from an empty regular block. No consumer of `blocks.BlockHandler` can
currently tell a config change happened.
## Approach
Add `ConfigEnvelope *common.Envelope` to `blocks.Block` (blocks/types.go), populated by
`BlockParser.Parse` in both `blocks/fabric` and `blocks/fabricx` whenever an envelope's
`ChannelHeader.Type` is `CONFIG`, plus a `p.log.Infof(...)` line so it's visible even to handlers
that don't use the field.
`ParseTx` itself is untouched — it stays scoped to application transactions and keeps returning
`nil, nil` for non-application envelope types, exactly as today. That contract is also relied on by
`local/submit.go:76`. `Parse()` does its own cheap peek at `ChannelHeader.Type` before deciding
whether to call `ParseTx` at all, rather than changing what `ParseTx` returns.
Purely additive: existing `BlockHandler` implementations ignore the new field for free (zero value
is nil). A handler that wants to react (e.g. rebuild an `identity.TrustStore` via
`identity.NewTrustStoreFromConfig`, from
[hyperledger/fabric-x-sdk#43](https://github.com/hyperledger/fabric-x-sdk/issues/43)) checks
`block.ConfigEnvelope != nil` like any other field — no new interface or dispatch mechanism.
**Why the raw proto, not a decoded type.** Unlike `Transaction`/`ReadWriteSet` (fully decoded,
proto-free), `ConfigEnvelope` stays a raw `*common.Envelope` — a deliberate exception, not an
oversight. Decoding it into org/MSP data needs `fabric-x-common/common/channelconfig`/`msp`,
machinery that already lives in `identity` (see `identity.NewTrustStoreFromConfig`) and shouldn't
become a `blocks` package dependency — that would be a bigger leak (a heavy dependency edge) than
the proto type itself. There's precedent for this in the SDK already: `endorsement.Invocation.Proposal`
is a raw `*peer.Proposal` for the same reason. It also matters for the RPC-avoidance point above:
handing back the actual envelope, not just a "something changed" boolean, is what lets a
Synchronizer-driven consumer react with the data it needs from the block it already has, no extra
`ConfigTransaction` round-trip required.
**CONFIG block vs. CONFIG transaction — not two things to handle.** `HeaderType_CONFIG_UPDATE` is
the client-submitted delta sent to the orderer's `Broadcast`; it never lands in a committed block.
Only the orderer-computed, full `HeaderType_CONFIG` envelope is written to the ledger, and the
orderer never batches it with application transactions — it's always the sole envelope in its
block. So "CONFIG block" and "the CONFIG envelope inside it" are the same event at two
granularities, not two cases needing separate logic — detecting it per-envelope, as `Parse()`
already loops over `Data.Data`, handles this correctly without assuming exactly one envelope per
block. This holds identically for classic Fabric and Fabric-X — fabric-x-committer's sidecar
detects config blocks via the same `HeaderType_CONFIG` check; Fabric-X didn't introduce a different
type here.
## Out of scope
- A dedicated `ConfigHandler` interface / separate dispatch chain in `blocks.Processor` — more
machinery than justified without a concrete consumer; `BlockHandler` is already the one hook
everything goes through.
- Anything that actually acts on the envelope (parsing it into an `identity.TrustStore`, etc.) —
that's [hyperledger/fabric-x-sdk#43](https://github.com/hyperledger/fabric-x-sdk/issues/43)'s
job; this issue only makes the envelope visible.
- Fabric-X's internal mirroring of config changes into a reserved `_config`/`_meta` namespace,
which may make a config change separately observable via `notification.AllTxStreamer`/`Notifier`
(a namespace-write-shaped event, via a different service) in addition to the raw block this issue
surfaces. `blocks.Processor` only ever sees the raw block-level view; the two aren't reconciled
here.
## Verification
- `go test ./blocks/... -race -v` — new cases confirm a CONFIG-type envelope produces a `Block`
with `ConfigEnvelope` set and `Transactions` empty, for both parsers.
- `go test ./... -short -race` — full suite stays green; `Block{}`'s zero value is unaffected for
every existing test/handler.
- `make checks`.
Contributor guide
No contributing guide indexed for this repository
Research direction
Read blocks/types.go and the Parse implementations in blocks/fabric/parser.go and blocks/fabricx/parser.go, then run go test ./blocks/... -race -v to inspect the existing parser cases. Done means CONFIG envelopes produce blocks with ConfigEnvelope set and no transactions in both parsers, while go test ./... -short -race and make checks remain green.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- distributed-systems
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100