hiero-ledger / hiero-ledger/hiero-consensus-node
Harden CRS update framing and accepted-contributor accounting
- Dominant language
- Java
- Stars
- 406
- Forks
- 226
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 210
Description
## Summary
Strengthen the execution-layer boundary around CRS contribution validation. Completion of this issue requires **both**:
1. Exact framing validation for CRS updates before crossing the native-library boundary.
2. Explicit, unique, restart-safe accounting of accepted contributors.
Point-level and pairing validation remain the responsibility of the cryptography library; the execution layer should enforce protocol framing and state-transition invariants without parsing curve-point encodings.
## Required work
### 1. Enforce exact CRS update framing
At the execution-layer/native-library boundary:
- Require the submitted `newCrs` length to equal the previous accepted CRS length.
- Require the submitted CRS length to match the ceremony's original expected CRS length.
- Require the contribution proof to have its canonical length (currently 128 bytes).
- Reject malformed framing before copying input into native arrays or invoking JNI where practical.
- When producing a local contribution, require the output of `updateCrs()` to be exactly `previousCrs.length() + proofLength` before splitting it into CRS and proof.
- Do not accept truncated CRS encodings, appended/trailing data, short or extended proofs, or incorrectly framed local update output.
Keep format-specific constants owned by, or exposed through, the cryptography adapter where possible. Do not duplicate Arkworks point parsing in the application.
### 2. Make accepted-contributor accounting explicit
Replace a bare running contribution-weight total with explicit accepted-contributor identity:
- Track the node IDs whose contributions were cryptographically accepted.
- Derive contributed weight from the unique accepted-contributor set and source-roster weights.
- A node must not receive contribution weight more than once, including across ceremony restart/replay paths.
- Adoption of a new candidate CRS and addition of its contributor must occur atomically and only after all framing and cryptographic checks pass.
- An invalid contribution must preserve the previous candidate and accepted-contributor set, receive no weight, and must not prevent the ceremony from progressing to later scheduled contributors.
- Restart/reconstruction from persisted state/publications must produce the same candidate CRS and accepted-contributor set as uninterrupted execution.
- Distinguish an invalid contribution from a local verifier/JNI failure. A local verification failure must be observable and must not allow the ceremony to finalize with ambiguous accounting.
Persist enough information, or retain enough ordered publications, to make reconstruction deterministic across repeated ceremony rounds.
## Acceptance criteria
- [ ] A shorter or longer `newCrs` than the previous accepted CRS is rejected.
- [ ] A CRS with trailing bytes is rejected.
- [ ] A proof whose length is not exactly the canonical proof length is rejected.
- [ ] Malformed local `updateCrs()` output is not submitted.
- [ ] Rejected framing does not invoke the native verifier where the application can determine invalidity itself.
- [ ] Only a cryptographically accepted contribution changes the candidate CRS.
- [ ] Only unique accepted node IDs contribute weight.
- [ ] Repeating a valid contribution from the same node across a restart/replay does not increase contributed weight.
- [ ] An invalid contributor is skipped without poisoning the candidate used by the next honest contributor.
- [ ] Controller reconstruction yields the same candidate, accepted contributors, and contributed weight as uninterrupted execution.
- [ ] Finalization cannot complete after a local verifier failure or with inconsistent contributor accounting.
## Tests
Add execution-layer tests covering at least:
- truncated and extended CRS byte arrays;
- trailing CRS data;
- short and extended proofs;
- incorrectly sized local update output;
- a valid contribution following a rejected contribution;
- duplicate publication by one node across restart/replay;
- reconstruction after accepted and rejected publications; and
- weight threshold calculation from unique accepted contributors.
At least one test should exercise the real cryptography adapter rather than mocking every native-library result, so the node build verifies the expected adapter framing contract.
## Non-goals
- Reimplementing curve-point decoding, identity-point checks, pairing equations, or contribution proofs in Java.
- Adding a mock-signature fallback after real-TSS cutover.
Contributor guide
Research direction
Start at the execution-layer/native-library boundary and trace updateCrs(), JNI verification, candidate adoption, and persisted ceremony reconstruction. Add execution-layer tests for malformed framing, rejected-then-valid contributions, duplicate replay, reconstruction, and unique-weight thresholds; exercise the real cryptography adapter. Done means framing is rejected early, accepted contributors and CRS state reconstruct deterministically, and verifier failures cannot finalize the ceremony.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, cryptography
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100