hiero-ledger / hiero-ledger/hiero-sdk-python
feat: implement _from_protobuf for consensus (topic) transactions (from_bytes round-trip)
- Dominant language
- Python
- Stars
- 63
- Forks
- 298
- Avg merge
- 3d 18h
- Merged PRs (30d)
- 38
Description
### π§βπ» Intermediate Issue
Welcome! This is an **[Intermediate Issue](https://github.com/issues?q=is%3Aopen%20is%3Aissue%20org%3Ahiero-ledger%20archived%3Afalse%20no%3Aassignee%20(label%3A%22intermediate%22%20OR%20label%3A%22skill%3A%20intermediate%22)%20(repo%3Ahiero-ledger%2Fhiero-sdk-cpp%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-swift%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-python%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-js%20OR%20repo%3Ahiero-ledger%2Fhiero-website))** touching core SDK architecture.
π **When this issue is complete, you will have:**
β
Researched across multiple files and modules
β
Owned implementation decisions
β
Written thorough, meaningful tests
β
Delivered a clean, review-ready pull request
### π Problem Description
`Transaction.from_bytes()` returns a correctly-typed but **empty** instance for the transaction types below: they never override `_from_protobuf`, so every type-specific field is left at its default with no error or warning (common fields, signatures and the original body bytes *are* restored by the base class, so execution still works β inspection does not). Part of #2179; the dispatch-map fixes and the round-trip test harness land in #2614 first.
Affected classes:
- `TopicCreateTransaction` (`src/hiero_sdk_python/consensus/topic_create_transaction.py`)
- `TopicUpdateTransaction` (`src/hiero_sdk_python/consensus/topic_update_transaction.py`)
- `TopicDeleteTransaction` (`src/hiero_sdk_python/consensus/topic_delete_transaction.py`)
- `TopicMessageSubmitTransaction` (`src/hiero_sdk_python/consensus/topic_message_submit_transaction.py`)
### π‘ Expected Solution
Implement `_from_protobuf` for each affected class as the exact field-for-field inverse of its `build_transaction_body()`, then remove the `xfail` markers for these types in the round-trip harness from #2614.
- [ ] `TopicCreateTransaction._from_protobuf`
- [ ] `TopicUpdateTransaction._from_protobuf`
- [ ] `TopicDeleteTransaction._from_protobuf`
- [ ] `TopicMessageSubmitTransaction._from_protobuf`
- [ ] Un-xfail these types in the #2614 round-trip harness
### π Background Research
This is inverse-serialization contract work β please research the pattern before coding; **do not code from this issue title alone**, and do not ship the first AI-generated attempt that runs. Reviewers check inverse fidelity per field.
1. Issue #2179 (context) and #2614 (the test harness your PR must satisfy β **do not start before it is merged**).
2. The reference implementations: `FileCreateTransaction._from_protobuf` (`src/hiero_sdk_python/file/file_create_transaction.py`) and `TransferTransaction._from_protobuf` (`src/hiero_sdk_python/transaction/transfer_transaction.py`). Your implementation must follow their structure exactly: call `super()._from_protobuf(...)`, then restore type-specific fields from the body.
3. Each affected class's `build_transaction_body()` β your `_from_protobuf` is its exact inverse. Reuse the SDK's existing `_from_proto` converters (`AccountId`, `TokenId`, keys, β¦); never hand-parse a submessage that already has one.
4. The generated proto message for each body (`src/hiero_sdk_python/hapi/services/`) β learn which fields are `optional` (guard with `HasField` so unset stays `None`) versus plain scalars/repeated.
5. [CONTRIBUTING.md](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/CONTRIBUTING.md) for test and PR conventions.
### π οΈ Implementation Notes
`TopicMessageSubmitTransaction` is a chunked transaction β research how chunking interacts with serialization before implementing (what does `to_bytes()` of a multi-chunk transaction contain, and what should `from_bytes` restore?). State your conclusion in the PR description. Topic create/update carry optional keys and auto-renew fields β use `HasField` for optionals.
**Constraints / acceptance criteria:**
- For each class: build with all fields set β freeze β `to_bytes()` β `from_bytes()` β every type-specific field equals the original
- Unset optional fields come back as `None`/empty, not proto defaults
- `restored.to_bytes()` stays byte-identical to the original (no re-serialization of the body)
- No changes to public API signatures
Part of #2179. **Blocked by #2614.**
### π¬ Technical Domains
- [x] **Intermediate to Advanced Programming** (Object oriented design, inheritance, complex type systems)
- [x] **File Specific Knowledge** (request β serialization β execution β response mapping)
- [x] **Backward Compatibility** (preserving method signatures, defaults, and return types)
- [x] **Protobuf Alignment** (reading `.proto` files, `_to_proto()` / `_from_proto()` correctness)
- [x] **Testing** (unit, integration, mocking, test coverage for edge cases and failure modes)
### π§ Intermediate Contributors β Prerequisites & Expectations
> [!CAUTION]
> **Intermediate issues are high-risk. We expect more than just a 'working solution' and will recommend beginner issues if the PR does not meet these standards.**
### π Concrete Prerequisites
- **Advanced Programming Language:** Higher level intermediate or advanced programming language.
- **Expertise:** Strong understanding of files related to this issue (research before claiming!).
- **Proven History:** Successfully completed **β₯ 5 beginner issues** in this repo.
If this feels like too big a step, that is completely fine β try a [Beginner Issue](https://github.com/issues?q=is%3Aopen%20is%3Aissue%20org%3Ahiero-ledger%20archived%3Afalse%20no%3Aassignee%20(label%3A%22beginner%22%20OR%20label%3A%22skill%3A%20beginner%22)%20(repo%3Ahiero-ledger%2Fhiero-sdk-cpp%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-swift%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-python%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-js%20OR%20repo%3Ahiero-ledger%2Fhiero-website)) first or a different **[Intermediate Issue](https://github.com/issues?q=is%3Aopen%20is%3Aissue%20org%3Ahiero-ledger%20archived%3Afalse%20no%3Aassignee%20(label%3A%22intermediate%22%20OR%20label%3A%22skill%3A%20intermediate%22)%20(repo%3Ahiero-ledger%2Fhiero-sdk-cpp%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-swift%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-python%20OR%20repo%3Ahiero-ledger%2Fhiero-sdk-js%20OR%20repo%3Ahiero-ledger%2Fhiero-website))**. You can always come back when you are ready.
### β οΈ AI Usage Policy
- Using AI to generate code for Intermediate issues is **strictly discouraged**
- Using AI as the main source of research is **strictly discouraged**, refer to language and library documentation, protobuf definitions and other SDKs.
### β±οΈ Timeline & Workflow
- **Typical time:** ~2 weeks / ~25 hours.
- π΄ Completing an intermediate issue in 1β3 days is a **red flag**.
> [!TIP]
> **Suggested:** share your proposed implementation approach as a comment before writing code to get early feedback and avoid wasted effort.
### π§ͺ Testing Requirements
> [!IMPORTANT]
> At the intermediate level, **testing is a major component**.
> Each `_from_protobuf` you implement must be verified field-by-field. Tests should cover happy paths, unset-optional edge cases, and error handling.
**Source code changes (in `src/`):**
- Un-xfail and pass the parametrized round-trip tests from #2614 for your types (build with all fields set β freeze β `to_bytes()` β `from_bytes()` β assert every type-specific field equals the original)
- Add explicit unset-optional cases: fields not set must come back as `None`/empty, not proto defaults
- Run tests locally: `uv run pytest tests/unit/_test.py -v`
- Verify naming, types, and field ordering match [protobuf definitions](https://github.com/hashgraph/hedera-protobufs/tree/main/services)
- Check consistency with similar classes already in the SDK β use the same patterns
- Integration tests will run automatically when you push
### π‘οΈ Quality & Review Standards
Intermediate PRs must be **"working, maintainable, and aligned with SDK architecture."**
1. **Working:** The implementation must solve the problem and meet the acceptance criteria.
2. **Maintainable:** Code should be clear and concise enough for others to understand and debug without your assistance.
3. **SDK Alignment:** The solution should fit well with existing SDK patterns and abstractions.
4. **Backward Compatibility:** Public API signatures must be preserved.
5. **Comprehensive Testing:** Must include unit and integration tests covering all new logic paths, edge cases, and failure modes. AI generated tests based on AI generated code is grounds for immediate rejection.
**β οΈ Breaking changes**
- Before changing any function signature, return type, or public API β stop and check
- If a breaking change is unavoidable: get explicit maintainer approval **before** implementing
- All existing tests should pass as-is.
### β PR Quality Checklist
Before opening your PR, confirm:
- [ ] I have spent the majority of my time researching the problem and solution space extensively, including reviewing relevant code, documentation, and external resources.
- [ ] My implementation works but is also of high quality - including maintainability, readability, and architectural fit.
- [ ] I have checked for breaking changes - no public APIs regress.
- [ ] The system design fits with current Hiero SDK architectural approaches.
- [ ] Every line of code is personally understood and explainable.
Before requesting a review, confirm:
- [ ] I have reviewed the diff line by line.
- [ ] My implementation fully addresses the problem described above.
- [ ] I did not modify files unrelated to this issue
- [ ] Clean git history β no rebase artifacts, merge commits, or unrelated files
- [ ] My commits are signed: `git commit -S -s -m "chore: description"` β [Signing guide](https://github.com/hiero-ledger/sdk-collaboration-hub/blob/main/guides/issue-progression/for-developers/signing.md)
- [ ] I have verified naming, types, and field ordering against pinned Protobufs.
- [ ] I have applied appropriate linting, code quality, and formatting tools used in this repo.
- [ ] I have included appropriate tests and all CI checks pass.
- [ ] Double and triple check β intermediate PRs are time-consuming to review
### π Workflow quick reference
You know the workflow β here are the links if you need them:
| Step | Guide |
|------|-------|
| Claim this issue | Comment `/assign` below |
| Sync with main | [Rebasing guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/rebasing.md) |
| Open a PR and link this issue | [PR guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/training/workflow/11_submit_pull_request.md) Β· [Linking guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/how_to_link_issues.md) |
| Resolve merge conflicts | [Merge conflicts guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/merge_conflicts.md) |
| Testing | [Testing guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/testing.md) |
### π Resources & Support
**π Stuck?**
> [!TIP]
> **Comment on this issue:** and describe what you have tried. A maintainer will respond.
**Project references:**
- [Project structure](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/training/setup/project_structure.md)
- [CONTRIBUTING.md](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/CONTRIBUTING.md)
- [Browse closed intermediate PRs](https://github.com/hiero-ledger/hiero-sdk-python/pulls?q=is%3Apr+is%3Amerged+label%3A%22skill%3A+intermediate%22) β see how others did it
- [Pylance guide](https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/pylance.md)
**Protobuf references:**
- [Hedera Protobufs](https://github.com/hashgraph/hedera-protobufs/tree/main/services) β source of truth for field names, types, and ordering
- [Protobuf language guide](https://protobuf.dev/programming-guides/proto3/)
**Community:**
- [Community Calls](https://zoom-lfx.platform.linuxfoundation.org/meetings/hiero?view=week)
- [Discord](https://github.com/hiero-ledger/sdk-collaboration-hub/blob/main/guides/issue-progression/for-developers/discord.md)
Contributor guide
Research direction
Wait for #2614, then read the four affected transaction files and their build_transaction_body() methods, comparing them with FileCreateTransaction._from_protobuf and TransferTransaction._from_protobuf. Review the generated protobuf messages and CONTRIBUTING.md, then run the parametrized round-trip tests plus explicit unset-optional cases. Done means type-specific fields round-trip field-for-field and restored bytes remain identical.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend-api-design, blockchain
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100