Skip to content

Commit

Permalink
feat(reactive): provide deterministic randomness
Browse files Browse the repository at this point in the history
  • Loading branch information
justmoon committed Sep 10, 2024
1 parent 3f6e1bd commit 8177e63
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ import {
type Crypto,
type DisposableScope,
createMockClock,
createMockDeterministicCrypto,
createScope,
createTopic,
} from "@dassie/lib-reactive"
import { createCrypto } from "@dassie/lib-reactive-io"

import type { StreamProtocolContext } from "../../context/context"
import { DEFAULT_POLICY, type StreamPolicy } from "../../context/policy"
import { getPskEnvironment } from "../../crypto/functions"
import { createMockCryptoContext } from "./crypto-context"

interface EnvironmentOptions {
// Environment options
Expand Down Expand Up @@ -67,7 +68,7 @@ export function createTestEnvironment({
maxPacketsInFlight = Infinity,
scope = createScope("test-environment"),
logger = createLogger("das:test:stream"),
crypto = createMockCryptoContext(),
crypto = createMockDeterministicCrypto(createCrypto()),
clock = createMockClock(),
policy = DEFAULT_POLICY,
}: EnvironmentOptions = {}) {
Expand Down
4 changes: 4 additions & 0 deletions packages/lib-reactive/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export {
MockClockImplementation,
DEFAULT_MOCK_CLOCK_TIME,
} from "./mocks/clock"
export {
createMockDeterministicCrypto,
Xoshiro128PlusPlus,
} from "./mocks/deterministic-crypto"
export { delay, delayWithAbortSignal } from "./tools/delay"

export type { Topic, ReadonlyTopic, InferTopicType } from "./topic"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
import type { Crypto } from "@dassie/lib-reactive"
import { createCrypto } from "@dassie/lib-reactive-io"
import type { Crypto } from "../types/base-modules/crypto"

const DEFAULT_SEED = new Uint32Array([
0x13_67_bd_3b, 0x83_31_fa_de, 0x7b_96_f6_b5, 0xb4_9e_9f_58,
])

export function createMockCryptoContext(): Crypto {
const randomGenerator = new Xoshiro128PlusPlus()
export function createMockDeterministicCrypto(
crypto: Crypto,
seed: Uint32Array = DEFAULT_SEED,
): Crypto {
const randomGenerator = new Xoshiro128PlusPlus(seed)

return Object.assign(createCrypto(), {
return Object.assign(crypto, {
getRandomBytes: (length: number) => {
const data = new Uint32Array(Math.ceil(length / 4))

for (let index = 0; index < data.length; index++) {
data[index] = randomGenerator.next()
}

const result = new Uint8Array(data.buffer)

return result.subarray(0, length)
return new Uint8Array(data.buffer, 0, length)
},
})
}

class Xoshiro128PlusPlus {
export class Xoshiro128PlusPlus {
private state: Uint32Array

constructor(seed: Uint32Array = DEFAULT_SEED) {
Expand Down
25 changes: 25 additions & 0 deletions packages/lib-reactive/src/test/deterministic-crypto.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { uint8ArrayToHex } from "uint8array-extras"
import { describe, test } from "vitest"

import { createMockDeterministicCrypto } from "../mocks/deterministic-crypto"
import type { Crypto } from "../types/base-modules/crypto"

describe("Deterministic Crypto", () => {
test("should generate (not so) random bytes", ({ expect }) => {
const crypto = createMockDeterministicCrypto({} as Crypto)
const randomNumber = crypto.getRandomBytes(32)
expect(uint8ArrayToHex(randomNumber)).toMatchInlineSnapshot(
`"1f0796160c164e1fdcc306caed8497f7c424a4e4d66f5653f50d1f35e47638d9"`,
)
})

test("should generate (not so) random bytes of a length that is not a multiple of 4", ({
expect,
}) => {
const crypto = createMockDeterministicCrypto({} as Crypto)
const randomNumber = crypto.getRandomBytes(31)
expect(uint8ArrayToHex(randomNumber)).toMatchInlineSnapshot(
`"1f0796160c164e1fdcc306caed8497f7c424a4e4d66f5653f50d1f35e47638"`,
)
})
})

0 comments on commit 8177e63

Please sign in to comment.