Skip to content

sdk%feat(codec): define Hashable trait, impl_hash helper for typical cases, Codec to validate impl of subtraits, TypeId for name-stable u32 identifier with uniqueness test#16

Open
kwvg wants to merge 14 commits into
dashpay:developfrom
kwvg:hash

Conversation

@kwvg

@kwvg kwvg commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Additional Information

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@kwvg kwvg added this to the 0.1 milestone Jun 28, 2026
@kwvg kwvg self-assigned this Jun 28, 2026
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 31d4a3f4-6819-4fff-af69-50811b009eff

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown

@github-actions github-actions Bot removed the needs-rebase This pull request needs to be rebased against the base branch label Jun 30, 2026
@kwvg kwvg marked this pull request as ready for review June 30, 2026 01:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkgs/p2p_core/src/primitives/compressed_header.rs (1)

138-153: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

prev_hash elision is still keyed off the wrong predecessor value.

Line 147 compares header.prev_hash with prev.prev_hash. For a normal contiguous chain those values almost never match, so FLAG_PREV_HASH stays set and headers2 keeps paying the full 32-byte prev-hash on nearly every header. The decode fallback mirrors the same assumption, so both sides should reconstruct against the previous header's block hash instead.

🤖 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 `@pkgs/p2p_core/src/primitives/compressed_header.rs` around lines 138 - 153,
The prev-hash compression logic in `CompressedHeader::encode_header` is
comparing against the wrong field, so `FLAG_PREV_HASH` is rarely cleared on
normal chains. Update the `need_prev_hash` check to compare `header.prev_hash`
against the previous header’s block hash rather than `prev.prev_hash`, and make
the matching decode fallback in the compressed header path reconstruct using the
previous header’s block hash as well so both `encode_header` and the
corresponding decode logic use the same predecessor reference.
🧹 Nitpick comments (4)
pkgs/primitives/src/block.rs (1)

175-217: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a regression case for mutated = true.

The new CVE-2012-2459 path is only covered here through non-mutated corpus/genesis blocks, so the duplicate-sibling branch can regress silently. A small unit test that feeds duplicate leaf hashes into compute_merkle_root() (or a crafted block with repeated txids) would lock down the new contract.

🤖 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 `@pkgs/primitives/src/block.rs` around lines 175 - 217, Add a regression test
for the CVE-2012-2459 mutated path in compute_merkle_root() and/or
Block::merkle(). Create a small unit test that uses duplicate sibling leaf
hashes so the duplicate-last-pair branch is exercised and assert that the
returned mutated flag is true; this will lock down the new contract and prevent
silent regressions. Use the existing compute_merkle_root helper and the
Block::merkle method as the entry points for the test.
pkgs/primitives/src/gov.rs (1)

372-390: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Please add a hash regression for GovVote.

GovVote::hash() now has custom legacy-compatible serialization, but the test module only round-trips vote wire/serde data. One fixed-vector assertion for the canonical vote hash would protect the padding/ordering contract you just introduced.

🤖 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 `@pkgs/primitives/src/gov.rs` around lines 372 - 390, Add a regression test for
GovVote::hash to lock down the new legacy-compatible serialization contract. Use
the existing GovVote type in the gov.rs test module and add one fixed-vector
assertion that checks the exact canonical Hash256 output for a known vote
instance. This should verify the padding and field ordering in GovVote::hash,
not just wire/serde round-trips, so future changes to masternode_outpoint,
parent_hash, signal, outcome, or time encoding are caught.
pkgs/primitives/src/payload/proupregtx.rs (1)

21-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid restating the type name in the rustdoc summary.

Line 21 repeats ProUpRegTx; make the summary describe the type instead.

Proposed wording
-/// ProUpRegTx -- update MN keys/payout (type 3).
+/// Updates masternode keys and payout details (type 3).

As per coding guidelines, rustdoc summaries should be written "without restating the signature".

🤖 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 `@pkgs/primitives/src/payload/proupregtx.rs` at line 21, The rustdoc summary on
ProUpRegTx should describe the type without repeating its name or the signature.
Update the comment above the ProUpRegTx type in proupregtx.rs so it focuses on
what the type represents (an update to MN keys/payout) instead of restating
“ProUpRegTx”.

Source: Coding guidelines

pkgs/primitives/src/payload/prouprevtx.rs (1)

20-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Avoid restating the type name in the rustdoc summary.

Line 20 repeats ProUpRevTx; make the summary describe the type instead.

Proposed wording
-/// ProUpRevTx -- revoke a masternode (type 4).
+/// Revokes a masternode (type 4).

As per coding guidelines, rustdoc summaries should be written "without restating the signature".

🤖 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 `@pkgs/primitives/src/payload/prouprevtx.rs` at line 20, The rustdoc summary on
ProUpRevTx restates the type name, so rewrite the doc comment to describe what
the type does without repeating the signature text. Update the summary attached
to the ProUpRevTx item to use a descriptive phrase about revoking a masternode,
keeping the wording concise and aligned with the rustdoc summary guidelines.

Source: Coding guidelines

🤖 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.

