Uh oh!
There was an error while loading. Please reload this page.
fix: compute SML entry hash with SER_GETHASH semantics in dash - #798
Conversation
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThe PR splits MasternodeListEntry consensus encoding into version and body parts, updates entry hashing to use the body-only preimage, and changes SocketAddr decoding to recognize IPv4-mapped IPv6 values while preserving round-trip bytes. ChangesConsensus Encoding and Hashing Alignment
🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
dash/src/sml/masternode_list_entry/hash.rs (1)
6-10: 💤 Low valueConsider returning
Resultor documenting infallibility.The
expect("encoding failed")violates the guideline to avoidexpect()in library code. However, encoding to aVec<u8>is practically infallible sinceVec'sWriteimpl only fails on allocation exhaustion (which would panic anyway).Two options:
- Keep as-is but add a comment explaining why failure is impossible
- Change signature to return
Result<sha256d::Hash, std::io::Error>for API consistencyGiven that this is a public method and allocation failure would abort regardless, option 1 is reasonable here.
📝 Suggested documentation
impl MasternodeListEntry { pub fn calculate_entry_hash(&self) -> sha256d::Hash { + // Vec<u8> write is infallible (barring OOM which aborts), so expect is safe here. let mut writer = Vec::new(); self.consensus_encode_body(&mut writer).expect("encoding failed"); sha256d::Hash::hash(&writer) } }As per coding guidelines: "Avoid
unwrap()andexpect()in library code; use proper error types".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@dash/src/sml/masternode_list_entry/hash.rs` around lines 6 - 10, The method calculate_entry_hash currently calls self.consensus_encode_body(&mut writer).expect("encoding failed"), which uses expect in library code; replace this by keeping the current behavior but add a concise comment explaining why encoding to a Vec<u8> is effectively infallible (the Write impl for Vec only fails on allocation exhaustion which would abort) and that returning a Result was considered but omitted for API stability; reference the calculate_entry_hash and consensus_encode_body symbols and state that sha256d::Hash::hash(&writer) remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@dash/src/sml/masternode_list_entry/hash.rs`:
- Around line 6-10: The method calculate_entry_hash currently calls
self.consensus_encode_body(&mut writer).expect("encoding failed"), which uses
expect in library code; replace this by keeping the current behavior but add a
concise comment explaining why encoding to a Vec<u8> is effectively infallible
(the Write impl for Vec only fails on allocation exhaustion which would abort)
and that returning a Result was considered but omitted for API stability;
reference the calculate_entry_hash and consensus_encode_body symbols and state
that sha256d::Hash::hash(&writer) remains unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fa716e82-9a61-4a6f-9dd8-5f0fb0b7d223
📒 Files selected for processing (3)
dash/src/sml/address.rsdash/src/sml/masternode_list_entry/hash.rsdash/src/sml/masternode_list_entry/mod.rs
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@## dev #798 +/- ##
==========================================
+ Coverage 72.61% 72.67% +0.05%
==========================================
Files 323 323 Lines 71747 71786 +39 ==========================================
+ Hits 52097 52167 +70 + Misses 19650 19619 -31
|
This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them. |
`MasternodeListEntry::calculate_entry_hash` hashed the full network consensus serialization, including the leading `version`. Dash Core's `CSimplifiedMNListEntry::CalcHash` uses `CHashWriter(SER_GETHASH, ...)`, and `SER_GETHASH` does not set `SER_NETWORK`, so the `SER_NETWORK`-gated leading `nVersion` is omitted from the hash pre-image. The two contexts therefore diverged for every entry. Extract the post-`version` body of the wire encoder into a shared `consensus_encode_body` helper. `consensus_encode` writes `version` then the body (byte-identical to before), while `calculate_entry_hash` hashes the body alone, matching Core's `CalcHash`. Verified against Core for both a `version` 1 and a `version` 2 Evo entry. Also fix `SocketAddr` decoding to use `to_ipv4_mapped` instead of `to_ipv4`, so an all-zero (`::`) service address round-trips to the same 16 bytes instead of acquiring an `::ffff:` mapped prefix. The prefix corruption changed the wire bytes and thus the entry hash for masternodes with an unset service.
458894f to
09a142fCompareUh oh!
There was an error while loading. Please reload this page.
MasternodeListEntry::calculate_entry_hashhashed the full network consensus serialization, including the leadingversion. Dash Core'sCSimplifiedMNListEntry::CalcHashusesCHashWriter(SER_GETHASH, ...), andSER_GETHASHdoes not setSER_NETWORK, so theSER_NETWORK-gated leadingnVersionis omitted from the hash pre-image. The two contexts therefore diverged for every entry.Extract the post-
versionbody of the wire encoder into a sharedconsensus_encode_bodyhelper.consensus_encodewritesversionthen the body (byte-identical to before), whilecalculate_entry_hashhashes the body alone, matching Core'sCalcHash. Verified against Core for both aversion1 and aversion2 Evo entry.Also fix
SocketAddrdecoding to useto_ipv4_mappedinstead ofto_ipv4, so an all-zero (::) service address round-trips to the same 16 bytes instead of acquiring an::ffff:mapped prefix. The prefix corruption changed the wire bytes and thus the entry hash for masternodes with an unset service.Summary by CodeRabbit
Bug Fixes
Tests