Skip to content

feat(encoding,block): accept Uint8Array as input alongside Buffer#315

Open
thepastaclaw wants to merge 4 commits into
dashpay:masterfrom
thepastaclaw:feat-uint8array-input
Open

feat(encoding,block): accept Uint8Array as input alongside Buffer#315
thepastaclaw wants to merge 4 commits into
dashpay:masterfrom
thepastaclaw:feat-uint8array-input

Conversation

@thepastaclaw
Copy link
Copy Markdown

@thepastaclaw thepastaclaw commented May 26, 2026

Why

Downstream consumers, specifically @dashevo/dapi-client's BlockHeadersProvider, want to stop wrapping protobuf bytes in Buffer.from(...) before passing them to dashcore-lib. Requiring Buffer at that boundary leaks Node-specific handling into web-targeted code.

What

This widens the BufferReader constructor, BlockHeader._from, and byte helpers in lib/util/buffer.js to accept plain Uint8Array alongside Buffer. Plain Uint8Array inputs are promoted to Buffer at the boundary so existing Buffer-only read methods continue to work unchanged, and existing Buffer callers keep working unchanged.

Scope

This only touches the input-acceptance path through BlockHeader construction. Other public entry points remain untouched.

Test plan

  • Added Uint8Array coverage in test/encoding/bufferreader.js and test/block/blockheader.js
  • Confirmed existing Buffer-path assertions still pass in the focused test run: npx mocha --no-timeout test/encoding/bufferreader.js test/block/blockheader.js
  • Ran npm test:
    • test:types passed
    • test:node failed in existing GovObject/Proposal tests with Invalid Timespan (12 failures), so test:browser did not start
  • Ran git diff --check

Summary by CodeRabbit

  • New Features

    • Block header parsing and low-level buffer reading now accept Uint8Array inputs in addition to existing supported types, improving input flexibility and interoperability.
  • Tests

    • Added unit tests confirming Uint8Array handling for block header parsing and buffer reader behavior, and verifying consistent serialized output and read values compared to existing Buffer-based processing.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0b838a0b-4f4c-4ee5-8d96-79a6f350c9e8

📥 Commits

Reviewing files that changed from the base of the PR and between f12c140 and 18e6f55.

📒 Files selected for processing (4)
  • lib/block/blockheader.js
  • lib/encoding/bufferreader.js
  • test/block/blockheader.js
  • test/encoding/bufferreader.js
✅ Files skipped from review due to trivial changes (1)
  • lib/block/blockheader.js

📝 Walkthrough

Walkthrough

BufferReader now accepts Uint8Array inputs by converting them to Node Buffer before storage. BlockHeader's type annotations are updated to reflect Uint8Array support. Tests validate BufferReader's Uint8Array conversion and confirm BlockHeader parsing produces identical results whether constructed from Uint8Array or Buffer.

Changes

Uint8Array input support

Layer / File(s) Summary
BufferReader Uint8Array conversion and validation
lib/encoding/bufferreader.js, test/encoding/bufferreader.js
BufferReader constructor extended to detect and convert Uint8Array to Node Buffer; test verifies the conversion and confirms integer reads produce correct values.
BlockHeader type annotations and end-to-end validation
lib/block/blockheader.js, test/block/blockheader.js
BlockHeader constructor and _from JSDoc broadened to declare Uint8Array as an accepted input; test verifies parsing a Uint8Array and a Buffer from the same source produce identical fields and serialization.

🎯 2 (Simple) | ⏱️ ~8 minutes

🐰 With Uint8Array now in the mix,
BufferReader's conversion fixed,
BlockHeader types align so tight,
Tests prove the output shines just right! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: accepting Uint8Array as input alongside Buffer in encoding and block modules.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
lib/block/blockheader.js (1)

15-15: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update JSDoc to reflect Uint8Array acceptance.

The JSDoc at lines 15 and 43 states the parameter accepts "Buffer" but the implementation now also accepts plain Uint8Array inputs (via the isBytes check at line 50). Update the parameter documentation to clarify that both Buffer and Uint8Array are accepted.

📝 Suggested JSDoc updates

Line 15:

- * `@param` {BlockHeader.fromObjectParams|Buffer} arg - A Buffer, JSON string, or Object
+ * `@param` {BlockHeader.fromObjectParams|Buffer|Uint8Array} arg - A Buffer, Uint8Array, JSON string, or Object

Line 43:

