fix: incorrect cursor encoding in Store queries

Fixes https://github.com/status-im/nwaku/issues/1157
This commit is contained in:
fryorcraken.eth 2022-10-28 09:01:00 +11:00
parent 29436eafdc
commit bf1988cda8
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
10 changed files with 52 additions and 1010 deletions

View File

@ -16,6 +16,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `Message` interface changed to ensure implementations do not omit fields. - `Message` interface changed to ensure implementations do not omit fields.
- `Decoder` and `Encoder` interfaces change to better express what the function members do. - `Decoder` and `Encoder` interfaces change to better express what the function members do.
### Fixed
- Incorrect cursor encoding in Store queries.
### Removed
- Support for Waku Store 2.0.0-beta4.
## [0.29.0] - 2022-09-21 ## [0.29.0] - 2022-09-21
### Changed ### Changed
@ -31,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `WakuRelay.addObserver` now returns a function to delete the observer. - `WakuRelay.addObserver` now returns a function to delete the observer.
- `WakuLightPush.push` and `WakuRelay.send` returns `SendResult` with the list of recipients. - `WakuLightPush.push` and `WakuRelay.send` returns `SendResult` with the list of recipients.
### Changed ### Removed
- `queryCallbackOnPromise`'s return value has been simplified to `Promise<void>`. - `queryCallbackOnPromise`'s return value has been simplified to `Promise<void>`.
- doc: clarified behaviour of `WakuStore` query functions. - doc: clarified behaviour of `WakuStore` query functions.

View File

@ -30,4 +30,4 @@ export * as waku_relay from "./lib/waku_relay";
export { WakuRelay } from "./lib/waku_relay"; export { WakuRelay } from "./lib/waku_relay";
export * as waku_store from "./lib/waku_store"; export * as waku_store from "./lib/waku_store";
export { PageDirection, WakuStore, StoreCodecs } from "./lib/waku_store"; export { PageDirection, WakuStore, StoreCodec } from "./lib/waku_store";

View File

@ -2,8 +2,3 @@
* DefaultPubSubTopic is the default gossipsub topic to use for Waku. * DefaultPubSubTopic is the default gossipsub topic to use for Waku.
*/ */
export const DefaultPubSubTopic = "/waku/2/default-waku/proto"; export const DefaultPubSubTopic = "/waku/2/default-waku/proto";
export enum StoreCodecs {
V2Beta3 = "/vac/waku/store/2.0.0-beta3",
V2Beta4 = "/vac/waku/store/2.0.0-beta4",
}

View File

