hiero-ledger / hiero-ledger/hiero-consensus-node
Hand-crafted graph conformance suite for `ConsensusImpl`
- Dominant language
- Java
- Stars
- 406
- Forks
- 226
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 210
Description
## Background
Every consensus test today uses a *relative* oracle. None assert that consensus is
correct — only that it is self-consistent.
- `ConsensusTests` — one generated graph, two instances, different topological orders,
assert outputs match plus a consensus-ratio threshold
(`OutputEventsEqualityValidation`, `OutputEventRatioValidation`, driven from `ConsensusTestDefinitions#orderInvarianceTests`).
- Falcon — nodes agree with each other and keep making progress
(`haveEqualCommonRounds().haveConsistentRounds()`, `falcon/SmokeTest.java`).
- `ConsensusEngineContractTest` — real contract checks, but structural, not value-level.
A deterministically and uniformly wrong `ConsensusImpl` — wrong judge set, wrong
intra-round ordering, wrong round timestamp — passes all three. Nodes agree, progress
continues, suite is green.
This epic adds the missing prong: small hand-crafted graphs with human-derived,
hard-coded expected output.
| | Falcon | This suite |
|---|---|---|
| Oracle | agreement + liveness across nodes | absolute, human-derived |
| Coverage | probabilistic, breadth over seeds | enumerated, one shape per test |
| Failure signal | "a node diverged / stalled" | "round 3's judge set is wrong" |
| Graph size | thousands of events | ~10–40 events |
| Covers | gossip, intake, timing, restart, wiring | the algorithm's decision function |
Latency is not something consensus consumes — it is a *shape generator*. Consensus
consumes a DAG. Falcon discovers which shapes real latency produces; this suite answers
"given this shape, is the output right." A hand-crafted graph can encode any shape
latency would produce.
## Machinery that already exists
- `TestIntake` (`consensus-hashgraph-impl/src/testFixtures/.../consensus/TestIntake.java`)
— real `DefaultConsensusEngine`, `DefaultOrphanBuffer`, `DefaultEventHasher` on a
`DeterministicWiringModel`. No node, no network, no threads.
- `SimpleGraph` / `SimpleGraphs` / `SimplePlatformEventGraph`
(`.../test/fixtures/graph/`) — hand-built graphs, ASCII javadoc pictures,
human-readable hashes.
- `DeGenTest` — the exemplar style: named graph, hard-coded value per event
(`assertDeGen(8, 3)`), scoped to one helper.
- `TestingEventBuilder` — `setSelfParent`, `setOtherParents`, `setBirthRound`,
`setHash`, `setCreatorId`, `setTimeCreated`.
- GUI reachable from a unit test: `ConsensusTestDebugGui#runGui` / `TestGuiSource`.
- `SimpleGraph#shuffledEvents(Random)` — keeps the differential order-invariance check
on top of the absolute one, for free.
- `ConsensusConfig.roundsNonAncient` is read off `Configuration` in `TestIntake`; set it
to 3 and staleness/ancient-eviction needs a dozen events, not hundreds.
Observability for the assertion layer is largely present: `EventImpl` exposes
`getRoundCreated()`, `isWitness()`, `isFamous()`, `isJudge()`, `isConsensus()`,
`getRecTimes()`, `getConsensusTimestamp()`. Per-round judges are observable without
impl access via `ConsensusRound#getSnapshot().judgeIds()`
(`JudgeId{creator_id, judge_hash}`, `hapi/.../platform/state/platform_state.proto`).
## Scope
1. **First hand-crafted test — SCN-001.** Prove the approach with no new framework; let
it reveal what the authoring layer needs.
2. **`HandGraph` parser.** Text-defined graphs, name-based lookup, deterministic ladder
for scaffolding rounds.
3. **Mermaid renderer.** Review a hand-crafted graph in a diff without launching Swing.
## Out of scope — follow-on epics
- **Mutation gate.** Known-bad `ConsensusImpl` variants (pre-fix `recalculateAndVote`
carve-out, off-by-one supermajority, judges sorted by wrong key) that the suite must
kill. This is what turns "we wrote tests" into a measurable claim — highest-priority
follow-on, but needs a catalog to measure.
- **Catalog buildout.** Backlog is already written down: INV-001…INV-015 (most have no
deterministic test; INV-014, INV-007, INV-015 are directly assertable on a small
graph), SCN-002, SCN-003, RUL-005, and re-enabling `CoinRoundTest` (`@Disabled` — its
PCES fixtures predate birth rounds).
- **Assertion-layer buildout** beyond sub-task 1: per-round witness sets,
strongly-seeing pairs, election votes, stale sets.
- **Model oracle.** Naive paper-literal reimplementation, no shared code, cross-checked
against hand-derived cases. Force multiplier; contingent on this epic.
- **`ConsensusTests` retirement.** Scenario intent (partition, clique, branching,
shunned node, quorum-down) → Falcon. Shape classification (`ancient`, `stale`,
`branchingTests`, `repeatedTimestampTest`, `usesStaleOtherParents`,
`providesStaleOtherParents`, `genesisSnapshotTest`) → this suite. Separate epic.
## Acceptance Criteria
1. All three sub-tasks closed.
2. At least one hand-crafted test asserts human-derived values — not captured output —
in the standard `consensus-hashgraph-impl` unit test task.
3. A graph can be authored from text and rendered to Mermaid without the GUI.
4. Every test added cites the KB entry it covers; that entry's `related.tests` is
updated in the same PR.
5. Authoring guide exists (module `README.md` or KB page): how to define a graph, how to
derive expectations by hand, and the rule that expected values are literals with a
derivation comment — never captured from a run.
## Dependencies
None blocking. Sub-task order is 1 → 2 → 3.
Contributor guide
Research direction
Start with sub-task 1 (SCN-001) in the consensus-hashgraph-impl unit tests, reading TestIntake, the graph fixtures, and DeGenTest. Run the standard unit test task and use the named observability APIs to derive human-written expected values. Done means at least one hard-coded hand-crafted test cites its KB entry, updates related.tests, and follows the authoring guidance; the parser and Mermaid renderer are later sub-tasks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- distributed-systems, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100