-
Notifications
You must be signed in to change notification settings - Fork 1
Offline networking worker #1026
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import assert from "node:assert"; | ||
| import { describe, it } from "node:test"; | ||
|
|
||
| describe("Offline Networking Example", () => { | ||
| it("should submit blocks and observe outgoing announcements", async () => { | ||
| // <!-- example:networking-offline --> | ||
| const { startOfflineNetworkingWorker } = await import("@typeberry/lib/networking-offline"); | ||
| const { Block, emptyBlock, reencodeAsView } = await import("@typeberry/lib/block"); | ||
| type BlockView = import("@typeberry/lib/block").BlockView; | ||
| type HeaderHash = import("@typeberry/lib/block").HeaderHash; | ||
| const { Bytes } = await import("@typeberry/lib/bytes"); | ||
| const { tinyChainSpec } = await import("@typeberry/lib/config"); | ||
| const { HASH_SIZE, WithHash } = await import("@typeberry/lib/hash"); | ||
| const { DirectPort } = await import("@typeberry/lib/workers-api"); | ||
|
|
||
| const authorshipPorts = DirectPort.pair(); | ||
| const worker = startOfflineNetworkingWorker(authorshipPorts[0]); | ||
| // Connect authorshipPorts[1] to block authorship. | ||
|
|
||
| // Connect blocks received through offline networking to the importer. | ||
| const importedBlocks: BlockView[] = []; | ||
| worker.network.setOnBlocks(async (blocks) => { | ||
| importedBlocks.push(...blocks); | ||
| }); | ||
|
|
||
| const block = reencodeAsView(Block.Codec, emptyBlock(), tinyChainSpec); | ||
| await worker.offline.submitBlock(block); | ||
| assert.strictEqual(importedBlocks[0], block); | ||
|
|
||
| // Outgoing online-network announcements are observable programmatically. | ||
| let announcedHeader: unknown = null; | ||
| worker.offline.announcedHeaders.once((header) => { | ||
| announcedHeader = header; | ||
| }); | ||
| const header = WithHash.new(Bytes.zero(HASH_SIZE).asOpaque<HeaderHash>(), block.header.view()); | ||
| await worker.network.sendNewHeader(header); | ||
| assert.strictEqual(announcedHeader, header); | ||
|
|
||
| await worker.finish(); | ||
| // <!-- /example:networking-offline --> | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| /** | ||
| * Browser-safe cryptographic sizes and opaque key/signature types. | ||
| * | ||
| * This module does not expose signing, verification, or native/WASM setup. | ||
| * | ||
| * @module crypto-browser | ||
| */ | ||
| export * from "@typeberry/crypto/browser.js"; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| /** | ||
| * Programmatically controlled offline implementation of the JAM networking protocol. | ||
| * | ||
| * @module networking-offline | ||
| */ | ||
| export * from "@typeberry/networking-offline"; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Crypto entry points | ||
|
|
||
| `@typeberry/crypto` is the complete cryptographic implementation. It includes | ||
| native/WASM initialization and signing or verification operations. | ||
|
|
||
| `@typeberry/crypto/browser.js` is the dependency-light entry point for code | ||
| which only needs encoded key/signature sizes and their opaque TypeScript types. | ||
| It has no runtime imports and does not expose cryptographic operations. Its | ||
| constants intentionally mirror the canonical values in `ed25519.ts` and | ||
| `bandersnatch.ts`; their literal type annotations and unit test catch drift. | ||
|
Comment on lines
+6
to
+10
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Clarify the encoded-size wording. Replace “only needs encoded key/signature sizes” with “only needs the sizes of encoded keys/signatures” to avoid ambiguity. 🧰 Tools🪛 LanguageTool[style] ~7-~7: The double modal “needs encoded” is nonstandard (only accepted in certain dialects). Consider “to be encoded”. (NEEDS_FIXED) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
|
|
||
| Browser-facing codecs should import from `@typeberry/crypto/browser.js` rather | ||
| than the package root, so merely describing encoded data does not load native | ||
| implementations. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import assert from "node:assert"; | ||
| import { describe, it } from "node:test"; | ||
|
Comment on lines
+1
to
+2
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Keep this shared test runtime-neutral.
As per path instructions, 🤖 Prompt for AI AgentsSource: Path instructions |
||
| import * as bandersnatch from "./bandersnatch.js"; | ||
| import * as browser from "./browser.js"; | ||
| import * as ed25519 from "./ed25519.js"; | ||
|
|
||
| describe("browser-safe crypto constants", () => { | ||
| it("match their canonical implementation values", () => { | ||
| assert.strictEqual(browser.ED25519_PRIV_KEY_BYTES, ed25519.ED25519_PRIV_KEY_BYTES); | ||
| assert.strictEqual(browser.ED25519_KEY_BYTES, ed25519.ED25519_KEY_BYTES); | ||
| assert.strictEqual(browser.ED25519_SIGNATURE_BYTES, ed25519.ED25519_SIGNATURE_BYTES); | ||
| assert.strictEqual(browser.BANDERSNATCH_KEY_BYTES, bandersnatch.BANDERSNATCH_KEY_BYTES); | ||
| assert.strictEqual(browser.BANDERSNATCH_VRF_SIGNATURE_BYTES, bandersnatch.BANDERSNATCH_VRF_SIGNATURE_BYTES); | ||
| assert.strictEqual(browser.BANDERSNATCH_RING_ROOT_BYTES, bandersnatch.BANDERSNATCH_RING_ROOT_BYTES); | ||
| assert.strictEqual(browser.BANDERSNATCH_PROOF_BYTES, bandersnatch.BANDERSNATCH_PROOF_BYTES); | ||
| assert.strictEqual(browser.BLS_KEY_BYTES, bandersnatch.BLS_KEY_BYTES); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /** | ||
| * Browser-safe cryptographic sizes and opaque data types. | ||
| * | ||
| * This module intentionally has no runtime imports. The annotations on the | ||
| * mirrored constants make TypeScript fail if their canonical values in the | ||
| * implementation modules change. | ||
| */ | ||
|
|
||
| type CanonicalEd25519PrivateKeyBytes = typeof import("./ed25519.js").ED25519_PRIV_KEY_BYTES; | ||
| type CanonicalEd25519KeyBytes = typeof import("./ed25519.js").ED25519_KEY_BYTES; | ||
| type CanonicalEd25519SignatureBytes = typeof import("./ed25519.js").ED25519_SIGNATURE_BYTES; | ||
| type CanonicalBandersnatchKeyBytes = typeof import("./bandersnatch.js").BANDERSNATCH_KEY_BYTES; | ||
| type CanonicalBandersnatchVrfSignatureBytes = typeof import("./bandersnatch.js").BANDERSNATCH_VRF_SIGNATURE_BYTES; | ||
| type CanonicalBandersnatchRingRootBytes = typeof import("./bandersnatch.js").BANDERSNATCH_RING_ROOT_BYTES; | ||
| type CanonicalBandersnatchProofBytes = typeof import("./bandersnatch.js").BANDERSNATCH_PROOF_BYTES; | ||
| type CanonicalBlsKeyBytes = typeof import("./bandersnatch.js").BLS_KEY_BYTES; | ||
|
|
||
| export const ED25519_PRIV_KEY_BYTES: CanonicalEd25519PrivateKeyBytes = 32; | ||
| export type ED25519_PRIV_KEY_BYTES = typeof ED25519_PRIV_KEY_BYTES; | ||
|
|
||
| export const ED25519_KEY_BYTES: CanonicalEd25519KeyBytes = 32; | ||
| export type ED25519_KEY_BYTES = typeof ED25519_KEY_BYTES; | ||
|
|
||
| export const ED25519_SIGNATURE_BYTES: CanonicalEd25519SignatureBytes = 64; | ||
| export type ED25519_SIGNATURE_BYTES = typeof ED25519_SIGNATURE_BYTES; | ||
|
|
||
| export const BANDERSNATCH_KEY_BYTES: CanonicalBandersnatchKeyBytes = 32; | ||
| export type BANDERSNATCH_KEY_BYTES = typeof BANDERSNATCH_KEY_BYTES; | ||
|
|
||
| export const BANDERSNATCH_VRF_SIGNATURE_BYTES: CanonicalBandersnatchVrfSignatureBytes = 96; | ||
| export type BANDERSNATCH_VRF_SIGNATURE_BYTES = typeof BANDERSNATCH_VRF_SIGNATURE_BYTES; | ||
|
|
||
| export const BANDERSNATCH_RING_ROOT_BYTES: CanonicalBandersnatchRingRootBytes = 144; | ||
| export type BANDERSNATCH_RING_ROOT_BYTES = typeof BANDERSNATCH_RING_ROOT_BYTES; | ||
|
|
||
| export const BANDERSNATCH_PROOF_BYTES: CanonicalBandersnatchProofBytes = 784; | ||
| export type BANDERSNATCH_PROOF_BYTES = typeof BANDERSNATCH_PROOF_BYTES; | ||
|
|
||
| export const BLS_KEY_BYTES: CanonicalBlsKeyBytes = 144; | ||
| export type BLS_KEY_BYTES = typeof BLS_KEY_BYTES; | ||
|
|
||
| export type { | ||
| BandersnatchKey, | ||
| BandersnatchProof, | ||
| BandersnatchRingRoot, | ||
| BandersnatchVrfSignature, | ||
| BlsKey, | ||
| } from "./bandersnatch.js"; | ||
| export type { Ed25519Key, Ed25519Signature } from "./ed25519.js"; |
There was a problem hiding this comment.
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
Make the README example self-contained.
Lines [125] and [134] call
assert.strictEqual, but this snippet never imports or definesassert, and browsers do not provide it globally. Use explicit checks or add an environment-appropriate assertion import.Proposed browser-safe replacement
📝 Committable suggestion
🤖 Prompt for AI Agents