- * `@param` {BlockHeader.fromObjectParams|Buffer} arg - A Buffer, JSON string or Object
+ * `@param` {BlockHeader.fromObjectParams|Buffer|Uint8Array} arg - A Buffer, Uint8Array, JSON string or Object

Also applies to: 43-43

🤖 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 `@lib/block/blockheader.js` at line 15, The JSDoc for the
constructor/BlockHeader.fromObjectParams currently lists "Buffer" but the
implementation also accepts Uint8Array (see the isBytes check used in the
parsing logic); update the `@param` annotations that mention "Buffer" to
"Buffer|Uint8Array" (and any corresponding `@typedef` or return docs) so both
Buffer and Uint8Array are documented consistently for the parameter referenced
as BlockHeader.fromObjectParams; ensure both the top-level param line and the
secondary occurrence (the one around the JSON/Object parsing docs) are updated.
🤖 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.

Outside diff comments:
In `@lib/block/blockheader.js`:
- Line 15: The JSDoc for the constructor/BlockHeader.fromObjectParams currently
lists "Buffer" but the implementation also accepts Uint8Array (see the isBytes
check used in the parsing logic); update the `@param` annotations that mention
"Buffer" to "Buffer|Uint8Array" (and any corresponding `@typedef` or return docs)
so both Buffer and Uint8Array are documented consistently for the parameter
referenced as BlockHeader.fromObjectParams; ensure both the top-level param line
and the secondary occurrence (the one around the JSON/Object parsing docs) are
updated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3f01bd9b-c104-4f45-8b39-d2e06512d62a

📥 Commits

Reviewing files that changed from the base of the PR and between c3c3fe5 and d0b71ff.

📒 Files selected for processing (5)
  • lib/block/blockheader.js
  • lib/encoding/bufferreader.js
  • lib/util/buffer.js
  • test/block/blockheader.js
  • test/encoding/bufferreader.js

Copy link
Copy Markdown
Author

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

The runtime change is real and safely normalizes plain Uint8Array inputs back to Buffer inside BufferReader, so the new byte-handling path itself looks correct. The one in-scope gap is that BlockHeader's public TypeScript declarations still reject the new static entry points this PR enables at runtime. That leaves the feature incomplete for typed consumers even though the JavaScript tests now cover it.

Blocking finding (not on a changed diff line): typings/block/BlockHeader.d.ts lines 72-82 still declare fromRawBlock as Buffer | string and fromBuffer as Buffer, but this PR now accepts Uint8Array at runtime through BufferReader. TypeScript/web consumers cannot use the newly supported API without casts, so the published declarations need to be widened too.

🔴 1 blocking

1 additional finding(s) omitted (not in diff).

Out-of-scope follow-up suggestions (1)

These are valid observations, but they are outside this PR's scope and should be handled in separate issues or author/maintainer-requested PRs rather than blocking this review.

  • BufferReader widens more public parser entry points than BlockHeader alone — Because the constructor change in lib/encoding/bufferreader.js sits underneath many fromBuffer(...) and fromRawBlock(...) helpers, this PR implicitly broadens other runtime entry points such as Block, MerkleBlock, ChainLock, InstantLock, and several transaction payload parsers. That may be acceptable, and input widening is not inherently breaking, but the PR only adds focused tests and docs around BlockHeader, so the broader contract change should be audited separately instead of expanding this review beyond the current scope.
    • Follow-up: Create a separate issue or author-requested PR to audit all public APIs that instantiate BufferReader directly, then update typings/tests/docs consistently where Uint8Array support is intended.

Note: this is a self-review, so GitHub rejected REQUEST_CHANGES; posting as COMMENT while retaining the blocking finding above.

@thepastaclaw thepastaclaw force-pushed the feat-uint8array-input branch from f12c140 to 18e6f55 Compare May 26, 2026 19:26
Copy link
Copy Markdown
Author

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