Inline comments:
In `@contrib/codeql/lib/policy.qll`:
- Around line 212-218: Exclude the proc-macro marker crate from isEnforcedCrate
by tightening the path checks in policy.qll so the pkgs/types rule does not
match pkgs/types/marker/**. Update the isEnforcedCrate predicate to keep the
existing crate coverage for num, types, primitives, and p2p_core while
explicitly filtering out the marker crate, matching the Semgrep policy behavior.
- Around line 15-24: The hasDerive predicate is currently matching any attribute
text on the same lines, so unrelated attrs like doc or cfg can be mistaken for
derive. Update hasDerive in policy.qll to only accept derive-style attributes by
checking the attribute kind or meta directly, or by filtering to derive/cfg_attr
before scanning the source text. Keep the existing TypeItem/Attr logic, but make
sure isNotEncodable can only infer Unencodable from a real #[derive(...)]-style
attribute.

In `@contrib/semgrep/workspace.yml`:
- Around line 56-70: The Semgrep rule macro-no-bare-foreign-crate is too broadly
scoped and its crate-name regex is too restrictive. Update the rule in
workspace.yml so paths.include only targets macro-generated code instead of all
Rust files, and adjust the pattern-regex to allow digits in crate names (for
example, crate names like proc_macro2). Keep the existing exclusions and the
$crate::__private hygiene check intact while narrowing the scope and broadening
the crate-name match.

In `@pkgs/dev/build.rs`:
- Around line 64-71: Do not deduplicate type names before the collision check in
build.rs: ScanResult::names currently uses BTreeSet<String>, which hides
duplicate `Foo` spellings across crates/modules before the TypeId hash pass.
Change ScanResult and the related insertion sites in the scan logic to collect
names with push semantics, then detect repeated names during the hash/collision
pass and panic on duplicates, ideally including the source paths or other
provenance in the error message.

In `@pkgs/num/src/hash.rs`:
- Line 309: The generated EncodeBuf path in the macro still uses invocation-site
crate::, which breaks when the macro is exported or reused. Update the
encode-related path in the hash macro (the fn encode signature in the generated
impl) to use $crate::__private::dash_types::codec::EncodeBuf instead of crate::,
so it always resolves through dash_num regardless of expansion site.

In `@pkgs/p2p_core/src/error.rs`:
- Line 17: The public Rust enum in error.rs is missing the required Hash eager
derive. Update the derive list on the enum identified by Unencodable to include
Hash alongside Clone, Debug, PartialEq, and Eq, keeping the existing derives
intact and in the repository’s standard eager-derive order.

In `@pkgs/primitives/src/codec.rs`:
- Around line 45-46: The TypeId assertion in the macro helper is too long for
the Rust line-width limit; wrap the bound in the `_assert` function in
`codec.rs` so the `BaseCodec` and `TypeId` constraints fit within 120
characters. Keep the change localized to the `_assert`/`_check` helper and
preserve the existing type-check behavior while splitting the trait bounds
across multiple lines.
- Around line 35-40: The macro expansion for the `hash()` body in `codec.rs`
relies on the `sha256d::Hash::hash(...)` trait method, but it does not import
`bitcoin_hashes::Hash` itself. Update the macro-generated code in the
`BaseCodec`/`hash` expansion to bring `bitcoin_hashes::Hash as _` into scope so
the expansion is self-contained and does not depend on the caller’s imports.

In `@pkgs/primitives/src/support.rs`:
- Around line 214-229: The bit-masking logic in the serialization path is
applied to the wrong byte when the source is shorter than required; in the
`support.rs` code around the `take`/`last_byte` handling for `DynBitset`, ensure
the final encoded wire byte is masked instead of masking the last copied source
byte. Update the logic so padding behavior stays unchanged, but the partial-byte
mask is applied to the actual last output byte in the buffer when `self.num_bits
% 8 != 0`, preserving the intended serialized bytes and downstream hashes.

In `@pkgs/types/marker/Cargo.toml`:
- Around line 7-13: The new crate is missing the standard feature contract in
its Cargo.toml, so add a [features] table for the crate and follow the workspace
convention by defining default = [], std = [...], and full = ["std"]. Update the
package’s feature configuration in Cargo.toml so the crate opts into the shared
feature layout and exposes its dependencies through the std feature as expected.

In `@pkgs/types/marker/src/lib.rs`:
- Around line 25-45: The derive macros in marker use an absolute path to
::dash_types::codec::TypeId, so the pkgs/types crate must expose itself under
that name for the generated path to resolve. Add a self-alias in
pkgs/types/src/lib.rs with extern crate self as dash_types; near the crate-level
exports so the TypeId derive in pkgs/types/marker/src/lib.rs can reference the
local crate correctly. Keep the alias alongside the other public module setup
used by the dash_types crate root.

In `@pkgs/types/src/lib.rs`:
- Line 25: Do not re-export Unencodable from dash_types in the public lib.rs
yet; the derive macros still resolve against dash_primitives::__CodecMarker and
__UnencodableMarker, so exposing dash_types::Unencodable would break crates that
only depend on dash_types. Keep the marker available through dash_primitives for
now, or update the derive expansion to reference a path that dash_types
re-exports consistently, and verify the symbols involved in
pkgs/types/src/lib.rs and the related derive macro path.

---

Outside diff comments:
In `@pkgs/p2p_core/src/primitives/compressed_header.rs`:
- Around line 138-153: The prev-hash compression logic in
`CompressedHeader::encode_header` is comparing against the wrong field, so
`FLAG_PREV_HASH` is rarely cleared on normal chains. Update the `need_prev_hash`
check to compare `header.prev_hash` against the previous header’s block hash
rather than `prev.prev_hash`, and make the matching decode fallback in the
compressed header path reconstruct using the previous header’s block hash as
well so both `encode_header` and the corresponding decode logic use the same
predecessor reference.

---

Nitpick comments:
In `@pkgs/primitives/src/block.rs`:
- Around line 175-217: Add a regression test for the CVE-2012-2459 mutated path
in compute_merkle_root() and/or Block::merkle(). Create a small unit test that
uses duplicate sibling leaf hashes so the duplicate-last-pair branch is
exercised and assert that the returned mutated flag is true; this will lock down
the new contract and prevent silent regressions. Use the existing
compute_merkle_root helper and the Block::merkle method as the entry points for
the test.

In `@pkgs/primitives/src/gov.rs`:
- Around line 372-390: Add a regression test for GovVote::hash to lock down the
new legacy-compatible serialization contract. Use the existing GovVote type in
the gov.rs test module and add one fixed-vector assertion that checks the exact
canonical Hash256 output for a known vote instance. This should verify the
padding and field ordering in GovVote::hash, not just wire/serde round-trips, so
future changes to masternode_outpoint, parent_hash, signal, outcome, or time
encoding are caught.

In `@pkgs/primitives/src/payload/proupregtx.rs`:
- Line 21: The rustdoc summary on ProUpRegTx should describe the type without
repeating its name or the signature. Update the comment above the ProUpRegTx
type in proupregtx.rs so it focuses on what the type represents (an update to MN
keys/payout) instead of restating “ProUpRegTx”.

In `@pkgs/primitives/src/payload/prouprevtx.rs`:
- Line 20: The rustdoc summary on ProUpRevTx restates the type name, so rewrite
the doc comment to describe what the type does without repeating the signature
text. Update the summary attached to the ProUpRevTx item to use a descriptive
phrase about revoking a masternode, keeping the wording concise and aligned with
the rustdoc summary guidelines.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3ed4ddbb-481c-4cf2-a937-4014aed178c8

📥 Commits

Reviewing files that changed from the base of the PR and between 577a749 and 73fea3b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (76)
  • Cargo.toml
  • README.md
  • contrib/codeql/attrib.ql
  • contrib/codeql/decl.ql
  • contrib/codeql/lib/filters.qll
  • contrib/codeql/lib/imports.qll
  • contrib/codeql/lib/policy.qll
  • contrib/lint/lint_codeql.py
  • contrib/samples/solver/solver.rs
  • contrib/semgrep/workspace.yml
  • docs/zen/index.md
  • pkgs/dev/Cargo.toml
  • pkgs/dev/build.rs
  • pkgs/dev/src/lambda.rs
  • pkgs/num/src/compact.rs
  • pkgs/num/src/hash.rs
  • pkgs/num/src/lib.rs
  • pkgs/num/src/util.rs
  • pkgs/p2p_core/src/codec.rs
  • pkgs/p2p_core/src/error.rs
  • pkgs/p2p_core/src/lib.rs
  • pkgs/p2p_core/src/msg/addr.rs
  • pkgs/p2p_core/src/msg/compact_filters.rs
  • pkgs/p2p_core/src/msg/gov.rs
  • pkgs/p2p_core/src/msg/headers.rs
  • pkgs/p2p_core/src/msg/headers2.rs
  • pkgs/p2p_core/src/msg/inv.rs
  • pkgs/p2p_core/src/msg/mod.rs
  • pkgs/p2p_core/src/msg/ping.rs
  • pkgs/p2p_core/src/msg/version.rs
  • pkgs/p2p_core/src/primitives/command.rs
  • pkgs/p2p_core/src/primitives/compressed_header.rs
  • pkgs/p2p_core/src/primitives/inventory.rs
  • pkgs/p2p_core/src/primitives/magic.rs
  • pkgs/p2p_core/src/primitives/mn_list.rs
  • pkgs/p2p_core/src/primitives/protocol_version.rs
  • pkgs/p2p_core/src/primitives/service_flags.rs
  • pkgs/p2p_core/src/primitives/short_id.rs
  • pkgs/p2p_core/src/primitives/user_agent.rs
  • pkgs/params/Cargo.toml
  • pkgs/params/src/mainnet.rs
  • pkgs/params/src/regtest.rs
  • pkgs/params/src/test3.rs
  • pkgs/params/tests/genesis_valid.rs
  • pkgs/primitives/Cargo.toml
  • pkgs/primitives/src/block.rs
  • pkgs/primitives/src/codec.rs
  • pkgs/primitives/src/gov.rs
  • pkgs/primitives/src/hash.rs
  • pkgs/primitives/src/lib.rs
  • pkgs/primitives/src/payload/assetlock.rs
  • pkgs/primitives/src/payload/assetunlock.rs
  • pkgs/primitives/src/payload/cbtx.rs
  • pkgs/primitives/src/payload/mnhftx.rs
  • pkgs/primitives/src/payload/mod.rs
  • pkgs/primitives/src/payload/proregtx.rs
  • pkgs/primitives/src/payload/proupregtx.rs
  • pkgs/primitives/src/payload/prouprevtx.rs
  • pkgs/primitives/src/payload/proupservtx.rs
  • pkgs/primitives/src/payload/quorum.rs
  • pkgs/primitives/src/script.rs
  • pkgs/primitives/src/support.rs
  • pkgs/primitives/src/transaction.rs
  • pkgs/primitives/src/types/addrv1.rs
  • pkgs/primitives/src/types/addrv2.rs
  • pkgs/primitives/src/types/netaddr.rs
  • pkgs/primitives/src/types/netinfo.rs
  • pkgs/types/Cargo.toml
  • pkgs/types/marker/Cargo.toml
  • pkgs/types/marker/src/lib.rs
  • pkgs/types/src/codec.rs
  • pkgs/types/src/entity.rs
  • pkgs/types/src/hex.rs
  • pkgs/types/src/lib.rs
  • pkgs/types/src/uint.rs
  • unconv.toml
💤 Files with no reviewable changes (2)
  • pkgs/primitives/src/hash.rs
  • pkgs/params/Cargo.toml

Comment on lines +15 to +24
/** Holds if `t` carries `#[derive(...name...)]` detected via source-line scanning. */
bindingset[name]
predicate hasDerive(TypeItem t, string name) {
exists(Attr a, int srcLine, string relPath, string content |
a = t.getAnAttr() and
a.getMeta().getPath().getSegment().getIdentifier().getText() = "derive" and
text = a.getMeta().getTokenTree().toAbbreviatedString()
fileRelPath(fileOf(t), relPath) and
sourceLineContent(relPath, srcLine, content) and
content.regexpMatch(".*\\b" + name + "\\b.*") and
srcLine >= a.getLocation().getStartLine() and
srcLine <= a.getLocation().getEndLine()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether TypeId/Unencodable appears in non-derive attributes that this
# predicate would currently treat as coverage.
rg -nP '#\[(?!derive|cfg_attr)[^\]]*\b(TypeId|Unencodable)\b' --glob '*.rs'

Repository: dashpay/base-sdk

Length of output: 154


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant query file and where hasDerive is used.
git ls-files 'contrib/codeql/lib/policy.qll' 'contrib/codeql/lib/*.qll' | cat
echo '--- policy.qll outline ---'
ast-grep outline contrib/codeql/lib/policy.qll --view expanded || true
echo '--- hasDerive / isEnforcedCrate usages ---'
rg -n '\bhasDerive\b|\bisEnforcedCrate\b|\bisUnencodable\b|\bArrayBuf\b|\bHashable\b' contrib/codeql/lib -g '*.qll'
echo '--- policy.qll excerpt ---'
sed -n '1,120p' contrib/codeql/lib/policy.qll

Repository: dashpay/base-sdk

Length of output: 5252


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- source_lines.qll outline ---'
ast-grep outline contrib/codeql/lib/source_lines.qll --view expanded || true
echo '--- sourceLineContent / fileRelPath definitions and uses ---'
rg -n '\bsourceLineContent\b|\bfileRelPath\b|\bgetLocation\(\)\.get(Start|End)Line\b|\bgetAnAttr\b|\bAttr\b' contrib/codeql/lib -g '*.qll'
echo '--- source_lines.qll excerpt ---'
sed -n '1,220p' contrib/codeql/lib/source_lines.qll
echo '--- policy.qll around hasDerive ---'
sed -n '1,60p' contrib/codeql/lib/policy.qll

Repository: dashpay/base-sdk

Length of output: 2457


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- hasDerive callers ---'
rg -n '\bhasDerive\s*\(' contrib/codeql/lib -g '*.qll' -A2 -B2

echo '--- attribute lines containing Unencodable or TypeId ---'
rg -n '#\[[^]]*(Unencodable|TypeId)[^]]*\]' --glob '*.rs' .

echo '--- doc / cfg_attr lines containing Unencodable or TypeId ---'
rg -n '#\[(doc|cfg_attr)[^]]*(Unencodable|TypeId)[^]]*\]' --glob '*.rs' .

Repository: dashpay/base-sdk

Length of output: 10831


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- policy.qll around derived checks ---'
sed -n '140,180p' contrib/codeql/lib/policy.qll

echo '--- related attribute helpers in files.qll and filters.qll ---'
sed -n '1,80p' contrib/codeql/lib/files.qll
echo '---'
sed -n '1,90p' contrib/codeql/lib/filters.qll

Repository: dashpay/base-sdk

Length of output: 6429


Restrict hasDerive to derive-style attributes.
The raw text scan can be satisfied by unrelated #[doc], #[cfg], or other attribute payloads, so isNotEncodable can treat a non-derive attribute as proof of #[derive(Unencodable)]. Filter for derive/cfg_attr or inspect the attribute meta directly.

🤖 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 `@contrib/codeql/lib/policy.qll` around lines 15 - 24, The hasDerive predicate
is currently matching any attribute text on the same lines, so unrelated attrs
like doc or cfg can be mistaken for derive. Update hasDerive in policy.qll to
only accept derive-style attributes by checking the attribute kind or meta
directly, or by filtering to derive/cfg_attr before scanning the source text.
Keep the existing TypeItem/Attr logic, but make sure isNotEncodable can only
infer Unencodable from a real #[derive(...)]-style attribute.

Comment on lines +212 to 218
/** Holds if file `f` is in a crate subject to codec and ordering rules. */
predicate isEnforcedCrate(File f) {
f.getAbsolutePath().matches("%/pkgs/num/%") or
f.getAbsolutePath().matches("%/pkgs/types/%") or
f.getAbsolutePath().matches("%/pkgs/primitives/%") or
f.getAbsolutePath().matches("%/pkgs/p2p_core/%")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Exclude the proc-macro marker crate from isEnforcedCrate.

Line 214 matches pkgs/types/marker/** as part of pkgs/types, but that crate is the proc-macro implementation rather than a codec crate. This can make declaration-order/codec policy checks run on helper macro code, unlike the Semgrep policy which explicitly excludes /pkgs/types/marker/**.

Proposed fix
 predicate isEnforcedCrate(File f) {
-  f.getAbsolutePath().matches("%/pkgs/num/%") or
-  f.getAbsolutePath().matches("%/pkgs/types/%") or
-  f.getAbsolutePath().matches("%/pkgs/primitives/%") or
-  f.getAbsolutePath().matches("%/pkgs/p2p_core/%")
+  (
+    f.getAbsolutePath().matches("%/pkgs/num/%") or
+    f.getAbsolutePath().matches("%/pkgs/types/%") or
+    f.getAbsolutePath().matches("%/pkgs/primitives/%") or
+    f.getAbsolutePath().matches("%/pkgs/p2p_core/%")
+  ) and
+  not f.getAbsolutePath().matches("%/pkgs/types/marker/%")
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** Holds if file `f` is in a crate subject to codec and ordering rules. */
predicate isEnforcedCrate(File f) {
f.getAbsolutePath().matches("%/pkgs/num/%") or
f.getAbsolutePath().matches("%/pkgs/types/%") or
f.getAbsolutePath().matches("%/pkgs/primitives/%") or
f.getAbsolutePath().matches("%/pkgs/p2p_core/%")
}
/** Holds if file `f` is in a crate subject to codec and ordering rules. */
predicate isEnforcedCrate(File f) {
(
f.getAbsolutePath().matches("%/pkgs/num/%") or
f.getAbsolutePath().matches("%/pkgs/types/%") or
f.getAbsolutePath().matches("%/pkgs/primitives/%") or
f.getAbsolutePath().matches("%/pkgs/p2p_core/%")
) and
not f.getAbsolutePath().matches("%/pkgs/types/marker/%")
}
🤖 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 `@contrib/codeql/lib/policy.qll` around lines 212 - 218, Exclude the proc-macro
marker crate from isEnforcedCrate by tightening the path checks in policy.qll so
the pkgs/types rule does not match pkgs/types/marker/**. Update the
isEnforcedCrate predicate to keep the existing crate coverage for num, types,
primitives, and p2p_core while explicitly filtering out the marker crate,
matching the Semgrep policy behavior.

Comment on lines +56 to +70
- id: macro-no-bare-foreign-crate
message: >
rooted foreign-crate paths (::crate::) in macros must route
through $crate::__private for hygiene
severity: ERROR
languages: [rust]
paths:
include:
- "*.rs"
exclude:
- /pkgs/types/marker/**
patterns:
- pattern-regex: '(?<![:\w])::[a-z_]+::'
- pattern-not-regex: "::(?:core|alloc|std|serde)::"
- pattern-not-regex: '\$crate::__private::'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Show current matches so false positives outside macro_rules! bodies can be inspected.
rg -nP '(?<![:\w])::[a-z_]+::' --glob '*.rs' -g '!pkgs/types/marker/**'

Repository: dashpay/base-sdk

Length of output: 154


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant Semgrep workspace file and nearby rule definitions.
git ls-files contrib/semgrep/workspace.yml
wc -l contrib/semgrep/workspace.yml
sed -n '1,140p' contrib/semgrep/workspace.yml

Repository: dashpay/base-sdk

Length of output: 4585


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find any rule or documentation that scopes Rust macro checks or uses this regex family.
rg -n "macro-no-bare-foreign-crate|pattern-regex|macro" contrib/semgrep workspace.yml .github . -g '!**/node_modules/**'

Repository: dashpay/base-sdk

Length of output: 10131


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for rooted crate paths in Rust source, then inspect whether they live inside macro bodies.
rg -n --glob '*.rs' '::[A-Za-z0-9_]+::' pkgs contrib | sed -n '1,200p'

Repository: dashpay/base-sdk

Length of output: 19431


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show all rooted crate-path occurrences in Rust source and a small sample of nearby context.
python3 - <<'PY'
import re
from pathlib import Path

pat = re.compile(r'::[A-Za-z0-9_]+::')
roots = []
for p in Path('.').rglob('*.rs'):
    if '/target/' in str(p):
        continue
    try:
        text = p.read_text()
    except Exception:
        continue
    for m in pat.finditer(text):
        line = text.count('\n', 0, m.start()) + 1
        start = text.rfind('\n', 0, m.start()) + 1
        end = text.find('\n', m.start())
        if end == -1:
            end = len(text)
        snippet = text[start:end]
        roots.append((str(p), line, snippet.strip()))
        if len(roots) >= 80:
            break
    if len(roots) >= 80:
        break

for item in roots:
    print(f"{item[0]}:{item[1]}:{item[2]}")
PY

Repository: dashpay/base-sdk

Length of output: 6817


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Check whether any Rust source contains rooted paths in ordinary code vs macro bodies.
python3 - <<'PY'
from pathlib import Path
import re

files = [
    Path("pkgs/dev/src/corpus.rs"),
    Path("pkgs/num/src/hash.rs"),
    Path("pkgs/types/src/serialize.rs"),
    Path("contrib/samples/parser/parser.rs"),
]
for p in files:
    if not p.exists():
        continue
    text = p.read_text()
    print(f"\n== {p} ==")
    for m in re.finditer(r'::[A-Za-z0-9_]+::', text):
        line = text.count('\n', 0, m.start()) + 1
        start = text.rfind('\n', 0, m.start()) + 1
        end = text.find('\n', m.start())
        if end == -1:
            end = len(text)
        print(f"{line}:{text[start:end].rstrip()}")
PY

# 2) Look for any crate/package identifiers with digits in Cargo manifests.
rg -n '^\s*name\s*=\s*".*[0-9].*"' Cargo.toml **/Cargo.toml

Repository: dashpay/base-sdk

Length of output: 4158


🌐 Web query:

Semgrep paths include glob "*.rs" matches files in subdirectories or only repository root pathspec semantics

💡 Result:

In Semgrep, path filtering patterns—such as those used in the paths configuration block or CLI --include/--exclude flags—follow glob syntax that is recursive by default [1][2]. A pattern like ".rs" is not restricted to the repository root [1][2]. Instead, it matches files with that extension anywhere in the project tree, including all subdirectories [1]. Key points regarding Semgrep path globbing behavior: 1. Recursive Matching: Patterns like ".rs" or "static/.js" match files at any directory depth within the project [1]. They are not anchored to the root unless explicitly structured to be [2]. 2. Globstar Support: Semgrep supports `` (globstar) syntax to explicitly represent directory recursion (e.g., tests//*.js will match all .js files within `tests` and any of its subdirectories) [1][2]. 3. Semantics: Current Semgrep versions (specifically under Semgrepignore v2 and modern rule configurations) align their globbing semantics closely with standard `.gitignore` behavior [3][2]. This means simple patterns like "foo" are treated as floating (matching `foo` anywhere) [2]. To match only a specific path relative to the root, one would use anchored patterns (e.g., starting with `/`) if the specific implementation supports it, though for general rule filtering, the recursive "match anywhere" behavior is the default [2]. In summary, a pattern like ".rs" will successfully match all Rust files throughout your entire repository, not just those in the root [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether any rooted crate paths use identifiers with digits/underscores that the regex would miss.
rg -n '::[A-Za-z0-9_]*[0-9][A-Za-z0-9_]*::' --glob '*.rs' pkgs contrib

# Show any literal rooted proc_macro2 references.
rg -n '::proc_macro2::|::xxhash_rust::|::wasm_bindgen::|::dash_types::|::dash_primitives::' --glob '*.rs' pkgs contrib

Repository: dashpay/base-sdk

Length of output: 6189


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether any rooted crate paths use identifiers with digits/underscores that the regex would miss.
rg -n '::[A-Za-z0-9_]*[0-9][A-Za-z0-9_]*::' --glob '*.rs' pkgs contrib

# Show any literal rooted proc_macro2 references and a few related foreign-crate roots.
rg -n '::proc_macro2::|::xxhash_rust::|::wasm_bindgen::|::dash_types::|::dash_primitives::' --glob '*.rs' pkgs contrib

Repository: dashpay/base-sdk

Length of output: 6189


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the proc-macro file where rooted paths appear to see whether they're emitted from macro code.
cat -n pkgs/types/marker/src/lib.rs | sed -n '1,120p'

Repository: dashpay/base-sdk

Length of output: 2224


Scope this rule to macro-generated code and allow digits in crate names. paths.include: ["*.rs"] is recursive, so this rule applies across all Rust files, and [a-z_]+ misses crates like proc_macro2.

🤖 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 `@contrib/semgrep/workspace.yml` around lines 56 - 70, The Semgrep rule
macro-no-bare-foreign-crate is too broadly scoped and its crate-name regex is
too restrictive. Update the rule in workspace.yml so paths.include only targets
macro-generated code instead of all Rust files, and adjust the pattern-regex to
allow digits in crate names (for example, crate names like proc_macro2). Keep
the existing exclusions and the $crate::__private hygiene check intact while
narrowing the scope and broadening the crate-name match.

Comment thread pkgs/dev/build.rs
Comment on lines +64 to +71
#[derive(Default)]
struct ScanResult {
/// `macro_rules!` names whose body contains `TypeId`.
type_id_macros: BTreeSet<String>,
/// Type names with direct `#[derive(TypeId)]`.
names: BTreeSet<String>,
/// Unresolved `(macro_name, type_name)` from invocation sites.
pending: Vec<(String, String)>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Don't deduplicate discovered type names before the collision pass.

TypeId is computed from the bare type name, but names: BTreeSet<String> collapses duplicate spellings across crates/modules before hashing. That means two different Foo types can share the same generated id and this script will never report it.

Suggested fix
 #[derive(Default)]
 struct ScanResult {
   /// `macro_rules!` names whose body contains `TypeId`.
   type_id_macros: BTreeSet<String>,
-  /// Type names with direct `#[derive(TypeId)]`.
-  names: BTreeSet<String>,
+  /// Type names with direct `#[derive(TypeId)]`. Keep duplicates so
+  /// same-name collisions across crates are still detected.
+  names: Vec<String>,
   /// Unresolved `(macro_name, type_name)` from invocation sites.
   pending: Vec<(String, String)>,
 }

Then update the insertion sites to push(...) and fail if the same name appears more than once during the hash pass, ideally including the source paths in the panic message.

🤖 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 `@pkgs/dev/build.rs` around lines 64 - 71, Do not deduplicate type names before
the collision check in build.rs: ScanResult::names currently uses
BTreeSet<String>, which hides duplicate `Foo` spellings across crates/modules
before the TypeId hash pass. Change ScanResult and the related insertion sites
in the scan logic to collect names with push semantics, then detect repeated
names during the hash/collision pass and panic on duplicates, ideally including
the source paths or other provenance in the error message.

Comment thread pkgs/num/src/hash.rs
}

fn encode(&self, buf: &mut ::alloc::vec::Vec<u8>) {
fn encode(&self, buf: &mut impl crate::__private::dash_types::codec::EncodeBuf) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use $crate for the generated EncodeBuf path.

Line 309 is the only path in this macro using invocation-site crate::; use $crate so exported or re-used macro expansions keep resolving through dash_num.

Proposed fix
-      fn encode(&self, buf: &mut impl crate::__private::dash_types::codec::EncodeBuf) {
+      fn encode(&self, buf: &mut impl $crate::__private::dash_types::codec::EncodeBuf) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn encode(&self, buf: &mut impl crate::__private::dash_types::codec::EncodeBuf) {
fn encode(&self, buf: &mut impl $crate::__private::dash_types::codec::EncodeBuf) {
🤖 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 `@pkgs/num/src/hash.rs` at line 309, The generated EncodeBuf path in the macro
still uses invocation-site crate::, which breaks when the macro is exported or
reused. Update the encode-related path in the hash macro (the fn encode
signature in the generated impl) to use
$crate::__private::dash_types::codec::EncodeBuf instead of crate::, so it always
resolves through dash_num regardless of expansion site.

Comment on lines +45 to +46
fn _assert<T: $crate::__private::dash_types::codec::BaseCodec + $crate::__private::dash_types::codec::TypeId>() {}
fn _check() { _assert::<$ty>(); }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Wrap the TypeId assertion bound to stay within the Rust line-width limit.

Line 45 exceeds the configured 120-character maximum.

Proposed fix
-      fn _assert<T: $crate::__private::dash_types::codec::BaseCodec + $crate::__private::dash_types::codec::TypeId>() {}
+      fn _assert<T>()
+      where
+        T: $crate::__private::dash_types::codec::BaseCodec
+          + $crate::__private::dash_types::codec::TypeId,
+      {
+      }
       fn _check() { _assert::<$ty>(); }

As per coding guidelines, **/*.rs must enforce a max line width of 120 characters.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn _assert<T: $crate::__private::dash_types::codec::BaseCodec + $crate::__private::dash_types::codec::TypeId>() {}
fn _check() { _assert::<$ty>(); }
fn _assert<T>()
where
T: $crate::__private::dash_types::codec::BaseCodec
$crate::__private::dash_types::codec::TypeId,
{
}
fn _check() { _assert::<$ty>(); }
🤖 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 `@pkgs/primitives/src/codec.rs` around lines 45 - 46, The TypeId assertion in
the macro helper is too long for the Rust line-width limit; wrap the bound in
the `_assert` function in `codec.rs` so the `BaseCodec` and `TypeId` constraints
fit within 120 characters. Keep the change localized to the `_assert`/`_check`
helper and preserve the existing type-check behavior while splitting the trait
bounds across multiple lines.

Source: Coding guidelines

Comment on lines 214 to 229
let take = src.len().min(required);
// nosemgrep: codec-no-raw-extend
buf.extend_from_slice(&src[..take]);
if take > 0 {
// nosemgrep: codec-no-raw-extend
buf.extend_from_slice(&src[..take - 1]);
// Mask padding bits in the final source byte.
let remainder = (self.num_bits % 8) as u32;
let last_byte = if remainder != 0 {
src[take - 1] & ((1u8 << remainder) - 1)
} else {
src[take - 1]
};
buf.push(last_byte);
}
// Pad with zero bytes if data is shorter than required.
for _ in take..required {
buf.push(0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Mask the actual final wire byte.

When self.data.len() < required and num_bits % 8 != 0, this masks the last copied source byte instead of the last encoded byte. For example, num_bits = 10 with data = [0xff] now serializes as [0x03, 0x00] instead of [0xff, 0x00]. Because DynBitset is embedded in quorum commitments, this changes both wire bytes and hashes.

Patch idea
   fn encode(&self, buf: &mut impl EncodeBuf) {
     codec::write_compact_u64(self.num_bits, buf);
     let required = (self.num_bits as usize).div_ceil(8);
-    let src = &self.data;
-    let take = src.len().min(required);
-    if take > 0 {
-      // nosemgrep: codec-no-raw-extend
-      buf.extend_from_slice(&src[..take - 1]);
-      // Mask padding bits in the final source byte.
-      let remainder = (self.num_bits % 8) as u32;
-      let last_byte = if remainder != 0 {
-        src[take - 1] & ((1u8 << remainder) - 1)
-      } else {
-        src[take - 1]
-      };
-      buf.push(last_byte);
-    }
-    // Pad with zero bytes if data is shorter than required.
-    for _ in take..required {
-      buf.push(0);
-    }
+    let remainder = (self.num_bits % 8) as u32;
+    for i in 0..required {
+      let mut byte = self.data.get(i).copied().unwrap_or(0);
+      if i + 1 == required && remainder != 0 {
+        byte &= (1u8 << remainder) - 1;
+      }
+      buf.push(byte);
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let take = src.len().min(required);
// nosemgrep: codec-no-raw-extend
buf.extend_from_slice(&src[..take]);
if take > 0 {
// nosemgrep: codec-no-raw-extend
buf.extend_from_slice(&src[..take - 1]);
// Mask padding bits in the final source byte.
let remainder = (self.num_bits % 8) as u32;
let last_byte = if remainder != 0 {
src[take - 1] & ((1u8 << remainder) - 1)
} else {
src[take - 1]
};
buf.push(last_byte);
}
// Pad with zero bytes if data is shorter than required.
for _ in take..required {
buf.push(0);
let remainder = (self.num_bits % 8) as u32;
for i in 0..required {
let mut byte = self.data.get(i).copied().unwrap_or(0);
if i + 1 == required && remainder != 0 {
byte &= (1u8 << remainder) - 1;
}
buf.push(byte);
}
🤖 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 `@pkgs/primitives/src/support.rs` around lines 214 - 229, The bit-masking logic
in the serialization path is applied to the wrong byte when the source is
shorter than required; in the `support.rs` code around the `take`/`last_byte`
handling for `DynBitset`, ensure the final encoded wire byte is masked instead
of masking the last copied source byte. Update the logic so padding behavior
stays unchanged, but the partial-byte mask is applied to the actual last output
byte in the buffer when `self.num_bits % 8 != 0`, preserving the intended
serialized bytes and downstream hashes.

Comment on lines +7 to +13
[lib]
proc-macro = true

[dependencies]
quote = "1"
syn = "2"
xxhash-rust = { version = "0.8", features = ["xxh32"] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the standard crate feature table.

This new crate has no [features] section, so it misses the workspace feature contract.

Proposed fix
 [lib]
 proc-macro = true
 
+[features]
+default = []
+std = []
+full = ["std"]
+
 [dependencies]
 quote = "1"
 syn = "2"
 xxhash-rust = { version = "0.8", features = ["xxh32"] }

As per coding guidelines: **/Cargo.toml: "Configure Rust crate features with default = [], std = [...], full = ["std"]".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[lib]
proc-macro = true
[dependencies]
quote = "1"
syn = "2"
xxhash-rust = { version = "0.8", features = ["xxh32"] }
[lib]
proc-macro = true
[features]
default = []
std = []
full = ["std"]
[dependencies]
quote = "1"
syn = "2"
xxhash-rust = { version = "0.8", features = ["xxh32"] }
🤖 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 `@pkgs/types/marker/Cargo.toml` around lines 7 - 13, The new crate is missing
the standard feature contract in its Cargo.toml, so add a [features] table for
the crate and follow the workspace convention by defining default = [], std =
[...], and full = ["std"]. Update the package’s feature configuration in
Cargo.toml so the crate opts into the shared feature layout and exposes its
dependencies through the std feature as expected.

Source: Coding guidelines

Comment on lines +25 to +45
let expanded = quote! {
impl #impl_generics ::dash_primitives::__CodecMarker for #name #ty_generics #where_clause {}
impl #impl_generics ::dash_primitives::__UnencodableMarker for #name #ty_generics #where_clause {}
};

expanded.into()
}

/// Derives `TypeId` with a compile-time XXH32 hash of the type name.
#[proc_macro_derive(TypeId)]
pub fn derive_type_id(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

let name_str = name.to_string();
let id = xxh32(name_str.as_bytes(), 0);

let expanded = quote! {
impl #impl_generics ::dash_types::codec::TypeId for #name #ty_generics #where_clause {
const TYPE_ID: u32 = #id;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

echo "Self-aliases:"
rg -n --type=rust 'extern\s+crate\s+self\s+as\s+(dash_types|dash_primitives)\b' pkgs/types pkgs/primitives || true

echo "TypeId/Unencodable derive sites:"
rg -n -U --type=rust '#\s*\[\s*derive\s*\([^]]*(TypeId|Unencodable)' pkgs/types pkgs/primitives pkgs/p2p_core pkgs/num || true

Repository: dashpay/base-sdk

Length of output: 9616


🏁 Script executed:

#!/bin/bash
set -eu

echo "pkgs/types/src/lib.rs:"
sed -n '1,120p' pkgs/types/src/lib.rs

echo
echo "pkgs/types/marker/src/lib.rs:"
sed -n '1,120p' pkgs/types/marker/src/lib.rs

echo
echo "References to dash_types alias or path usage:"
rg -n --type=rust 'extern\s+crate\s+self\s+as\s+dash_types\b|::dash_types::|dash_types::' pkgs/types pkgs/primitives pkgs/num pkgs/p2p_core || true

Repository: dashpay/base-sdk

Length of output: 14545


Add a dash_types self-alias in pkgs/types/src/lib.rs
::dash_types::codec::TypeId is emitted by the derive macro, and pkgs/types uses that derive from its own local macros, so the crate needs extern crate self as dash_types; for the generated path to resolve.

🤖 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 `@pkgs/types/marker/src/lib.rs` around lines 25 - 45, The derive macros in
marker use an absolute path to ::dash_types::codec::TypeId, so the pkgs/types
crate must expose itself under that name for the generated path to resolve. Add
a self-alias in pkgs/types/src/lib.rs with extern crate self as dash_types; near
the crate-level exports so the TypeId derive in pkgs/types/marker/src/lib.rs can
reference the local crate correctly. Keep the alias alongside the other public
module setup used by the dash_types crate root.

Comment thread pkgs/types/src/lib.rs
#[cfg(feature = "serde")]
pub mod serialize;

pub use dash_types_marker::{TypeId, Unencodable};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Don't re-export Unencodable from dash_types yet.

The derive still expands against ::dash_primitives::__CodecMarker / ::__UnencodableMarker, so dash_types::Unencodable will fail for crates that only depend on dash_types. Either keep this derive exposed from dash_primitives, or change the macro to target a path that dash_types itself re-exports.

🤖 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 `@pkgs/types/src/lib.rs` at line 25, Do not re-export Unencodable from
dash_types in the public lib.rs yet; the derive macros still resolve against
dash_primitives::__CodecMarker and __UnencodableMarker, so exposing
dash_types::Unencodable would break crates that only depend on dash_types. Keep
the marker available through dash_primitives for now, or update the derive
expansion to reference a path that dash_types re-exports consistently, and
verify the symbols involved in pkgs/types/src/lib.rs and the related derive
macro path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant