Repository navigation
primitives%fix!: refuse governance object signatures over 96 bytes - #126
PastaPastaPasta wants to merge 6 commits into
Conversation
|
No actionable comments were generated in the recent review. Summary
Merge Risk:
|
|
✅ Final review complete — no blockers (commit 8ad5a62) · triage: low |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! 🚀 New features to boost your workflow:
|
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Phase 1 + Phase 2
Verified the complete diff at 74b1364 and found no actionable defects. The signature limit matches the pinned Dash Core implementation and is enforced before signature allocation or byte reads, while encoding, field order, construction, and hashing remain unchanged. Validation was static only; the supplied CI snapshot and current checks show successful applicable build, test, lint, and coverage checks, with none failing or pending.
Review provenance
Source: reviewer 1: glm-5.3-flash (agent: phase1-reviewer, role: general); reviewer 2: glm-5.3-flash (agent: phase1-reviewer, role: rust-quality); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
lowbygpt-6.1-sol(effort low) — This is a small, contained decoding-bound fix with focused boundary tests and a straightforward macro passthrough, not a large or intricate change despite touching peer-facing deserialization. - Phase 1 reviewers:
glm-5.3-flash— general (completed, effort high); agentphase1-reviewer,glm-5.3-flash— rust-quality (completed, effort high); agentphase1-reviewer - Phase 1 model:
glm-5.3-flash— zai quota: 5h 99% left, weekly 44% left; passed overgemini-3.8-flash-high(antigravity quota lookup failed) - Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort medium); agentphase2-reviewer
|
Note This pull request has no conflicts! 🎊 🎉 🎊 |
`codec_base!` takes `field: limit` in its codec form. `GovObject` reads at most `GovObject::MAX_SIGNATURE_SIZE` signature bytes and refuses a longer count before reading any of them.
74b1364 to
7b552ac
Compare
| codec_base! { | ||
| impl_new! { | ||
| /// A governance object as serialized on the wire. | ||
| /// |
There was a problem hiding this comment.
We can probably drop the below segment and shorten the description to "Governance object", the expanded name was an artefact a noisier iteration of this crate
```text
There was a problem hiding this comment.
Done in 49d3978: the doc is now "Governance object.".
🤖 Posted autonomously by Claude on behalf of pasta.
| #[rstest] | ||
| #[case::with_the_bytes(true)] | ||
| #[case::without_the_bytes(false)] | ||
| fn refuses_a_sig_one_over_the_bound(#[case] with_bytes: bool) { |
There was a problem hiding this comment.
Tautological test, it's effectively a check on codec_base! itself, prefer if there is a general check for codec_base! itself against a dummy struct and then all three cases can be validated and, transiently covering all invocations of the macro
There was a problem hiding this comment.
Done in c10390b: codec_base_bounds_a_limited_field in codec.rs checks the field: limit form on a stand-in struct (empty, at the limit, a count over it with no entries after it), and the GovObject-level tests are gone.
🤖 Posted autonomously by Claude on behalf of pasta.
|
|
||
| - Initial release. | ||
|
|
||
| ### Added |
There was a problem hiding this comment.
This should be in the PR description, unreleased crates don't get changelog updates.
Drop the wire layout block, which repeated the fields in order, and describe the type as a governance object.
One test on a stand-in struct covers an empty list, a list at the limit and a count over it, in place of the governance object's tests.
The crate is unreleased, so the change is described in the pull request instead.
The base form doc names the two macros built on it, as on develop, and adds only the field limit.
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
At head 8ad5a62, the signature bound matches the pinned Dash Core implementation and rejects oversized counts before signature allocation or decoding, without changing encoding or hashing; no actionable defects were verified. Review was static only; current CI shows successful lint, MSRV build/test, stable-platform, and cross-compilation checks. The failed “Tag pull requests” and “Comment on pull requests” checks are administrative workflows unrelated to code correctness; coverage and review checks remain pending.
🔴 0 blocking | 🟡 0 suggestion(s) | 💬 0 nitpick(s)
Review provenance
Source: reviewer 1: glm-5.3-flash (agent: phase1-reviewer, role: general); reviewer 2: glm-5.3-flash (agent: phase1-reviewer, role: rust-quality); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
lowbygpt-6.1-sol(effort low) — The change is small and contained, forwarding an existing field-limit mechanism through codec_base! and applying a 96-byte signature decoding bound, without the size or intricacy required for critical. - Phase 1 reviewers:
glm-5.3-flash— general (completed, effort high); agentphase1-reviewer,glm-5.3-flash— rust-quality (completed, effort high); agentphase1-reviewer - Phase 1 model:
glm-5.3-flash— zai quota: 5h 77% left, weekly 76% left; passed overgemini-3.8-flash-high(antigravity quota lookup failed) - Fresh verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort medium); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort medium); agentphase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify the current code and confirm that no unresolved issues remain.
No unresolved findings remain from the prior review on this head.
Motivation
The reference implementation v24.0.0 reads a governance object's signature as a vector of at most 96 bytes, and refuses a longer length before reading the bytes (dashpay/dash#7831).
dash-primitivesreads it up toMAX_SER_SIZE. This pull request bounds it at 96, usingimpl_vec!'sfield: limitfrom #119. #119 named this field as a follow-up.Additional Information
GovObject::sigat 96 bytesGovObject::MAX_SIGNATURE_SIZEis 96.GovObjectdeclares itself withimpl_new!and takes its codec fromcodec_base!'s$ty, $max, { fields }form, which now passes afield: limitthrough toimpl_vec!. The signature count is checked before any signature byte is read, and a longer count isDecodeError::CompactSizeExceedsLimit. The other fields,dataincluded, read as before. Encoding is unchanged.govobj.json5,proposals.json5andtriggers.json5, unchangedChangelog
The crate is unreleased, so this entry is kept here instead of in
pkgs/primitives/CHANGELOG.md.Added
GovObject::MAX_SIGNATURE_SIZE, the most signature bytes a governance object carries (96).codec_base!reads a field writtenfield: limitwith at mostlimitentries, in its$ty, $max, { fields }form.Changed
GovObjectrefuses a signature longer thanGovObject::MAX_SIGNATURE_SIZEwhen decoding, before reading its bytes.Breaking Changes
GovObjectrefuses a signature longer than 96 bytes when decoding, which it read before.dash-p2p-core'sgovobjmessage, which carries aGovObject, refuses it too.How Has This Been Tested?
codec_base_bounds_a_limited_fieldcheckscodec_base!itself on a stand-in struct with a field writtenitems: 2: an empty list and a list at the limit decode and encode back to the same bytes, and a count of 3 is refused when only the count is on the wire, so no entry is read first. No test decodes aGovObjectwith a long signature: its bound is thesig: Self::MAX_SIGNATURE_SIZEentry in thatcodec_base!form, whose limit this test checks.govobj.json5,proposals.json5andtriggers.json5still decodes and encodes to the same bytes.Checklist
comments and concerns without said assistance. I assume authorship of the code submitted.
Agent disclosure
Code, commit messages and this description were generated with Claude Code using Claude Opus 5.5, running autonomously as an agent on behalf of the author. The change was reviewed by a Claude Code agent using Opus 5.5.
🤖 Generated with Claude Code