PR widens BufferReader and BlockHeader to accept plain Uint8Array at runtime by normalizing to Buffer at the boundary. Implementation is small and preserves Buffer behavior, but the published TypeScript declarations in typings/block/BlockHeader.d.ts were not updated, so TS consumers (the stated motivation for this PR) still cannot pass Uint8Array without casts. The latest delta from f12c140 only adds GovObject/Proposal fake-timer fixtures (bundled via merge of #316) and does not address the prior blocking finding.

🔴 1 blocking (carried-forward prior finding)

Carried-forward prior finding — STILL VALID

typings/block/BlockHeader.d.ts:54-82 — BlockHeader typings still reject Uint8Array input accepted at runtime

Verified STILL VALID at 18e6f55. The PR widens the runtime contract: lib/util/buffer.js:61-62 isBuffer() now accepts any Uint8Array; lib/encoding/bufferreader.js:24-27 normalizes Uint8Array to Buffer; lib/block/blockheader.js:48-52, 100-107, 115-118 route Uint8Array through that widened path; and the JSDoc at lib/block/blockheader.js:15, 43 advertises Buffer|Uint8Array.

The published declarations in typings/block/BlockHeader.d.ts were not updated:

  • constructor() (line 55) has no signature for byte/object input, so new BlockHeader(uint8array) is unhelped at the type level.
  • static fromRawBlock(data: Buffer | string) (line 76) rejects Uint8Array.
  • static fromBuffer(buf: Buffer) (line 82) rejects Uint8Array.

The stated motivation for this PR is downstream TS consumers like @dashevo/dapi-client's BlockHeadersProvider. Without widened declarations, those consumers must use as any casts, defeating the PR's purpose. test-d/index.test-d.ts does not exercise these factories with Uint8Array, so npm run test:types would not catch the gap.

Widen the declarations to match the runtime and add a test-d assertion that BlockHeader.fromBuffer(new Uint8Array(...)) and BlockHeader.fromRawBlock(new Uint8Array(...)) type-check.

Suggested declaration update
export class BlockHeader {
  constructor(arg?: Buffer | Uint8Array | BlockHeader.fromObjectParams);

  id: string;
  hash: string;
  version: number;
  prevHash: string | Buffer;
  merkleRoot: string | Buffer;
  time: number;
  bits: number;
  nonce: number;

  /**
   * @param {BlockHeader.fromObjectParams} obj - A plain JavaScript object
   * @returns {BlockHeader} - An instance of block header
   */
  static fromObject(obj: BlockHeader.fromObjectParams): BlockHeader;

  /**
   * @param {Buffer|Uint8Array|string} data Raw block binary data or buffer
   * @returns {BlockHeader} - An instance of block header
   */
  static fromRawBlock(data: Buffer | Uint8Array | string): BlockHeader;

  /**
   * @param {Buffer|Uint8Array} buf - A buffer of the block header
   * @returns {BlockHeader} - An instance of block header
   */
  static fromBuffer(buf: Buffer | Uint8Array): BlockHeader;

Source: claude, codex

New findings in latest delta

None. The latest delta f12c140f..18e6f550 only adds the GovObject/Proposal fake-clock fixtures and does not address the carried-forward TypeScript declaration gap.

Out-of-scope follow-up suggestions (2)

These are valid observations, but they are outside this PR's scope and should be handled separately rather than blocking this review.

  • PR branch bundles sibling PR #316 (govobject date-fixture fix) via merge commit — The cumulative diff against master includes test-only changes in test/govobject/govobject.js and test/govobject/types/proposal.js pinning time with sinon.useFakeTimers(new Date('2024-01-01T00:00:00Z')). These came in via merge commit a1da488 (PR #316), not from any of the four Uint8Array-related commits in this PR. The change itself is reasonable — it neutralizes the known Invalid Timespan baseline failure — but is unrelated to 'accept Uint8Array as input alongside Buffer'. Today's date is 2026-05-26, so the fake-clock window is already two-plus years stale; if proposal date validation has a maximum-future-window assertion, this could regress later.
    • Follow-up: Land #316 directly on master on its own and rebase this PR to drop the merge commit. If #316 stays bundled, mention it in the PR description and anchor the fake clock to a date that keeps fixtures within their validation windows.
  • Other public byte-accepting entry points still require Buffer — PR is explicitly scoped to BlockHeader/BufferReader and honors that scope. Downstream callers wanting to drop Buffer.from(...) wrappers across Block, MerkleBlock, Transaction, InstantLock, ChainLock, SimplifiedMNListDiff, etc. will still need Buffer for those classes. Deliberate scope decision, not a defect.
    • Follow-up: Open a tracking issue describing which downstream call sites in dapi-client / Platform packages still wrap protobuf bytes in Buffer.from(...) and which dashcore-lib factories (plus TS declarations) would need widening to remove those wrappers.

Note: this is a self-review, so GitHub rejected REQUEST_CHANGES; posting as COMMENT while retaining the blocking finding above.

@thepastaclaw
Copy link
Copy Markdown
Author

thepastaclaw commented May 29, 2026

✅ Review complete (commit 18e6f55)

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