@ -4,11 +4,11 @@ import debug from "debug";
import type { Libp2p } from "libp2p"; import type { Libp2p } from "libp2p";
import { pEvent } from "p-event"; import { pEvent } from "p-event";
import { StoreCodecs } from "./constants";
import type { Waku } from "./interfaces"; import type { Waku } from "./interfaces";
import { Protocols } from "./waku"; import { Protocols } from "./waku";
import { FilterCodec } from "./waku_filter"; import { FilterCodec } from "./waku_filter";
import { LightPushCodec } from "./waku_light_push"; import { LightPushCodec } from "./waku_light_push";
import { StoreCodec } from "./waku_store";
const log = debug("waku:wait-for-remote-peer"); const log = debug("waku:wait-for-remote-peer");
@ -60,7 +60,7 @@ export async function waitForRemotePeer(
if (protocols.includes(Protocols.Store)) { if (protocols.includes(Protocols.Store)) {
if (!waku.store) if (!waku.store)
throw new Error("Cannot wait for Store peer: protocol not mounted"); throw new Error("Cannot wait for Store peer: protocol not mounted");
promises.push(waitForConnectedPeer(waku.store, Object.values(StoreCodecs))); promises.push(waitForConnectedPeer(waku.store, [StoreCodec]));
} }
if (protocols.includes(Protocols.LightPush)) { if (protocols.includes(Protocols.LightPush)) {

View File

@ -14,7 +14,7 @@ import { EncoderV0 } from "./waku_message/version_0";
import { WakuRelay } from "./waku_relay"; import { WakuRelay } from "./waku_relay";
import { RelayCodecs, RelayPingContentTopic } from "./waku_relay/constants"; import { RelayCodecs, RelayPingContentTopic } from "./waku_relay/constants";
import * as relayConstants from "./waku_relay/constants"; import * as relayConstants from "./waku_relay/constants";
import { StoreCodecs, WakuStore } from "./waku_store"; import { StoreCodec, WakuStore } from "./waku_store";
export const DefaultPingKeepAliveValueSecs = 0; export const DefaultPingKeepAliveValueSecs = 0;
export const DefaultRelayKeepAliveValueSecs = 5 * 60; export const DefaultRelayKeepAliveValueSecs = 5 * 60;
@ -128,9 +128,7 @@ export class WakuNode implements Waku {
RelayCodecs.forEach((codec) => codecs.push(codec)); RelayCodecs.forEach((codec) => codecs.push(codec));
} }
if (_protocols.includes(Protocols.Store)) { if (_protocols.includes(Protocols.Store)) {
for (const codec of Object.values(StoreCodecs)) { codecs.push(StoreCodec);
codecs.push(codec);
}
} }
if (_protocols.includes(Protocols.LightPush)) { if (_protocols.includes(Protocols.LightPush)) {
codecs.push(LightPushCodec); codecs.push(LightPushCodec);

View File

@ -1,4 +0,0 @@
export enum StoreCodecs {
V2Beta3 = "/vac/waku/store/2.0.0-beta3",
V2Beta4 = "/vac/waku/store/2.0.0-beta4",
}

View File

@ -1,11 +1,8 @@
import type { Uint8ArrayList } from "uint8arraylist"; import type { Uint8ArrayList } from "uint8arraylist";
import { v4 as uuid } from "uuid"; import { v4 as uuid } from "uuid";
import * as protoV2Beta3 from "../../proto/store_v2beta3";
import * as protoV2Beta4 from "../../proto/store_v2beta4"; import * as protoV2Beta4 from "../../proto/store_v2beta4";
import { StoreCodecs } from "./constants";
const OneMillion = BigInt(1_000_000); const OneMillion = BigInt(1_000_000);
export enum PageDirection { export enum PageDirection {
@ -20,42 +17,17 @@ export interface Params {
pageSize: number; pageSize: number;
startTime?: Date; startTime?: Date;
endTime?: Date; endTime?: Date;
cursor?: protoV2Beta3.Index | protoV2Beta4.Index; cursor?: protoV2Beta4.Index;
storeCodec?: StoreCodecs;
} }
export class HistoryRPC { export class HistoryRPC {
private readonly historyRpc: private constructor(public readonly proto: protoV2Beta4.HistoryRPC) {}
| typeof protoV2Beta3.HistoryRPC
| typeof protoV2Beta4.HistoryRPC;
private constructor( get query(): protoV2Beta4.HistoryQuery | undefined {
public readonly proto: protoV2Beta3.HistoryRPC | protoV2Beta4.HistoryRPC,
public readonly storeCodec: StoreCodecs
) {
switch (storeCodec) {
case StoreCodecs.V2Beta3:
this.historyRpc = protoV2Beta3.HistoryRPC;
break;
case StoreCodecs.V2Beta4:
this.historyRpc = protoV2Beta4.HistoryRPC;
break;
default:
throw `Internal Error: Unexpected store codec value received in constructor: ${storeCodec}`;
}
}
get query():
| protoV2Beta3.HistoryQuery
| protoV2Beta4.HistoryQuery
| undefined {
return this.proto.query; return this.proto.query;
} }
get response(): get response(): protoV2Beta4.HistoryResponse | undefined {
| protoV2Beta3.HistoryResponse
| protoV2Beta4.HistoryResponse
| undefined {
return this.proto.response; return this.proto.response;
} }
@ -63,46 +35,12 @@ export class HistoryRPC {
* Create History Query. * Create History Query.
*/ */
static createQuery(params: Params): HistoryRPC { static createQuery(params: Params): HistoryRPC {
const storeCodec = params.storeCodec ?? StoreCodecs.V2Beta4;
const contentFilters = params.contentTopics.map((contentTopic) => { const contentFilters = params.contentTopics.map((contentTopic) => {
return { contentTopic }; return { contentTopic };
}); });
const direction = directionToProto(params.pageDirection); const direction = directionToProto(params.pageDirection);
switch (storeCodec) {
case StoreCodecs.V2Beta3:
// Using function to scope variables
return ((): HistoryRPC => {
const pagingInfo = {
pageSize: BigInt(params.pageSize),
cursor: params.cursor,
direction,
} as protoV2Beta3.PagingInfo;
let startTime, endTime;
if (params.startTime) startTime = params.startTime.valueOf() / 1000;
if (params.endTime) endTime = params.endTime.valueOf() / 1000;
return new HistoryRPC(
{
requestId: uuid(),
query: {
pubSubTopic: params.pubSubTopic,
contentFilters,
pagingInfo,
startTime,
endTime,
},
response: undefined,
},
storeCodec
);
})();
case StoreCodecs.V2Beta4:
return ((): HistoryRPC => {
const pagingInfo = { const pagingInfo = {
pageSize: BigInt(params.pageSize), pageSize: BigInt(params.pageSize),
cursor: params.cursor, cursor: params.cursor,
@ -119,8 +57,7 @@ export class HistoryRPC {
// milliseconds 10^-3 to nanoseconds 10^-9 // milliseconds 10^-3 to nanoseconds 10^-9
endTime = BigInt(params.endTime.valueOf()) * OneMillion; endTime = BigInt(params.endTime.valueOf()) * OneMillion;
} }
return new HistoryRPC( return new HistoryRPC({
{
requestId: uuid(), requestId: uuid(),
query: { query: {
pubSubTopic: params.pubSubTopic, pubSubTopic: params.pubSubTopic,
@ -130,23 +67,16 @@ export class HistoryRPC {
endTime, endTime,
}, },
response: undefined, response: undefined,
}, });
storeCodec
);
})();
default:
throw `Internal Error: Unexpected store codec value received in createQuery: ${storeCodec}`;
}
} }
decode(bytes: Uint8ArrayList): HistoryRPC { decode(bytes: Uint8ArrayList): HistoryRPC {
const res = this.historyRpc.decode(bytes); const res = protoV2Beta4.HistoryRPC.decode(bytes);
return new HistoryRPC(res, this.storeCodec); return new HistoryRPC(res);
} }
encode(): Uint8Array { encode(): Uint8Array {
return this.historyRpc.encode(this.proto as any); return protoV2Beta4.HistoryRPC.encode(this.proto);
} }
} }

View File

@ -10,7 +10,7 @@ import { Uint8ArrayList } from "uint8arraylist";
import * as protoV2Beta4 from "../../proto/store_v2beta4"; import * as protoV2Beta4 from "../../proto/store_v2beta4";
import { HistoryResponse } from "../../proto/store_v2beta4"; import { HistoryResponse } from "../../proto/store_v2beta4";
import { DefaultPubSubTopic, StoreCodecs } from "../constants"; import { DefaultPubSubTopic } from "../constants";
import { Decoder, Message } from "../interfaces"; import { Decoder, Message } from "../interfaces";
import { selectConnection } from "../select_connection"; import { selectConnection } from "../select_connection";
import { getPeersForProtocol, selectPeerForProtocol } from "../select_peer"; import { getPeersForProtocol, selectPeerForProtocol } from "../select_peer";
@ -22,9 +22,11 @@ import HistoryError = HistoryResponse.HistoryError;
const log = debug("waku:store"); const log = debug("waku:store");
export const StoreCodec = "/vac/waku/store/2.0.0-beta4";
export const DefaultPageSize = 10; export const DefaultPageSize = 10;
export { PageDirection, StoreCodecs }; export { PageDirection };
export interface CreateOptions { export interface CreateOptions {
/** /**
@ -232,7 +234,7 @@ export class WakuStore {
const res = await selectPeerForProtocol( const res = await selectPeerForProtocol(
this.libp2p.peerStore, this.libp2p.peerStore,
Object.values(StoreCodecs), [StoreCodec],
options?.peerId options?.peerId
); );
@ -261,12 +263,7 @@ export class WakuStore {
* store protocol. Waku may or may not be currently connected to these peers. * store protocol. Waku may or may not be currently connected to these peers.
*/ */
async peers(): Promise<Peer[]> { async peers(): Promise<Peer[]> {
const codecs = []; return getPeersForProtocol(this.libp2p.peerStore, [StoreCodec]);
for (const codec of Object.values(StoreCodecs)) {
codecs.push(codec);
}
return getPeersForProtocol(this.libp2p.peerStore, codecs);
} }
} }

View File

@ -1,47 +0,0 @@
syntax = "proto3";
import "message.proto";
message Index {
optional bytes digest = 1;
optional double received_time = 2;
optional double sender_time = 3;
}
message PagingInfo {
optional uint64 page_size = 1;
optional Index cursor = 2;
enum Direction {
DIRECTION_BACKWARD_UNSPECIFIED = 0;
DIRECTION_FORWARD = 1;
}
optional Direction direction = 3;
}
message ContentFilter {
optional string content_topic = 1;
}
message HistoryQuery {
optional string pub_sub_topic = 2;
repeated ContentFilter content_filters = 3;
optional PagingInfo paging_info = 4;
optional double start_time = 5;
optional double end_time = 6;
}
message HistoryResponse {
repeated WakuMessage messages = 2;
optional PagingInfo paging_info = 3;
enum HistoryError {
ERROR_NONE_UNSPECIFIED = 0;
ERROR_INVALID_CURSOR = 1;
}
optional HistoryError error = 4;
}
message HistoryRPC {
optional string request_id = 1;
optional HistoryQuery query = 2;
optional HistoryResponse response = 3;
}

View File

@ -1,835 +0,0 @@
/* eslint-disable import/export */
/* eslint-disable @typescript-eslint/no-namespace */
import {
encodeMessage,
decodeMessage,
message,
enumeration,
} from "protons-runtime";
import type { Uint8ArrayList } from "uint8arraylist";
import type { Codec } from "protons-runtime";
export interface Index {
digest?: Uint8Array;
receivedTime?: number;
senderTime?: number;
}
export namespace Index {
let _codec: Codec<Index>;
export const codec = (): Codec<Index> => {
if (_codec == null) {
_codec = message<Index>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.digest != null) {
writer.uint32(10);
writer.bytes(obj.digest);
}
if (obj.receivedTime != null) {
writer.uint32(17);
writer.double(obj.receivedTime);
}
if (obj.senderTime != null) {
writer.uint32(25);
writer.double(obj.senderTime);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
obj.digest = reader.bytes();
break;
case 2:
obj.receivedTime = reader.double();
break;
case 3:
obj.senderTime = reader.double();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: Index): Uint8Array => {
return encodeMessage(obj, Index.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): Index => {
return decodeMessage(buf, Index.codec());
};
}
export interface PagingInfo {
pageSize?: bigint;
cursor?: Index;
direction?: PagingInfo.Direction;
}
export namespace PagingInfo {
export enum Direction {
DIRECTION_BACKWARD_UNSPECIFIED = "DIRECTION_BACKWARD_UNSPECIFIED",
DIRECTION_FORWARD = "DIRECTION_FORWARD",
}
enum __DirectionValues {
DIRECTION_BACKWARD_UNSPECIFIED = 0,
DIRECTION_FORWARD = 1,
}
export namespace Direction {
export const codec = () => {
return enumeration<Direction>(__DirectionValues);
};
}
let _codec: Codec<PagingInfo>;
export const codec = (): Codec<PagingInfo> => {
if (_codec == null) {
_codec = message<PagingInfo>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.pageSize != null) {
writer.uint32(8);
writer.uint64(obj.pageSize);
}
if (obj.cursor != null) {
writer.uint32(18);
Index.codec().encode(obj.cursor, writer);
}
if (obj.direction != null) {
writer.uint32(24);
PagingInfo.Direction.codec().encode(obj.direction, writer);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
obj.pageSize = reader.uint64();
break;
case 2:
obj.cursor = Index.codec().decode(reader, reader.uint32());
break;
case 3:
obj.direction = PagingInfo.Direction.codec().decode(reader);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: PagingInfo): Uint8Array => {
return encodeMessage(obj, PagingInfo.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): PagingInfo => {
return decodeMessage(buf, PagingInfo.codec());
};
}
export interface ContentFilter {
contentTopic?: string;
}
export namespace ContentFilter {
let _codec: Codec<ContentFilter>;
export const codec = (): Codec<ContentFilter> => {
if (_codec == null) {
_codec = message<ContentFilter>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.contentTopic != null) {
writer.uint32(10);
writer.string(obj.contentTopic);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
obj.contentTopic = reader.string();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: ContentFilter): Uint8Array => {
return encodeMessage(obj, ContentFilter.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): ContentFilter => {
return decodeMessage(buf, ContentFilter.codec());
};
}
export interface HistoryQuery {
pubSubTopic?: string;
contentFilters: ContentFilter[];
pagingInfo?: PagingInfo;
startTime?: number;
endTime?: number;
}
export namespace HistoryQuery {
let _codec: Codec<HistoryQuery>;
export const codec = (): Codec<HistoryQuery> => {
if (_codec == null) {
_codec = message<HistoryQuery>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.pubSubTopic != null) {
writer.uint32(18);
writer.string(obj.pubSubTopic);
}
if (obj.contentFilters != null) {
for (const value of obj.contentFilters) {
writer.uint32(26);
ContentFilter.codec().encode(value, writer);
}
} else {
throw new Error(
'Protocol error: required field "contentFilters" was not found in object'
);
}
if (obj.pagingInfo != null) {
writer.uint32(34);
PagingInfo.codec().encode(obj.pagingInfo, writer);
}
if (obj.startTime != null) {
writer.uint32(41);
writer.double(obj.startTime);
}
if (obj.endTime != null) {
writer.uint32(49);
writer.double(obj.endTime);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {
contentFilters: [],
};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 2:
obj.pubSubTopic = reader.string();
break;
case 3:
obj.contentFilters.push(
ContentFilter.codec().decode(reader, reader.uint32())
);
break;
case 4:
obj.pagingInfo = PagingInfo.codec().decode(
reader,
reader.uint32()
);
break;
case 5:
obj.startTime = reader.double();
break;
case 6:
obj.endTime = reader.double();
break;
default:
reader.skipType(tag & 7);
break;
}
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: HistoryQuery): Uint8Array => {
return encodeMessage(obj, HistoryQuery.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): HistoryQuery => {
return decodeMessage(buf, HistoryQuery.codec());
};
}
export interface HistoryResponse {
messages: WakuMessage[];
pagingInfo?: PagingInfo;
error?: HistoryResponse.HistoryError;
}
export namespace HistoryResponse {
export enum HistoryError {
ERROR_NONE_UNSPECIFIED = "ERROR_NONE_UNSPECIFIED",
ERROR_INVALID_CURSOR = "ERROR_INVALID_CURSOR",
}
enum __HistoryErrorValues {
ERROR_NONE_UNSPECIFIED = 0,
ERROR_INVALID_CURSOR = 1,
}
export namespace HistoryError {
export const codec = () => {
return enumeration<HistoryError>(__HistoryErrorValues);
};
}
let _codec: Codec<HistoryResponse>;
export const codec = (): Codec<HistoryResponse> => {
if (_codec == null) {
_codec = message<HistoryResponse>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.messages != null) {
for (const value of obj.messages) {
writer.uint32(18);
WakuMessage.codec().encode(value, writer);
}
} else {
throw new Error(
'Protocol error: required field "messages" was not found in object'
);
}
if (obj.pagingInfo != null) {
writer.uint32(26);
PagingInfo.codec().encode(obj.pagingInfo, writer);
}
if (obj.error != null) {
writer.uint32(32);
HistoryResponse.HistoryError.codec().encode(obj.error, writer);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {
messages: [],
};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 2:
obj.messages.push(
WakuMessage.codec().decode(reader, reader.uint32())
);
break;
case 3:
obj.pagingInfo = PagingInfo.codec().decode(
reader,
reader.uint32()
);
break;
case 4:
obj.error = HistoryResponse.HistoryError.codec().decode(reader);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: HistoryResponse): Uint8Array => {
return encodeMessage(obj, HistoryResponse.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): HistoryResponse => {
return decodeMessage(buf, HistoryResponse.codec());
};
}
export interface HistoryRPC {
requestId?: string;
query?: HistoryQuery;
response?: HistoryResponse;
}
export namespace HistoryRPC {
let _codec: Codec<HistoryRPC>;
export const codec = (): Codec<HistoryRPC> => {
if (_codec == null) {
_codec = message<HistoryRPC>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.requestId != null) {
writer.uint32(10);
writer.string(obj.requestId);
}
if (obj.query != null) {
writer.uint32(18);
HistoryQuery.codec().encode(obj.query, writer);
}
if (obj.response != null) {
writer.uint32(26);
HistoryResponse.codec().encode(obj.response, writer);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
obj.requestId = reader.string();
break;
case 2:
obj.query = HistoryQuery.codec().decode(
reader,
reader.uint32()
);
break;
case 3:
obj.response = HistoryResponse.codec().decode(
reader,
reader.uint32()
);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: HistoryRPC): Uint8Array => {
return encodeMessage(obj, HistoryRPC.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): HistoryRPC => {
return decodeMessage(buf, HistoryRPC.codec());
};
}
export interface RateLimitProof {
proof: Uint8Array;
merkleRoot: Uint8Array;
epoch: Uint8Array;
shareX: Uint8Array;
shareY: Uint8Array;
nullifier: Uint8Array;
rlnIdentifier: Uint8Array;
}
export namespace RateLimitProof {
let _codec: Codec<RateLimitProof>;
export const codec = (): Codec<RateLimitProof> => {
if (_codec == null) {
_codec = message<RateLimitProof>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.proof != null) {
writer.uint32(10);
writer.bytes(obj.proof);
} else {
throw new Error(
'Protocol error: required field "proof" was not found in object'
);
}
if (obj.merkleRoot != null) {
writer.uint32(18);
writer.bytes(obj.merkleRoot);
} else {
throw new Error(
'Protocol error: required field "merkleRoot" was not found in object'
);
}
if (obj.epoch != null) {
writer.uint32(26);
writer.bytes(obj.epoch);
} else {
throw new Error(
'Protocol error: required field "epoch" was not found in object'
);
}
if (obj.shareX != null) {
writer.uint32(34);
writer.bytes(obj.shareX);
} else {
throw new Error(
'Protocol error: required field "shareX" was not found in object'
);
}
if (obj.shareY != null) {
writer.uint32(42);
writer.bytes(obj.shareY);
} else {
throw new Error(
'Protocol error: required field "shareY" was not found in object'
);
}
if (obj.nullifier != null) {
writer.uint32(50);
writer.bytes(obj.nullifier);
} else {
throw new Error(
'Protocol error: required field "nullifier" was not found in object'
);
}
if (obj.rlnIdentifier != null) {
writer.uint32(58);
writer.bytes(obj.rlnIdentifier);
} else {
throw new Error(
'Protocol error: required field "rlnIdentifier" was not found in object'
);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {
proof: new Uint8Array(0),
merkleRoot: new Uint8Array(0),
epoch: new Uint8Array(0),
shareX: new Uint8Array(0),
shareY: new Uint8Array(0),
nullifier: new Uint8Array(0),
rlnIdentifier: new Uint8Array(0),
};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
obj.proof = reader.bytes();
break;
case 2:
obj.merkleRoot = reader.bytes();
break;
case 3:
obj.epoch = reader.bytes();
break;
case 4:
obj.shareX = reader.bytes();
break;
case 5:
obj.shareY = reader.bytes();
break;
case 6:
obj.nullifier = reader.bytes();
break;
case 7:
obj.rlnIdentifier = reader.bytes();
break;
default:
reader.skipType(tag & 7);
break;
}
}
if (obj.proof == null) {
throw new Error(
'Protocol error: value for required field "proof" was not found in protobuf'
);
}
if (obj.merkleRoot == null) {
throw new Error(
'Protocol error: value for required field "merkleRoot" was not found in protobuf'
);
}
if (obj.epoch == null) {
throw new Error(
'Protocol error: value for required field "epoch" was not found in protobuf'
);
}
if (obj.shareX == null) {
throw new Error(
'Protocol error: value for required field "shareX" was not found in protobuf'
);
}
if (obj.shareY == null) {
throw new Error(
'Protocol error: value for required field "shareY" was not found in protobuf'
);
}
if (obj.nullifier == null) {
throw new Error(
'Protocol error: value for required field "nullifier" was not found in protobuf'
);
}
if (obj.rlnIdentifier == null) {
throw new Error(
'Protocol error: value for required field "rlnIdentifier" was not found in protobuf'
);
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: RateLimitProof): Uint8Array => {
return encodeMessage(obj, RateLimitProof.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): RateLimitProof => {
return decodeMessage(buf, RateLimitProof.codec());
};
}
export interface WakuMessage {
payload?: Uint8Array;
contentTopic?: string;
version?: number;
timestampDeprecated?: number;
timestamp?: bigint;
rateLimitProof?: RateLimitProof;
}
export namespace WakuMessage {
let _codec: Codec<WakuMessage>;
export const codec = (): Codec<WakuMessage> => {
if (_codec == null) {
_codec = message<WakuMessage>(
(obj, writer, opts = {}) => {
if (opts.lengthDelimited !== false) {
writer.fork();
}
if (obj.payload != null) {
writer.uint32(10);
writer.bytes(obj.payload);
}
if (obj.contentTopic != null) {
writer.uint32(18);
writer.string(obj.contentTopic);
}
if (obj.version != null) {
writer.uint32(24);
writer.uint32(obj.version);
}
if (obj.timestampDeprecated != null) {
writer.uint32(33);
writer.double(obj.timestampDeprecated);
}
if (obj.timestamp != null) {
writer.uint32(80);
writer.sint64(obj.timestamp);
}
if (obj.rateLimitProof != null) {
writer.uint32(170);
RateLimitProof.codec().encode(obj.rateLimitProof, writer);
}
if (opts.lengthDelimited !== false) {
writer.ldelim();
}
},
(reader, length) => {
const obj: any = {};
const end = length == null ? reader.len : reader.pos + length;
while (reader.pos < end) {
const tag = reader.uint32();
switch (tag >>> 3) {
case 1:
obj.payload = reader.bytes();
break;
case 2:
obj.contentTopic = reader.string();
break;
case 3:
obj.version = reader.uint32();
break;
case 4:
obj.timestampDeprecated = reader.double();
break;
case 10:
obj.timestamp = reader.sint64();
break;
case 21:
obj.rateLimitProof = RateLimitProof.codec().decode(
reader,
reader.uint32()
);
break;
default:
reader.skipType(tag & 7);
break;
}
}
return obj;
}
);
}
return _codec;
};
export const encode = (obj: WakuMessage): Uint8Array => {
return encodeMessage(obj, WakuMessage.codec());
};
export const decode = (buf: Uint8Array | Uint8ArrayList): WakuMessage => {
return decodeMessage(buf, WakuMessage.codec());
};
}