Skip to content

Commit

Permalink
KB universal accumulator
Browse files Browse the repository at this point in the history
Signed-off-by: lovesh <[email protected]>
  • Loading branch information
lovesh committed Mar 25, 2024
1 parent 3057ca0 commit 11b8b21
Show file tree
Hide file tree
Showing 35 changed files with 1,850 additions and 313 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@docknetwork/crypto-wasm-ts",
"version": "0.56.0",
"version": "0.57.0",
"description": "Typescript abstractions over Dock's Rust crypto library's WASM wrapper",
"homepage": "https://github.com/docknetwork/crypto-wasm-ts",
"main": "lib/index.js",
Expand Down Expand Up @@ -31,7 +31,7 @@
"@types/flat": "^5.0.2",
"@types/lodash": "^4.14.195",
"bs58": "5.0.0",
"crypto-wasm-new": "npm:@docknetwork/crypto-wasm@0.25.0",
"crypto-wasm-new": "file:///Users/lovesh/dev/dock/crypto-wasm",
"crypto-wasm-old": "npm:@docknetwork/[email protected]",
"flat": "^5.0.2",
"json-pointer": "^0.6.2",
Expand Down
14 changes: 14 additions & 0 deletions src/accumulator/IAccumulatorState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,17 @@ export interface IAccumulatorState {
export interface IUniversalAccumulatorState extends IAccumulatorState {
elements(): Promise<Iterable<Uint8Array>>;
}

export interface IKBUniversalAccumulatorState extends IAccumulatorState {
/**
* Whether this element is in the domain (could be a member or not)
* @param element
*/
inDomain(element: Uint8Array): Promise<boolean>;

/**
* Takes an element not in the domain and adds it.
* @param element
*/
addToDomain(element: Uint8Array): Promise<void>;
}
22 changes: 11 additions & 11 deletions src/accumulator/accumulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
universalAccumulatorVerifyMembership,
universalAccumulatorVerifyNonMembership
} from 'crypto-wasm-new';
import { VBMembershipWitness, VBNonMembershipWitness } from './accumulatorWitness';
import { AccumulatorWitness, VBMembershipWitness, VBNonMembershipWitness } from './accumulatorWitness';
import { getUint8ArraysFromObject } from '../util';
import { IAccumulatorState, IUniversalAccumulatorState } from './IAccumulatorState';
import { IInitialElementsStore } from './IInitialElementsStore';
Expand All @@ -53,7 +53,7 @@ import {
* the state object is to check if duplicate elements are not added or already absent elements are not removed or membership witness
* for absent elements is not created. If checks in the `state` fail, they throw errors.
*/
export abstract class Accumulator {
export abstract class Accumulator<T> {
value: Uint8Array | object;
secretKey: AccumulatorSecretKey | undefined;
params: AccumulatorParams | undefined;
Expand Down Expand Up @@ -194,7 +194,7 @@ export abstract class Accumulator {
/**
* Get the accumulated value.
*/
abstract get accumulated(): Uint8Array;
abstract get accumulated(): T;

// The following functions optionally take secret key as an argument as its better to not store secret key in memory for
// long time.
Expand Down Expand Up @@ -261,7 +261,7 @@ export abstract class Accumulator {
element: Uint8Array,
secretKey?: AccumulatorSecretKey,
state?: IAccumulatorState
): Promise<VBMembershipWitness>;
): Promise<AccumulatorWitness<T>>;

/**
* Calculate the membership witnesses for the given batch of elements
Expand All @@ -273,7 +273,7 @@ export abstract class Accumulator {
elements: Uint8Array[],
secretKey?: AccumulatorSecretKey,
state?: IAccumulatorState
): Promise<VBMembershipWitness[]>;
): Promise<AccumulatorWitness<T>[]>;

/**
* Verify the membership witness.
Expand All @@ -284,7 +284,7 @@ export abstract class Accumulator {
*/
abstract verifyMembershipWitness(
member: Uint8Array,
witness: VBMembershipWitness,
witness: AccumulatorWitness<T>,
pk: AccumulatorPublicKey,
params?: AccumulatorParams
): boolean;
Expand Down Expand Up @@ -401,9 +401,9 @@ export abstract class Accumulator {
}

/**
* Accumulator that supports only membership proofs.
* VB accumulator that supports only membership proofs.
*/
export class PositiveAccumulator extends Accumulator {
export class PositiveAccumulator extends Accumulator<Uint8Array> {
// @ts-ignore
value: Uint8Array;

Expand Down Expand Up @@ -441,7 +441,7 @@ export class PositiveAccumulator extends Accumulator {
* Remove a single element from the accumulator
* @param element
* @param secretKey
* @param state- Optional. If provided, checked before removing and element is removed
* @param state Optional. If provided, checked before removing and element is removed
*/
async remove(element: Uint8Array, secretKey?: AccumulatorSecretKey, state?: IAccumulatorState) {
await this.ensurePresence(element, state);
Expand Down Expand Up @@ -576,12 +576,12 @@ export class PositiveAccumulator extends Accumulator {
}

/**
* Accumulator that supports both membership proofs and non-membership proofs. For guarding against forgery of
* VB accumulator that supports both membership proofs and non-membership proofs. For guarding against forgery of
* non-membership proofs (details in the paper), during initialization, it should generate several accumulator members
* and never remove them from accumulator, nor it should allow duplicates of them to be added. Thus, several methods
* accept an optional persistent database `IInitialElementsStore` which stores those initial elements.
*/
export class UniversalAccumulator extends Accumulator {
export class UniversalAccumulator extends Accumulator<Uint8Array> {
/**
* `f_V` is supposed to kept private by the accumulator manager. `V` is the accumulated value.
*/
Expand Down
59 changes: 13 additions & 46 deletions src/accumulator/accumulatorWitness.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
publicInfoForWitnessUpdate,
updateMembershipWitnessesPostBatchUpdates,
updateMembershipWitnessPostAdd,
updateMembershipWitnessPostRemove,
Expand All @@ -11,34 +10,34 @@ import {
updateNonMembershipWitnessUsingPublicInfoAfterBatchUpdate,
updateNonMembershipWitnessUsingPublicInfoAfterMultipleBatchUpdates
} from 'crypto-wasm-new';
import { getUint8ArraysFromObject, jsonObjToUint8Array } from '../util';
import { getUint8ArraysFromObject } from '../util';
import { AccumulatorSecretKey } from './params-and-keys';
import { BytearrayWrapper } from '../bytearray-wrapper';
import { VBWitnessUpdateInfo, WitnessUpdateInfo } from './witness-update-info';

export abstract class AccumulatorWitness {
export abstract class AccumulatorWitness<V> {
value: Uint8Array | object;

constructor(value: Uint8Array | object) {
this.value = value;
}

abstract updatePostAdd(addition: Uint8Array, element: Uint8Array, accumulatorValueBeforeAddition: Uint8Array): void;
abstract updatePostRemove(removal: Uint8Array, element: Uint8Array, accumulatorValueAfterRemoval: Uint8Array): void;
abstract updatePostAdd(addition: Uint8Array, element: Uint8Array, accumulatorValueBeforeAddition: V): void;
abstract updatePostRemove(removal: Uint8Array, element: Uint8Array, accumulatorValueAfterRemoval: V): void;
abstract updateUsingPublicInfoPostBatchUpdate(
element: Uint8Array,
additions: Uint8Array[],
removals: Uint8Array[],
publicInfo: VBWitnessUpdatePublicInfo
publicInfo: WitnessUpdateInfo
): void;
abstract updateUsingPublicInfoPostMultipleBatchUpdates(
element: Uint8Array,
additions: Uint8Array[][],
removals: Uint8Array[][],
publicInfo: VBWitnessUpdatePublicInfo[]
publicInfo: WitnessUpdateInfo[]
): void;
}

export class VBMembershipWitness extends AccumulatorWitness {
export class VBMembershipWitness extends AccumulatorWitness<Uint8Array> {
// @ts-ignore
value: Uint8Array;

Expand Down Expand Up @@ -73,7 +72,7 @@ export class VBMembershipWitness extends AccumulatorWitness {
member: Uint8Array,
additions: Uint8Array[],
removals: Uint8Array[],
publicInfo: VBWitnessUpdatePublicInfo
publicInfo: VBWitnessUpdateInfo
) {
this.value = updateMembershipWitnessUsingPublicInfoAfterBatchUpdate(
this.value,
Expand All @@ -96,7 +95,7 @@ export class VBMembershipWitness extends AccumulatorWitness {
member: Uint8Array,
additions: Uint8Array[][],
removals: Uint8Array[][],
publicInfo: VBWitnessUpdatePublicInfo[]
publicInfo: VBWitnessUpdateInfo[]
) {
const info = publicInfo.map((i) => i.value);
this.value = updateMembershipWitnessUsingPublicInfoAfterMultipleBatchUpdates(
Expand Down Expand Up @@ -149,7 +148,7 @@ export class VBMembershipWitness extends AccumulatorWitness {
}
}

export class VBNonMembershipWitness extends AccumulatorWitness {
export class VBNonMembershipWitness extends AccumulatorWitness<Uint8Array> {
// @ts-ignore
value: { d: Uint8Array; C: Uint8Array };

Expand Down Expand Up @@ -184,7 +183,7 @@ export class VBNonMembershipWitness extends AccumulatorWitness {
nonMember: Uint8Array,
additions: Uint8Array[],
removals: Uint8Array[],
publicInfo: VBWitnessUpdatePublicInfo
publicInfo: VBWitnessUpdateInfo
) {
this.value = updateNonMembershipWitnessUsingPublicInfoAfterBatchUpdate(
this.value,
Expand All @@ -207,7 +206,7 @@ export class VBNonMembershipWitness extends AccumulatorWitness {
nonMember: Uint8Array,
additions: Uint8Array[][],
removals: Uint8Array[][],
publicInfo: VBWitnessUpdatePublicInfo[]
publicInfo: VBWitnessUpdateInfo[]
) {
const info = publicInfo.map((i) => i.value);
this.value = updateNonMembershipWitnessUsingPublicInfoAfterMultipleBatchUpdates(
Expand Down Expand Up @@ -259,35 +258,3 @@ export class VBNonMembershipWitness extends AccumulatorWitness {
return new VBNonMembershipWitness({ d, C });
}
}

/**
* Public info published by the accumulator manager used to update witnesses after several additions and removals.
*/
export class VBWitnessUpdatePublicInfo extends BytearrayWrapper {
toJSON(): string {
return JSON.stringify({
value: this.value
});
}

fromJSON(json: string): VBWitnessUpdatePublicInfo {
return new VBWitnessUpdatePublicInfo(jsonObjToUint8Array(json));
}

/**
* Accumulator manager creates the witness update info corresponding to the additions and removals.
* @param accumulatorValueBeforeUpdates - accumulator value before the additions and removals
* @param additions
* @param removals
* @param sk
*/
static new(
accumulatorValueBeforeUpdates: Uint8Array,
additions: Uint8Array[],
removals: Uint8Array[],
sk: AccumulatorSecretKey
): VBWitnessUpdatePublicInfo {
const value = publicInfoForWitnessUpdate(accumulatorValueBeforeUpdates, additions, removals, sk.value);
return new VBWitnessUpdatePublicInfo(value);
}
}
72 changes: 71 additions & 1 deletion src/accumulator/in-memory-persistence.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IAccumulatorState, IUniversalAccumulatorState } from './IAccumulatorState';
import { IAccumulatorState, IKBUniversalAccumulatorState, IUniversalAccumulatorState } from './IAccumulatorState';
import { IInitialElementsStore } from './IInitialElementsStore';

/**
Expand All @@ -11,6 +11,10 @@ export class InMemoryState implements IAccumulatorState {
this.state = new Set<string>();
}

get size(): number {
return this.state.size;
}

async add(element: Uint8Array): Promise<void> {
const key = InMemoryState.key(element);
if (this.state.has(key)) {
Expand Down Expand Up @@ -75,3 +79,69 @@ export class InMemoryInitialElementsStore implements IInitialElementsStore {
return JSON.stringify(Array.from(element));
}
}

/**
* In memory implementation of the state. For testing only
*/
export class InMemoryKBUniversalState implements IKBUniversalAccumulatorState {
memState: Set<string>;
nonMemState: Set<string>;

constructor() {
this.memState = new Set<string>();
this.nonMemState = new Set<string>();
}

get size(): number {
return this.memState.size;
}

add(element: Uint8Array): Promise<void> {
const key = InMemoryKBUniversalState.key(element);
if (this.memState.has(key)) {
throw new Error(`${element} already present in mem state`);
}
if (!this.nonMemState.has(key)) {
throw new Error(`${element} not present in non mem state`);
}
this.memState.add(key);
this.nonMemState.delete(key);
return Promise.resolve();
}

has(element: Uint8Array): Promise<boolean> {
const key = InMemoryKBUniversalState.key(element);
// Ideally, something present in `memState` should not be present in `nonMemState` and vice-versa
const b = this.memState.has(key) && !this.nonMemState.has(key);
return Promise.resolve(b);
}

remove(element: Uint8Array): Promise<void> {
const key = InMemoryKBUniversalState.key(element);
if (!this.memState.has(key)) {
throw new Error(`${element} not present in mem state`);
}
if (this.nonMemState.has(key)) {
throw new Error(`${element} already present in non mem state`);
}
this.memState.delete(key);
this.nonMemState.add(key);
return Promise.resolve();
}

static key(element: Uint8Array) {
return JSON.stringify(Array.from(element));
}

inDomain(element: Uint8Array): Promise<boolean> {
const key = InMemoryKBUniversalState.key(element);
const b = this.nonMemState.has(key) || this.memState.has(key);
return Promise.resolve(b);
}

async addToDomain(element: Uint8Array) {
const key = InMemoryKBUniversalState.key(element);
this.nonMemState.add(key);
return Promise.resolve();
}
}
1 change: 1 addition & 0 deletions src/accumulator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './accumulatorWitness';
export * from './proof';
export * from './IAccumulatorState';
export * from './IInitialElementsStore';
export { VBWitnessUpdateInfo } from './witness-update-info';
Loading

0 comments on commit 11b8b21

Please sign in to comment.