UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

91 lines (84 loc) 2.81 kB
import {Type} from "@chainsafe/ssz"; import {RequestError, RequestErrorCode, ResponseIncoming} from "@lodestar/reqresp"; import {SerializedCache} from "../../../util/serializedCache.js"; import {ResponseTypeGetter} from "../types.js"; /** * Sink for `<response_chunk>*`, from * ```bnf * response ::= <response_chunk>* * ``` * Expects exactly one response */ export async function collectExactOneTyped<T>( source: AsyncIterable<ResponseIncoming>, typeFn: ResponseTypeGetter<T> ): Promise<T> { for await (const chunk of source) { const type = typeFn(chunk.fork, chunk.protocolVersion); const response = sszDeserializeResponse(type, chunk.data); return response; } throw new RequestError({code: RequestErrorCode.EMPTY_RESPONSE}); } /** * Sink for `<response_chunk>*`, from * ```bnf * response ::= <response_chunk>* * ``` * Collects a bounded list of responses up to `maxResponses` */ export async function collectMaxResponseTyped<T>( source: AsyncIterable<ResponseIncoming>, maxResponses: number, typeFn: ResponseTypeGetter<T>, serializedCache?: SerializedCache ): Promise<T[]> { // else: zero or more responses const responses: T[] = []; for await (const chunk of source) { const type = typeFn(chunk.fork, chunk.protocolVersion); const response = sszDeserializeResponse(type, chunk.data); // optionally cache the serialized response if the cache is available serializedCache?.set(response as object, chunk.data); responses.push(response); if (maxResponses !== undefined && responses.length >= maxResponses) { break; } } return responses; } /** * Sink for `<response_chunk>*`, from * ```bnf * response ::= <response_chunk>* * ``` * Collects a bounded list of responses up to `maxResponses` */ export async function collectMaxResponseTypedWithBytes<T>( source: AsyncIterable<ResponseIncoming>, maxResponses: number, typeFn: ResponseTypeGetter<T>, serializedCache?: SerializedCache ): Promise<T[]> { // else: zero or more responses const responses: T[] = []; for await (const chunk of source) { const type = typeFn(chunk.fork, chunk.protocolVersion); const data = sszDeserializeResponse(type, chunk.data); responses.push(data); // optionally cache the serialized response if the cache is available serializedCache?.set(data as object, chunk.data); if (maxResponses !== undefined && responses.length >= maxResponses) { break; } } return responses; } /** Light wrapper on type to wrap deserialize errors */ export function sszDeserializeResponse<T>(type: Type<T>, bytes: Uint8Array): T { try { return type.deserialize(bytes); } catch (e) { throw new RequestError({code: RequestErrorCode.INVALID_RESPONSE_SSZ, errorMessage: (e as Error).message}); } }