From 9e439870f47dcb1db1520f293df883de945cefb7 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 6 Jan 2025 14:08:14 +0700 Subject: [PATCH 01/35] feat: add acl to DRPobject --- packages/object/src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 07b7689d..c2e706c7 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -63,6 +63,7 @@ export class DRPObject implements IDRPObject { bytecode: Uint8Array; vertices: ObjectPb.Vertex[]; drp: ProxyHandler | null; + acl?: IACL & DRP; hashGraph: HashGraph; // mapping from vertex hash to the DRP state states: Map; @@ -72,6 +73,7 @@ export class DRPObject implements IDRPObject { constructor( peerId: string, drp: DRP, + acl?: IACL & DRP, id?: string, abi?: string, config?: DRPObjectConfig, @@ -90,6 +92,7 @@ export class DRPObject implements IDRPObject { this.bytecode = new Uint8Array(); this.vertices = []; this.drp = drp ? new Proxy(drp, this.proxyDRPHandler()) : null; + this.acl = acl; this.hashGraph = new HashGraph( peerId, drp?.resolveConflicts?.bind(drp ?? this), From ce5f3ed23d41f18d2eb682070d5b0eccd9e5637e Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 11:55:30 +0700 Subject: [PATCH 02/35] feat: update proto --- .../src/proto/drp/object/v1/object_pb.ts | 21 +++++++++++++++++-- .../src/proto/drp/object/v1/object.proto | 1 + .../src/proto/drp/object/v1/object_grpc_pb.js | 1 + .../src/proto/drp/object/v1/object_pb.ts | 21 +++++++++++++++++-- .../src/proto/google/protobuf/struct_pb.ts | 2 +- 5 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 packages/object/src/proto/drp/object/v1/object_grpc_pb.js diff --git a/packages/network/src/proto/drp/object/v1/object_pb.ts b/packages/network/src/proto/drp/object/v1/object_pb.ts index 0b75129e..4b19805c 100644 --- a/packages/network/src/proto/drp/object/v1/object_pb.ts +++ b/packages/network/src/proto/drp/object/v1/object_pb.ts @@ -1,6 +1,6 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: -// protoc-gen-ts_proto v2.5.0 +// protoc-gen-ts_proto v2.6.0 // protoc unknown // source: drp/object/v1/object.proto @@ -23,6 +23,7 @@ export interface Vertex { export interface Vertex_Operation { type: string; value: any | undefined; + prefix: string; } export interface DRPObjectBase { @@ -177,7 +178,7 @@ export const Vertex: MessageFns = { }; function createBaseVertex_Operation(): Vertex_Operation { - return { type: "", value: undefined }; + return { type: "", value: undefined, prefix: "" }; } export const Vertex_Operation: MessageFns = { @@ -188,6 +189,9 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).join(); } + if (message.prefix !== "") { + writer.uint32(26).string(message.prefix); + } return writer; }, @@ -214,6 +218,14 @@ export const Vertex_Operation: MessageFns = { message.value = Value.unwrap(Value.decode(reader, reader.uint32())); continue; } + case 3: { + if (tag !== 26) { + break; + } + + message.prefix = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -227,6 +239,7 @@ export const Vertex_Operation: MessageFns = { return { type: isSet(object.type) ? globalThis.String(object.type) : "", value: isSet(object?.value) ? object.value : undefined, + prefix: isSet(object.prefix) ? globalThis.String(object.prefix) : "", }; }, @@ -238,6 +251,9 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { obj.value = message.value; } + if (message.prefix !== "") { + obj.prefix = message.prefix; + } return obj; }, @@ -248,6 +264,7 @@ export const Vertex_Operation: MessageFns = { const message = createBaseVertex_Operation(); message.type = object.type ?? ""; message.value = object.value ?? undefined; + message.prefix = object.prefix ?? ""; return message; }, }; diff --git a/packages/object/src/proto/drp/object/v1/object.proto b/packages/object/src/proto/drp/object/v1/object.proto index 3ee17d5e..59e510d9 100644 --- a/packages/object/src/proto/drp/object/v1/object.proto +++ b/packages/object/src/proto/drp/object/v1/object.proto @@ -9,6 +9,7 @@ message Vertex { message Operation { string type = 1; google.protobuf.Value value = 2; + string prefix = 3; } string hash = 1; string peer_id = 2; diff --git a/packages/object/src/proto/drp/object/v1/object_grpc_pb.js b/packages/object/src/proto/drp/object/v1/object_grpc_pb.js new file mode 100644 index 00000000..97b3a246 --- /dev/null +++ b/packages/object/src/proto/drp/object/v1/object_grpc_pb.js @@ -0,0 +1 @@ +// GENERATED CODE -- NO SERVICES IN PROTO \ No newline at end of file diff --git a/packages/object/src/proto/drp/object/v1/object_pb.ts b/packages/object/src/proto/drp/object/v1/object_pb.ts index 0b75129e..4b19805c 100644 --- a/packages/object/src/proto/drp/object/v1/object_pb.ts +++ b/packages/object/src/proto/drp/object/v1/object_pb.ts @@ -1,6 +1,6 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: -// protoc-gen-ts_proto v2.5.0 +// protoc-gen-ts_proto v2.6.0 // protoc unknown // source: drp/object/v1/object.proto @@ -23,6 +23,7 @@ export interface Vertex { export interface Vertex_Operation { type: string; value: any | undefined; + prefix: string; } export interface DRPObjectBase { @@ -177,7 +178,7 @@ export const Vertex: MessageFns = { }; function createBaseVertex_Operation(): Vertex_Operation { - return { type: "", value: undefined }; + return { type: "", value: undefined, prefix: "" }; } export const Vertex_Operation: MessageFns = { @@ -188,6 +189,9 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).join(); } + if (message.prefix !== "") { + writer.uint32(26).string(message.prefix); + } return writer; }, @@ -214,6 +218,14 @@ export const Vertex_Operation: MessageFns = { message.value = Value.unwrap(Value.decode(reader, reader.uint32())); continue; } + case 3: { + if (tag !== 26) { + break; + } + + message.prefix = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -227,6 +239,7 @@ export const Vertex_Operation: MessageFns = { return { type: isSet(object.type) ? globalThis.String(object.type) : "", value: isSet(object?.value) ? object.value : undefined, + prefix: isSet(object.prefix) ? globalThis.String(object.prefix) : "", }; }, @@ -238,6 +251,9 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { obj.value = message.value; } + if (message.prefix !== "") { + obj.prefix = message.prefix; + } return obj; }, @@ -248,6 +264,7 @@ export const Vertex_Operation: MessageFns = { const message = createBaseVertex_Operation(); message.type = object.type ?? ""; message.value = object.value ?? undefined; + message.prefix = object.prefix ?? ""; return message; }, }; diff --git a/packages/object/src/proto/google/protobuf/struct_pb.ts b/packages/object/src/proto/google/protobuf/struct_pb.ts index b0b633ad..2789c990 100644 --- a/packages/object/src/proto/google/protobuf/struct_pb.ts +++ b/packages/object/src/proto/google/protobuf/struct_pb.ts @@ -1,6 +1,6 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: -// protoc-gen-ts_proto v2.5.0 +// protoc-gen-ts_proto v2.6.0 // protoc unknown // source: google/protobuf/struct.proto From 874e342e29d928d112ebe10cd62753869a3b905a Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 12:08:15 +0700 Subject: [PATCH 03/35] feat: handle move acl from DRP to DRPObject --- packages/node/src/handlers.ts | 11 ++- packages/node/src/index.ts | 2 +- packages/object/src/index.ts | 172 ++++++++++++++++++++++++++++++---- 3 files changed, 163 insertions(+), 22 deletions(-) diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index fe591f23..4b29f858 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -1,6 +1,6 @@ import type { Stream } from "@libp2p/interface"; import { NetworkPb, streamToUint8Array } from "@ts-drp/network"; -import type { DRP, DRPObject, ObjectPb, Vertex } from "@ts-drp/object"; +import { PrefixOperation, type DRP, type DRPObject, type IACL, type ObjectPb, type Vertex } from "@ts-drp/object"; import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; import { type DRPNode, log } from "./index.js"; @@ -230,12 +230,14 @@ export async function verifyIncomingVertices( incomingVertices: ObjectPb.Vertex[], ): Promise { const vertices: Vertex[] = incomingVertices.map((vertex) => { + const prefix = vertex.operation ? vertex.operation.prefix : PrefixOperation.drp; return { hash: vertex.hash, peerId: vertex.peerId, operation: { type: vertex.operation?.type ?? "", value: vertex.operation?.value, + prefix, }, dependencies: vertex.dependencies, timestamp: vertex.timestamp, @@ -244,10 +246,13 @@ export async function verifyIncomingVertices( }); const drp = object.drp as DRP; - if (!drp.acl) { + // if (!drp.acl) { + // return vertices; + // } + const acl: IACL & DRP = object.acl as IACL & DRP; + if (!acl) { return vertices; } - const acl = drp.acl; const verificationPromises = vertices.map(async (vertex) => { if (vertex.signature === "") { return null; diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 9aa54354..51b51604 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -78,7 +78,7 @@ export class DRPNode { sync?: boolean, peerId?: string, ) { - const object = new DRPObject(this.networkNode.peerId, drp, id, abi); + const object = new DRPObject(this.networkNode.peerId, drp, null, id, abi); operations.createObject(this, object); operations.subscribeObject(this, object.id); if (sync) { diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index c2e706c7..0f9f6fc0 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -56,6 +56,21 @@ export interface DRPObjectConfig { export let log: Logger; +export enum PrefixOperation { + acl = "acl", + drp = "drp", +} + +export const isACLInterface = (target: object): boolean => { + return ( + typeof (target as IACL).isWriter === "function" && + typeof (target as IACL).isAdmin === "function" && + typeof (target as IACL).grant === "function" && + typeof (target as IACL).revoke === "function" && + typeof (target as IACL).getPeerKey === "function" + ); +}; + export class DRPObject implements IDRPObject { peerId: string; id: string; @@ -63,17 +78,19 @@ export class DRPObject implements IDRPObject { bytecode: Uint8Array; vertices: ObjectPb.Vertex[]; drp: ProxyHandler | null; - acl?: IACL & DRP; + acl: ProxyHandler | null; hashGraph: HashGraph; // mapping from vertex hash to the DRP state states: Map; + statesAcl: Map; originalDRP: DRP; + originalACL: IACL & DRP; subscriptions: DRPObjectCallback[]; constructor( peerId: string, drp: DRP, - acl?: IACL & DRP, + acl: IACL & DRP, id?: string, abi?: string, config?: DRPObjectConfig, @@ -92,24 +109,39 @@ export class DRPObject implements IDRPObject { this.bytecode = new Uint8Array(); this.vertices = []; this.drp = drp ? new Proxy(drp, this.proxyDRPHandler()) : null; - this.acl = acl; + this.acl = acl ? new Proxy(acl, this.proxyDRPHandler()) : null; this.hashGraph = new HashGraph( peerId, - drp?.resolveConflicts?.bind(drp ?? this), + this.resolveConflicts.bind(this), drp?.semanticsType, ); this.subscriptions = []; this.states = new Map([[HashGraph.rootHash, { state: new Map() }]]); + this.statesAcl = new Map([[HashGraph.rootHash, { state: new Map() }]]); this.originalDRP = cloneDeep(drp); + this.originalACL = cloneDeep(acl); this.vertices = this.hashGraph.getAllVertices(); } + resolveConflicts(vertices: Vertex[]): ResolveConflictsType { + if (this.acl) { + const acl = this.acl as IACL & DRP; + acl.resolveConflicts(vertices); + } + const drp = this.drp as DRP; + return drp.resolveConflicts(vertices); + } + // This function is black magic, it allows us to intercept calls to the DRP object proxyDRPHandler(parentProp?: string): ProxyHandler { const obj = this; return { get(target, propKey, receiver) { const value = Reflect.get(target, propKey, receiver); + let prefix = PrefixOperation.drp; + if (isACLInterface(target)) { + prefix = PrefixOperation.acl; + } if (typeof value === "function") { const fullPropKey = parentProp @@ -118,7 +150,11 @@ export class DRPObject implements IDRPObject { return new Proxy(target[propKey as keyof object], { apply(applyTarget, thisArg, args) { if ((thisArg.operations as string[]).includes(propKey as string)) - obj.callFn(fullPropKey, args.length === 1 ? args[0] : args); + obj.callFn( + fullPropKey, + args.length === 1 ? args[0] : args, + prefix, + ); return Reflect.apply(applyTarget, thisArg, args); }, }); @@ -139,8 +175,12 @@ export class DRPObject implements IDRPObject { } // biome-ignore lint: value can't be unknown because of protobuf - callFn(fn: string, args: any) { - const vertex = this.hashGraph.addToFrontier({ type: fn, value: args }); + callFn(fn: string, args: any, prefix: PrefixOperation = PrefixOperation.drp) { + const vertex = this.hashGraph.addToFrontier({ + type: fn, + value: args, + prefix: prefix, + }); this._setState(vertex); const serializedVertex = ObjectPb.Vertex.create({ @@ -160,6 +200,7 @@ export class DRPObject implements IDRPObject { */ merge(vertices: Vertex[]): [merged: boolean, missing: string[]] { const missing = []; + let needUpdateACLState = false; for (const vertex of vertices) { // Check to avoid manually crafted `undefined` operations if (!vertex.operation || this.hashGraph.vertices.has(vertex.hash)) { @@ -167,10 +208,14 @@ export class DRPObject implements IDRPObject { } try { - const drp = this._computeDRP(vertex.dependencies); - if (!this._checkWriterPermission(drp, vertex.peerId)) { + const drp = + vertex.operation.prefix === PrefixOperation.acl + ? this._computeACL(vertex.dependencies) + : this._computeDRP(vertex.dependencies); + if (!this._checkWriterPermission(vertex.peerId)) { throw new Error(`${vertex.peerId} does not have write permission.`); } + needUpdateACLState = vertex.operation.prefix === PrefixOperation.acl; this.hashGraph.addVertex( vertex.operation, @@ -181,14 +226,20 @@ export class DRPObject implements IDRPObject { ); this._applyOperation(drp, vertex.operation); - this._setState(vertex, this._getDRPState(drp)); + if (vertex.operation.prefix === PrefixOperation.acl) { + this._setACLState(vertex, this._getDRPState(drp)); + this._setDRPState(vertex); + } else { + this._setACLState(vertex); + this._setDRPState(vertex, this._getDRPState(drp)); + } } catch (e) { missing.push(vertex.hash); } } this.vertices = this.hashGraph.getAllVertices(); - + this._updateACLState(); this._updateDRPState(); this._notify("merge", this.vertices); @@ -206,11 +257,10 @@ export class DRPObject implements IDRPObject { } // check if the given peer has write permission - private _checkWriterPermission(drp: DRP, peerId: string): boolean { - if (drp.acl) { - return drp.acl.isWriter(peerId); - } - return true; + private _checkWriterPermission(peerId: string): boolean { + return this.acl + ? Reflect.get(this.acl, "isWriter").call(this.acl, peerId) + : true; } // apply the operation to the DRP @@ -268,15 +318,56 @@ export class DRPObject implements IDRPObject { } for (const op of linearizedOperations) { - this._applyOperation(drp, op); + op.prefix === PrefixOperation.drp && this._applyOperation(drp, op); } if (vertexOperation) { - this._applyOperation(drp, vertexOperation); + vertexOperation.prefix === PrefixOperation.drp && + this._applyOperation(drp, vertexOperation); } return drp; } + private _computeACL( + vertexDependencies: Hash[], + vertexOperation?: Operation, + ): DRP { + const subgraph: ObjectSet = new ObjectSet(); + const lca = + vertexDependencies.length === 1 + ? vertexDependencies[0] + : this.hashGraph.lowestCommonAncestorMultipleVertices( + vertexDependencies, + subgraph, + ); + const linearizedOperations = + vertexDependencies.length === 1 + ? [] + : this.hashGraph.linearizeOperations(lca, subgraph); + + const acl = cloneDeep(this.originalACL); + + const fetchedState = this.statesAcl.get(lca); + if (!fetchedState) { + throw new Error("State is undefined"); + } + + const state = cloneDeep(fetchedState); + + for (const [key, value] of state.state) { + acl[key] = value; + } + for (const op of linearizedOperations) { + op.prefix === PrefixOperation.acl && this._applyOperation(acl, op); + } + if (vertexOperation) { + vertexOperation.prefix === PrefixOperation.acl && + this._applyOperation(acl, vertexOperation); + } + + return acl; + } + // get the map representing the state of the given DRP by mapping variable names to their corresponding values private _getDRPState( drp: DRP, @@ -303,11 +394,43 @@ export class DRPObject implements IDRPObject { return this._getDRPState(drp); } + private _computeACLState( + vertexDependencies: Hash[], + vertexOperation?: Operation, + // biome-ignore lint: values can be anything + ): DRPState { + const drp = this._computeACL(vertexDependencies, vertexOperation); + return this._getDRPState(drp); + } + // store the state of the DRP corresponding to the given vertex private _setState( vertex: Vertex, // biome-ignore lint: values can be anything drpState?: DRPState, + ) { + this._setACLState(vertex, drpState); + this._setDRPState(vertex, drpState); + } + + private _setACLState( + vertex: Vertex, + // biome-ignore lint: values can be anything + drpState?: DRPState, + ) { + if (this.acl) { + this.statesAcl.set( + vertex.hash, + drpState ?? + this._computeACLState(vertex.dependencies, vertex.operation), + ); + } + } + + private _setDRPState( + vertex: Vertex, + // biome-ignore lint: values can be anything + drpState?: DRPState, ) { this.states.set( vertex.hash, @@ -328,4 +451,17 @@ export class DRPObject implements IDRPObject { } } } + + private _updateACLState() { + if (!this.acl) { + return; + } + const currentACL = this.acl as IACL & DRP; + const newState = this._computeACLState(this.hashGraph.getFrontier()); + for (const [key, value] of newState.state.entries()) { + if (key in currentACL && typeof currentACL[key] !== "function") { + currentACL[key] = value; + } + } + } } From 327b726c89af15c54f3629fab59a84f1a7d98aa1 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 12:08:24 +0700 Subject: [PATCH 04/35] Update testcase --- packages/node/tests/node.test.ts | 2 +- .../object/tests/causallyrelated.bench.ts | 19 +- packages/object/tests/hashgraph.test.ts | 361 +++++++++++------- 3 files changed, 232 insertions(+), 150 deletions(-) diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index 06559b27..bbbf1b95 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -113,6 +113,6 @@ describe("DPRNode with verify and sign signature", () => { }, ]; const verifiedVertices = await verifyIncomingVertices(drpObject, vertices); - expect(verifiedVertices.length).toBe(0); + expect(verifiedVertices.length).toBe(1); }); }); diff --git a/packages/object/tests/causallyrelated.bench.ts b/packages/object/tests/causallyrelated.bench.ts index a9c79e04..51097358 100644 --- a/packages/object/tests/causallyrelated.bench.ts +++ b/packages/object/tests/causallyrelated.bench.ts @@ -1,14 +1,27 @@ import { bench, describe } from "vitest"; import { AddWinsSet } from "../../blueprints/src/AddWinsSet/index.js"; import { DRPObject, type Hash } from "../src/index.js"; +import type { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; describe("AreCausallyDependent benchmark", async () => { const samples = 100000; const tests: Hash[][] = []; - const obj1 = new DRPObject("peer1", new AddWinsSet()); - const obj2 = new DRPObject("peer2", new AddWinsSet()); - const obj3 = new DRPObject("peer3", new AddWinsSet()); + const obj1 = new DRPObject( + "peer1", + new AddWinsSet(), + null as unknown as ACL, + ); + const obj2 = new DRPObject( + "peer2", + new AddWinsSet(), + null as unknown as ACL, + ); + const obj3 = new DRPObject( + "peer3", + new AddWinsSet(), + null as unknown as ACL, + ); const drp1 = obj1.drp as AddWinsSet; const drp2 = obj2.drp as AddWinsSet; diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 3e8eeae7..1ff5f753 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -1,15 +1,18 @@ import { AddWinsSetWithACL } from "@topology-foundation/blueprints/src/AddWinsSetWithACL/index.js"; -import { beforeEach, describe, expect, test } from "vitest"; +import { beforeEach, describe, expect, expectTypeOf, test } from "vitest"; import { AddWinsSet } from "../../blueprints/src/AddWinsSet/index.js"; import { DRPObject, type Operation, OperationType } from "../src/index.js"; +import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; describe("HashGraph construction tests", () => { let obj1: DRPObject; let obj2: DRPObject; beforeEach(async () => { - obj1 = new DRPObject("peer1", new AddWinsSet()); - obj2 = new DRPObject("peer2", new AddWinsSet()); + // biome-ignore lint/suspicious/noExplicitAny: + obj1 = new DRPObject("peer1", new AddWinsSet(), null as any); + // biome-ignore lint/suspicious/noExplicitAny: + obj2 = new DRPObject("peer2", new AddWinsSet(), null as any); }); test("Test: Vertices are consistent across data structures", () => { @@ -49,9 +52,9 @@ describe("HashGraph construction tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { type: "add", value: 2 }, - { type: "add", value: 1 }, - ]); + { type: "add", value: 2, prefix: "drp" }, + { type: "add", value: 1, prefix: "drp" }, + ] as Operation[]); }); test("Test: HashGraph with 2 root vertices", () => { @@ -66,6 +69,7 @@ describe("HashGraph construction tests", () => { { type: "root", value: null, + prefix: "drp", }, [], "", @@ -76,6 +80,7 @@ describe("HashGraph construction tests", () => { { type: "add", value: 1, + prefix: "drp", }, [hash], "", @@ -85,7 +90,8 @@ describe("HashGraph construction tests", () => { expect(obj1.hashGraph.selfCheckConstraints()).toBe(false); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([{ type: "add", value: 1 }]); + const expectedOps: Operation[] = [{ type: "add", value: 1, prefix: "drp" }]; + expect(linearOps).toEqual(expectedOps); }); }); @@ -95,9 +101,21 @@ describe("HashGraph for AddWinSet tests", () => { let obj3: DRPObject; beforeEach(async () => { - obj1 = new DRPObject("peer1", new AddWinsSet()); - obj2 = new DRPObject("peer2", new AddWinsSet()); - obj3 = new DRPObject("peer3", new AddWinsSet()); + obj1 = new DRPObject( + "peer1", + new AddWinsSet(), + null as unknown as ACL, + ); + obj2 = new DRPObject( + "peer2", + new AddWinsSet(), + null as unknown as ACL, + ); + obj3 = new DRPObject( + "peer3", + new AddWinsSet(), + null as unknown as ACL, + ); }); test("Test: Add Two Vertices", () => { @@ -111,10 +129,15 @@ describe("HashGraph for AddWinSet tests", () => { expect(drp1.contains(1)).toBe(false); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "remove", value: 1 }, - ]); + const expectedOps: Operation[] = [ + { + type: "add", + value: 1, + prefix: "drp", + }, + { type: "remove", value: 1, prefix: "drp" }, + ]; + expect(linearOps).toEqual(expectedOps); }); test("Test: Add Two Concurrent Vertices With Same Value", () => { @@ -139,10 +162,11 @@ describe("HashGraph for AddWinSet tests", () => { expect(obj1.hashGraph.vertices).toEqual(obj2.hashGraph.vertices); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "add", value: 1 }, - ]); + const expectedOps: Operation[] = [ + { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 1, prefix: "drp" }, + ]; + expect(linearOps).toEqual(expectedOps); }); test("Test: Add Two Concurrent Vertices With Different Values", () => { @@ -168,11 +192,12 @@ describe("HashGraph for AddWinSet tests", () => { expect(obj1.hashGraph.vertices).toEqual(obj2.hashGraph.vertices); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "remove", value: 1 }, - { type: "add", value: 2 }, - ]); + const expectedOps: Operation[] = [ + { type: "add", value: 1, prefix: "drp" }, + { type: "remove", value: 1, prefix: "drp" }, + { type: "add", value: 2, prefix: "drp" }, + ]; + expect(linearOps).toEqual(expectedOps); }); test("Test: Tricky Case", () => { @@ -201,12 +226,13 @@ describe("HashGraph for AddWinSet tests", () => { expect(obj1.hashGraph.vertices).toEqual(obj2.hashGraph.vertices); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "add", value: 1 }, - { type: "add", value: 10 }, - { type: "remove", value: 5 }, - ]); + const expectedOps: Operation[] = [ + { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 10, prefix: "drp" }, + { type: "remove", value: 5, prefix: "drp" }, + ]; + expect(linearOps).toEqual(expectedOps); }); test("Test: Yuta Papa's Case", () => { @@ -234,11 +260,12 @@ describe("HashGraph for AddWinSet tests", () => { expect(obj1.hashGraph.vertices).toEqual(obj2.hashGraph.vertices); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "add", value: 2 }, - { type: "add", value: 1 }, - ]); + const expectedOps: Operation[] = [ + { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 2, prefix: "drp" }, + { type: "add", value: 1, prefix: "drp" }, + ]; + expect(linearOps).toEqual(expectedOps); }); test("Test: Mega Complex Case", () => { @@ -287,14 +314,15 @@ describe("HashGraph for AddWinSet tests", () => { expect(obj1.hashGraph.vertices).toEqual(obj3.hashGraph.vertices); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "add", value: 1 }, - { type: "remove", value: 2 }, - { type: "add", value: 2 }, - { type: "remove", value: 1 }, - { type: "add", value: 3 }, - ]); + const expectedOps: Operation[] = [ + { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 1, prefix: "drp" }, + { type: "remove", value: 2, prefix: "drp" }, + { type: "add", value: 2, prefix: "drp" }, + { type: "remove", value: 1, prefix: "drp" }, + { type: "add", value: 3, prefix: "drp" }, + ]; + expect(linearOps).toEqual(expectedOps); }); test("Test: Mega Complex Case 1", () => { @@ -344,14 +372,14 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "add", value: 1 }, - { type: "remove", value: 2 }, - { type: "remove", value: 2 }, - { type: "remove", value: 1 }, - { type: "add", value: 3 }, - { type: "add", value: 2 }, - { type: "remove", value: 1 }, + { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 1, prefix: "drp" }, + { type: "remove", value: 2, prefix: "drp" }, + { type: "remove", value: 2, prefix: "drp" }, + { type: "remove", value: 1, prefix: "drp" }, + { type: "add", value: 3, prefix: "drp" }, + { type: "add", value: 2, prefix: "drp" }, + { type: "remove", value: 1, prefix: "drp" }, ]); }); @@ -382,11 +410,12 @@ describe("HashGraph for AddWinSet tests", () => { expect(obj1.hashGraph.vertices).toEqual(obj2.hashGraph.vertices); const linearOps = obj1.hashGraph.linearizeOperations(); - expect(linearOps).toEqual([ - { type: "add", value: 1 }, - { type: "add", value: 2 }, - { type: "remove", value: 2 }, - ]); + const expectedOps: Operation[] = [ + { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 2, prefix: "drp" }, + { type: "remove", value: 2, prefix: "drp" }, + ]; + expect(linearOps).toEqual(expectedOps); }); }); @@ -395,8 +424,16 @@ describe("HashGraph for undefined operations tests", () => { let obj2: DRPObject; beforeEach(async () => { - obj1 = new DRPObject("peer1", new AddWinsSet()); - obj2 = new DRPObject("peer2", new AddWinsSet()); + obj1 = new DRPObject( + "peer1", + new AddWinsSet(), + null as unknown as ACL, + ); + obj2 = new DRPObject( + "peer2", + new AddWinsSet(), + null as unknown as ACL, + ); }); test("Test: merge should skip undefined operations", () => { @@ -413,7 +450,7 @@ describe("HashGraph for undefined operations tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); // Should only have one, since we skipped the undefined operations - expect(linearOps).toEqual([{ type: "add", value: 2 }]); + expect(linearOps).toEqual([{ type: "add", value: 2, prefix: "drp" }]); }); test("Test: addToFrontier with undefined operation return Vertex with NoOp operation", () => { @@ -434,9 +471,21 @@ describe("Vertex state tests", () => { let obj3: DRPObject; beforeEach(async () => { - obj1 = new DRPObject("peer1", new AddWinsSet()); - obj2 = new DRPObject("peer2", new AddWinsSet()); - obj3 = new DRPObject("peer3", new AddWinsSet()); + obj1 = new DRPObject( + "peer1", + new AddWinsSet(), + null as unknown as ACL, + ); + obj2 = new DRPObject( + "peer2", + new AddWinsSet(), + null as unknown as ACL, + ); + obj3 = new DRPObject( + "peer3", + new AddWinsSet(), + null as unknown as ACL, + ); }); test("Test: Vertex states work correctly with single HashGraph", () => { @@ -575,9 +624,21 @@ describe("Vertex timestamp tests", () => { let obj3: DRPObject; beforeEach(async () => { - obj1 = new DRPObject("peer1", new AddWinsSet()); - obj2 = new DRPObject("peer1", new AddWinsSet()); - obj3 = new DRPObject("peer1", new AddWinsSet()); + obj1 = new DRPObject( + "peer1", + new AddWinsSet(), + null as unknown as ACL, + ); + obj2 = new DRPObject( + "peer1", + new AddWinsSet(), + null as unknown as ACL, + ); + obj3 = new DRPObject( + "peer1", + new AddWinsSet(), + null as unknown as ACL, + ); }); test("Test: Vertex created in the future is invalid", () => { @@ -590,6 +651,7 @@ describe("Vertex timestamp tests", () => { { type: "add", value: 1, + prefix: "drp", }, obj1.hashGraph.getFrontier(), "", @@ -624,6 +686,7 @@ describe("Vertex timestamp tests", () => { { type: "add", value: 1, + prefix: "drp", }, obj1.hashGraph.getFrontier(), "", @@ -634,71 +697,73 @@ describe("Vertex timestamp tests", () => { }); }); -describe("Operation with ACL tests", () => { - let obj1: DRPObject; - let obj2: DRPObject; - - beforeEach(async () => { - const peerIdToPublicKey = new Map([ - ["peer1", "publicKey1"], - ]); - obj1 = new DRPObject( - "peer1", - new AddWinsSetWithACL(peerIdToPublicKey), - ); - obj2 = new DRPObject( - "peer2", - new AddWinsSetWithACL(peerIdToPublicKey), - ); - }); - - test("Node with admin permission can grant permission to other nodes", () => { - /* - ROOT -- V1:GRANT("peer2") - */ - - const drp1 = obj1.drp as AddWinsSetWithACL; - const drp2 = obj2.drp as AddWinsSetWithACL; - - drp1.acl.grant("peer1", "peer2", "publicKey2"); - obj2.merge(obj1.hashGraph.getAllVertices()); - expect(drp2.acl.isWriter("peer2")).toBe(true); - }); - - test("Node with writer permission can create vertices", () => { - /* - ROOT -- V1:GRANT("peer2") -- V2:ADD(1) - */ - const drp1 = obj1.drp as AddWinsSetWithACL; - const drp2 = obj2.drp as AddWinsSetWithACL; - - drp1.acl.grant("peer1", "peer2", "publicKey2"); - obj2.merge(obj1.hashGraph.getAllVertices()); - - drp2.add(1); - obj1.merge(obj2.hashGraph.getAllVertices()); - expect(drp1.contains(1)).toBe(true); - }); - - test("Revoke permission from writer", () => { - /* - ROOT -- V1:GRANT("peer2") -- V2:ADD(1) -- V3:REVOKE("peer2") - */ - const drp1 = obj1.drp as AddWinsSetWithACL; - const drp2 = obj2.drp as AddWinsSetWithACL; - - drp1.acl.grant("peer1", "peer2", "publicKey2"); - obj2.merge(obj1.hashGraph.getAllVertices()); - - expect(drp2.acl.isWriter("peer2")).toBe(true); - drp2.add(1); - - obj1.merge(obj2.hashGraph.getAllVertices()); - drp1.acl.revoke("peer1", "peer2"); - obj2.merge(obj1.hashGraph.getAllVertices()); - expect(drp2.acl.isWriter("peer2")).toBe(false); - }); -}); +// describe("Operation with ACL tests", () => { +// let obj1: DRPObject; +// let obj2: DRPObject; + +// beforeEach(async () => { +// const peerIdToPublicKey = new Map([ +// ["peer1", "publicKey1"], +// ]); +// obj1 = new DRPObject( +// "peer1", +// new AddWinsSetWithACL(peerIdToPublicKey), +// null as unknown as ACL, +// ); +// obj2 = new DRPObject( +// "peer2", +// new AddWinsSetWithACL(peerIdToPublicKey), +// null as unknown as ACL, +// ); +// }); + +// test("Node with admin permission can grant permission to other nodes", () => { +// /* +// ROOT -- V1:GRANT("peer2") +// */ + +// const drp1 = obj1.drp as AddWinsSetWithACL; +// const drp2 = obj2.drp as AddWinsSetWithACL; + +// drp1.acl.grant("peer1", "peer2", "publicKey2"); +// obj2.merge(obj1.hashGraph.getAllVertices()); +// expect(drp2.acl.isWriter("peer2")).toBe(true); +// }); + +// test("Node with writer permission can create vertices", () => { +// /* +// ROOT -- V1:GRANT("peer2") -- V2:ADD(1) +// */ +// const drp1 = obj1.drp as AddWinsSetWithACL; +// const drp2 = obj2.drp as AddWinsSetWithACL; + +// drp1.acl.grant("peer1", "peer2", "publicKey2"); +// obj2.merge(obj1.hashGraph.getAllVertices()); + +// drp2.add(1); +// obj1.merge(obj2.hashGraph.getAllVertices()); +// expect(drp1.contains(1)).toBe(true); +// }); + +// test("Revoke permission from writer", () => { +// /* +// ROOT -- V1:GRANT("peer2") -- V2:ADD(1) -- V3:REVOKE("peer2") +// */ +// const drp1 = obj1.drp as AddWinsSetWithACL; +// const drp2 = obj2.drp as AddWinsSetWithACL; + +// drp1.acl.grant("peer1", "peer2", "publicKey2"); +// obj2.merge(obj1.hashGraph.getAllVertices()); + +// expect(drp2.acl.isWriter("peer2")).toBe(true); +// drp2.add(1); + +// obj1.merge(obj2.hashGraph.getAllVertices()); +// drp1.acl.revoke("peer1", "peer2"); +// obj2.merge(obj1.hashGraph.getAllVertices()); +// expect(drp2.acl.isWriter("peer2")).toBe(false); +// }); +// }); describe("Writer permission tests", () => { let obj1: DRPObject; @@ -707,13 +772,14 @@ describe("Writer permission tests", () => { beforeEach(async () => { const peerIdToPublicKeyMap = new Map([["peer1", "publicKey1"]]); - obj1 = new DRPObject("peer1", new AddWinsSetWithACL(peerIdToPublicKeyMap)); - obj2 = new DRPObject("peer2", new AddWinsSetWithACL(peerIdToPublicKeyMap)); - obj3 = new DRPObject("peer3", new AddWinsSetWithACL(peerIdToPublicKeyMap)); + const acl = new ACL(peerIdToPublicKeyMap); + obj1 = new DRPObject("peer1", new AddWinsSet(), acl); + obj2 = new DRPObject("peer2", new AddWinsSet(), acl); + obj3 = new DRPObject("peer3", new AddWinsSet(), acl); }); test("Node without writer permission can generate vertex locally", () => { - const drp = obj1.drp as AddWinsSetWithACL; + const drp = obj1.drp as AddWinsSet; drp.add(1); drp.add(2); @@ -722,8 +788,8 @@ describe("Writer permission tests", () => { }); test("Discard vertex if creator does not have write permission", () => { - const drp1 = obj1.drp as AddWinsSetWithACL; - const drp2 = obj2.drp as AddWinsSetWithACL; + const drp1 = obj1.drp as AddWinsSet; + const drp2 = obj2.drp as AddWinsSet; drp1.add(1); drp2.add(2); @@ -736,16 +802,18 @@ describe("Writer permission tests", () => { /* ROOT -- V1:ADD(1) -- V2:GRANT(peer2) -- V3:ADD(4) */ - const drp1 = obj1.drp as AddWinsSetWithACL; - const drp2 = obj2.drp as AddWinsSetWithACL; + const drp1 = obj1.drp as AddWinsSet; + const drp2 = obj2.drp as AddWinsSet; + const acl1 = obj1.acl as ACL; + const acl2 = obj2.acl as ACL; drp1.add(1); - drp1.acl.grant("peer1", "peer2", "publicKey2"); - expect(drp1.acl.isAdmin("peer1")).toBe(true); + acl1.grant("peer1", "peer2", "publicKey2"); + expect(acl1.isAdmin("peer1")).toBe(true); obj2.merge(obj1.hashGraph.getAllVertices()); expect(drp2.contains(1)).toBe(true); - expect(drp2.acl.isWriter("peer2")).toBe(true); + expect(acl2.isWriter("peer2")).toBe(true); drp2.add(4); obj1.merge(obj2.hashGraph.getAllVertices()); @@ -760,12 +828,13 @@ describe("Writer permission tests", () => { \ / -- V5:ADD(2) -- */ - const drp1 = obj1.drp as AddWinsSetWithACL; - const drp2 = obj2.drp as AddWinsSetWithACL; - const drp3 = obj3.drp as AddWinsSetWithACL; + const drp1 = obj1.drp as AddWinsSet; + const drp2 = obj2.drp as AddWinsSet; + const drp3 = obj3.drp as AddWinsSet; + const acl1 = obj1.acl as ACL; - drp1.acl.grant("peer1", "peer2", "publicKey2"); - drp1.acl.grant("peer1", "peer3", "publicKey3"); + acl1.grant("peer1", "peer2", "publicKey2"); + acl1.grant("peer1", "peer3", "publicKey3"); obj2.merge(obj1.hashGraph.getAllVertices()); obj3.merge(obj1.hashGraph.getAllVertices()); @@ -778,7 +847,7 @@ describe("Writer permission tests", () => { expect(drp1.contains(1)).toBe(true); expect(drp1.contains(2)).toBe(true); - drp1.acl.revoke("peer1", "peer3"); + acl1.revoke("peer1", "peer3"); obj3.merge(obj1.hashGraph.getAllVertices()); drp3.add(3); obj2.merge(obj3.hashGraph.getAllVertices()); From 43b83b96d8897675d6a6ee0929b0e1d2e113ee8e Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 12:09:03 +0700 Subject: [PATCH 05/35] remove acl --- packages/object/src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 0f9f6fc0..ef06167b 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -27,7 +27,6 @@ export interface DRP { operations: string[]; semanticsType: SemanticsType; resolveConflicts: (vertices: Vertex[]) => ResolveConflictsType; - acl?: IACL & DRP; // biome-ignore lint: attributes can be anything [key: string]: any; } From d574672605f75c0912fa667d658637f764c55fac Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 12:13:53 +0700 Subject: [PATCH 06/35] fix biome --- packages/node/src/handlers.ts | 13 +++++++++++-- packages/object/src/index.ts | 26 ++++--------------------- packages/object/tests/hashgraph.test.ts | 3 +-- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 4b29f858..6f2e032a 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -1,6 +1,13 @@ import type { Stream } from "@libp2p/interface"; import { NetworkPb, streamToUint8Array } from "@ts-drp/network"; -import { PrefixOperation, type DRP, type DRPObject, type IACL, type ObjectPb, type Vertex } from "@ts-drp/object"; +import { + PrefixOperation, + type DRP, + type DRPObject, + type IACL, + type ObjectPb, + type Vertex, +} from "@ts-drp/object"; import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; import { type DRPNode, log } from "./index.js"; @@ -230,7 +237,9 @@ export async function verifyIncomingVertices( incomingVertices: ObjectPb.Vertex[], ): Promise { const vertices: Vertex[] = incomingVertices.map((vertex) => { - const prefix = vertex.operation ? vertex.operation.prefix : PrefixOperation.drp; + const prefix = vertex.operation + ? vertex.operation.prefix + : PrefixOperation.drp; return { hash: vertex.hash, peerId: vertex.peerId, diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index ef06167b..15669020 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -368,12 +368,8 @@ export class DRPObject implements IDRPObject { } // get the map representing the state of the given DRP by mapping variable names to their corresponding values - private _getDRPState( - drp: DRP, - // biome-ignore lint: values can be anything - ): DRPState { + private _getDRPState(drp: DRP): DRPState { const varNames: string[] = Object.keys(drp); - // biome-ignore lint: values can be anything const drpState: DRPState = { state: new Map(), }; @@ -387,7 +383,6 @@ export class DRPObject implements IDRPObject { private _computeDRPState( vertexDependencies: Hash[], vertexOperation?: Operation, - // biome-ignore lint: values can be anything ): DRPState { const drp = this._computeDRP(vertexDependencies, vertexOperation); return this._getDRPState(drp); @@ -396,27 +391,18 @@ export class DRPObject implements IDRPObject { private _computeACLState( vertexDependencies: Hash[], vertexOperation?: Operation, - // biome-ignore lint: values can be anything ): DRPState { const drp = this._computeACL(vertexDependencies, vertexOperation); return this._getDRPState(drp); } // store the state of the DRP corresponding to the given vertex - private _setState( - vertex: Vertex, - // biome-ignore lint: values can be anything - drpState?: DRPState, - ) { + private _setState(vertex: Vertex, drpState?: DRPState) { this._setACLState(vertex, drpState); this._setDRPState(vertex, drpState); } - private _setACLState( - vertex: Vertex, - // biome-ignore lint: values can be anything - drpState?: DRPState, - ) { + private _setACLState(vertex: Vertex, drpState?: DRPState) { if (this.acl) { this.statesAcl.set( vertex.hash, @@ -426,11 +412,7 @@ export class DRPObject implements IDRPObject { } } - private _setDRPState( - vertex: Vertex, - // biome-ignore lint: values can be anything - drpState?: DRPState, - ) { + private _setDRPState(vertex: Vertex, drpState?: DRPState) { this.states.set( vertex.hash, drpState ?? this._computeDRPState(vertex.dependencies, vertex.operation), diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 1ff5f753..722cc24e 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -1,5 +1,4 @@ -import { AddWinsSetWithACL } from "@topology-foundation/blueprints/src/AddWinsSetWithACL/index.js"; -import { beforeEach, describe, expect, expectTypeOf, test } from "vitest"; +import { beforeEach, describe, expect, test } from "vitest"; import { AddWinsSet } from "../../blueprints/src/AddWinsSet/index.js"; import { DRPObject, type Operation, OperationType } from "../src/index.js"; import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; From 27702e1ed2456d2ed2fe71588c742bd4d695c1b9 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 12:23:23 +0700 Subject: [PATCH 07/35] fix biome --- packages/node/src/handlers.ts | 2 +- packages/object/tests/causallyrelated.bench.ts | 2 +- packages/object/tests/hashgraph.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 6f2e032a..18305f69 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -1,11 +1,11 @@ import type { Stream } from "@libp2p/interface"; import { NetworkPb, streamToUint8Array } from "@ts-drp/network"; import { - PrefixOperation, type DRP, type DRPObject, type IACL, type ObjectPb, + PrefixOperation, type Vertex, } from "@ts-drp/object"; import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; diff --git a/packages/object/tests/causallyrelated.bench.ts b/packages/object/tests/causallyrelated.bench.ts index 51097358..a4c2d157 100644 --- a/packages/object/tests/causallyrelated.bench.ts +++ b/packages/object/tests/causallyrelated.bench.ts @@ -1,7 +1,7 @@ +import type { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; import { bench, describe } from "vitest"; import { AddWinsSet } from "../../blueprints/src/AddWinsSet/index.js"; import { DRPObject, type Hash } from "../src/index.js"; -import type { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; describe("AreCausallyDependent benchmark", async () => { const samples = 100000; diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 722cc24e..6d49ae95 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -1,7 +1,7 @@ +import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; import { beforeEach, describe, expect, test } from "vitest"; import { AddWinsSet } from "../../blueprints/src/AddWinsSet/index.js"; import { DRPObject, type Operation, OperationType } from "../src/index.js"; -import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; describe("HashGraph construction tests", () => { let obj1: DRPObject; From 7e4be0b53d2346ba9ef5fac29879ed1a7eea9a69 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 13:14:29 +0700 Subject: [PATCH 08/35] fix: root vertex prefix --- packages/object/src/hashgraph/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index 12a45cef..f5542ed0 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -1,5 +1,5 @@ import * as crypto from "node:crypto"; -import { log } from "../index.js"; +import { log, PrefixOperation } from "../index.js"; import { linearizeMultipleSemantics } from "../linearize/multipleSemantics.js"; import { linearizePairSemantics } from "../linearize/pairSemantics.js"; import type { @@ -82,6 +82,7 @@ export class HashGraph { operation: { type: OperationType.NOP, value: null, + prefix: PrefixOperation.drp, }, dependencies: [], timestamp: -1, From 185f746ed93e22f217710e35207add135c48fb05 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Tue, 7 Jan 2025 13:18:59 +0700 Subject: [PATCH 09/35] fix: acl is null --- packages/node/src/index.ts | 10 ++++++++-- packages/object/src/hashgraph/index.ts | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 51b51604..8a508756 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -6,7 +6,7 @@ import { type DRPNetworkNodeConfig, NetworkPb, } from "@ts-drp/network"; -import { type DRP, DRPObject, type Vertex } from "@ts-drp/object"; +import { type DRP, DRPObject, type IACL, type Vertex } from "@ts-drp/object"; import { drpMessagesHandler } from "./handlers.js"; import * as operations from "./operations.js"; import { DRPObjectStore } from "./store/index.js"; @@ -78,7 +78,13 @@ export class DRPNode { sync?: boolean, peerId?: string, ) { - const object = new DRPObject(this.networkNode.peerId, drp, null, id, abi); + const object = new DRPObject( + this.networkNode.peerId, + drp, + null as unknown as IACL & DRP, + id, + abi, + ); operations.createObject(this, object); operations.subscribeObject(this, object.id); if (sync) { diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index f5542ed0..aa921359 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -1,5 +1,5 @@ import * as crypto from "node:crypto"; -import { log, PrefixOperation } from "../index.js"; +import { PrefixOperation, log } from "../index.js"; import { linearizeMultipleSemantics } from "../linearize/multipleSemantics.js"; import { linearizePairSemantics } from "../linearize/pairSemantics.js"; import type { From 17756238aa670136a58a86548e629c710872ee13 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 01:40:48 +0700 Subject: [PATCH 10/35] feat: resolve comment --- packages/node/src/handlers.ts | 3 --- packages/node/tests/node.test.ts | 3 +++ packages/object/src/index.ts | 9 --------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 18305f69..ce4086eb 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -255,9 +255,6 @@ export async function verifyIncomingVertices( }); const drp = object.drp as DRP; - // if (!drp.acl) { - // return vertices; - // } const acl: IACL & DRP = object.acl as IACL & DRP; if (!acl) { return vertices; diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index bbbf1b95..dae97491 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -7,6 +7,8 @@ import { verifyIncomingVertices, } from "../src/handlers.js"; import { DRPNode, type DRPNodeConfig } from "../src/index.js"; +import { prefix } from 'loglevel-plugin-prefix'; +import { PrefixOperation } from "@topology-foundation/object/src/index.js"; describe("DPRNode with verify and sign signature", () => { let drp: DRP; @@ -107,6 +109,7 @@ describe("DPRNode with verify and sign signature", () => { operation: { type: "add", value: 1, + prefix: PrefixOperation.drp }, dependencies: [], signature: "", diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 15669020..0746550e 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -159,15 +159,6 @@ export class DRPObject implements IDRPObject { }); } - if (typeof value === "object" && value !== null && propKey === "acl") { - return new Proxy( - value, - obj.proxyDRPHandler( - parentProp ? `${parentProp}.${String(propKey)}` : String(propKey), - ), - ); - } - return value; }, }; From 2ef967077f3d5b8a7e473ae329f8c04e8b3d507d Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 01:45:24 +0700 Subject: [PATCH 11/35] feat: update prefix in root vertex --- packages/object/src/hashgraph/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index aa921359..bd78c338 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -82,7 +82,7 @@ export class HashGraph { operation: { type: OperationType.NOP, value: null, - prefix: PrefixOperation.drp, + prefix: "", }, dependencies: [], timestamp: -1, From c325ac8120fc34867997c4a6469e3d8c7c7432d8 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 01:50:54 +0700 Subject: [PATCH 12/35] feat: fix biome --- packages/node/tests/node.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index dae97491..581c980c 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -1,5 +1,6 @@ import { AddWinsSetWithACL } from "@topology-foundation/blueprints/src/AddWinsSetWithACL/index.js"; import { AddWinsSet } from "@topology-foundation/blueprints/src/index.js"; +import { PrefixOperation } from "@topology-foundation/object/src/index.js"; import { type DRP, DRPObject } from "@ts-drp/object"; import { beforeAll, beforeEach, describe, expect, test } from "vitest"; import { @@ -7,8 +8,6 @@ import { verifyIncomingVertices, } from "../src/handlers.js"; import { DRPNode, type DRPNodeConfig } from "../src/index.js"; -import { prefix } from 'loglevel-plugin-prefix'; -import { PrefixOperation } from "@topology-foundation/object/src/index.js"; describe("DPRNode with verify and sign signature", () => { let drp: DRP; @@ -109,7 +108,7 @@ describe("DPRNode with verify and sign signature", () => { operation: { type: "add", value: 1, - prefix: PrefixOperation.drp + prefix: PrefixOperation.drp, }, dependencies: [], signature: "", From 4abc1e8a1a86168f5ab5227d49abd5308fcd1c0b Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 02:08:55 +0700 Subject: [PATCH 13/35] feat: fix testcase node --- packages/node/tests/node.test.ts | 11 +++++++---- packages/object/src/helper.ts | 11 +++++++++++ packages/object/src/index.ts | 11 +---------- 3 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 packages/object/src/helper.ts diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index 581c980c..6f13dd9a 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -1,4 +1,4 @@ -import { AddWinsSetWithACL } from "@topology-foundation/blueprints/src/AddWinsSetWithACL/index.js"; +import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; import { AddWinsSet } from "@topology-foundation/blueprints/src/index.js"; import { PrefixOperation } from "@topology-foundation/object/src/index.js"; import { type DRP, DRPObject } from "@ts-drp/object"; @@ -20,12 +20,14 @@ describe("DPRNode with verify and sign signature", () => { }); beforeEach(async () => { - drp = new AddWinsSetWithACL( + drp = new AddWinsSet(); + const acl = new ACL( new Map([ [drpNode.networkNode.peerId, drpNode.networkNode.publicKey || ""], ]), ); - drpObject = new DRPObject(drpNode.networkNode.peerId, drp); + drpObject = new DRPObject(drpNode.networkNode.peerId, drp, acl); + console.log(drpObject.acl); }); test("Node will not sign vertex if it is not the creator", async () => { @@ -114,7 +116,8 @@ describe("DPRNode with verify and sign signature", () => { signature: "", }, ]; + console.log(drpObject.acl); const verifiedVertices = await verifyIncomingVertices(drpObject, vertices); - expect(verifiedVertices.length).toBe(1); + expect(verifiedVertices.length).toBe(0); }); }); diff --git a/packages/object/src/helper.ts b/packages/object/src/helper.ts new file mode 100644 index 00000000..752cf7d8 --- /dev/null +++ b/packages/object/src/helper.ts @@ -0,0 +1,11 @@ +import type { IACL } from "./index.js"; + +export const isACLInterface = (target: object): boolean => { + return ( + typeof (target as IACL).isWriter === "function" && + typeof (target as IACL).isAdmin === "function" && + typeof (target as IACL).grant === "function" && + typeof (target as IACL).revoke === "function" && + typeof (target as IACL).getPeerKey === "function" + ); +}; diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 0746550e..c47aa5c6 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -14,6 +14,7 @@ import { ObjectSet } from "./utils/objectSet.js"; export * as ObjectPb from "./proto/drp/object/v1/object_pb.js"; export * from "./hashgraph/index.js"; import { cloneDeep } from "es-toolkit"; +import { isACLInterface } from "./helper.js"; export interface IACL { isWriter: (peerId: string) => boolean; @@ -60,16 +61,6 @@ export enum PrefixOperation { drp = "drp", } -export const isACLInterface = (target: object): boolean => { - return ( - typeof (target as IACL).isWriter === "function" && - typeof (target as IACL).isAdmin === "function" && - typeof (target as IACL).grant === "function" && - typeof (target as IACL).revoke === "function" && - typeof (target as IACL).getPeerKey === "function" - ); -}; - export class DRPObject implements IDRPObject { peerId: string; id: string; From 3c6bc220de0f9afb7389c0628634309e9b775ce5 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 02:11:44 +0700 Subject: [PATCH 14/35] remove console --- packages/node/tests/node.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index 6f13dd9a..cef32af8 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -27,7 +27,6 @@ describe("DPRNode with verify and sign signature", () => { ]), ); drpObject = new DRPObject(drpNode.networkNode.peerId, drp, acl); - console.log(drpObject.acl); }); test("Node will not sign vertex if it is not the creator", async () => { @@ -116,7 +115,6 @@ describe("DPRNode with verify and sign signature", () => { signature: "", }, ]; - console.log(drpObject.acl); const verifiedVertices = await verifyIncomingVertices(drpObject, vertices); expect(verifiedVertices.length).toBe(0); }); From 8a0edb3ef650e3e770d98af630cabfcf66e55b88 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 18:05:46 +0700 Subject: [PATCH 15/35] feat: rename prefix to vertex type --- .../proto/drp/network/v1/messages_grpc_pb.js | 1 + .../src/proto/drp/network/v1/messages_pb.ts | 2 +- .../src/proto/drp/object/v1/object_pb.ts | 18 ++--- .../src/proto/google/protobuf/struct_pb.ts | 2 +- packages/node/src/handlers.ts | 8 +- packages/node/tests/node.test.ts | 4 +- packages/object/src/hashgraph/index.ts | 4 +- packages/object/src/index.ts | 24 +++--- .../src/proto/drp/object/v1/object.proto | 2 +- .../src/proto/drp/object/v1/object_pb.ts | 18 ++--- packages/object/tests/hashgraph.test.ts | 80 ++++++++++--------- 11 files changed, 81 insertions(+), 82 deletions(-) create mode 100644 packages/network/src/proto/drp/network/v1/messages_grpc_pb.js diff --git a/packages/network/src/proto/drp/network/v1/messages_grpc_pb.js b/packages/network/src/proto/drp/network/v1/messages_grpc_pb.js new file mode 100644 index 00000000..97b3a246 --- /dev/null +++ b/packages/network/src/proto/drp/network/v1/messages_grpc_pb.js @@ -0,0 +1 @@ +// GENERATED CODE -- NO SERVICES IN PROTO \ No newline at end of file diff --git a/packages/network/src/proto/drp/network/v1/messages_pb.ts b/packages/network/src/proto/drp/network/v1/messages_pb.ts index f3e23db2..3cebd92c 100644 --- a/packages/network/src/proto/drp/network/v1/messages_pb.ts +++ b/packages/network/src/proto/drp/network/v1/messages_pb.ts @@ -1,6 +1,6 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: -// protoc-gen-ts_proto v2.5.0 +// protoc-gen-ts_proto v2.6.0 // protoc unknown // source: drp/network/v1/messages.proto diff --git a/packages/network/src/proto/drp/object/v1/object_pb.ts b/packages/network/src/proto/drp/object/v1/object_pb.ts index 4b19805c..4e907eb2 100644 --- a/packages/network/src/proto/drp/object/v1/object_pb.ts +++ b/packages/network/src/proto/drp/object/v1/object_pb.ts @@ -23,7 +23,7 @@ export interface Vertex { export interface Vertex_Operation { type: string; value: any | undefined; - prefix: string; + vertexType: string; } export interface DRPObjectBase { @@ -178,7 +178,7 @@ export const Vertex: MessageFns = { }; function createBaseVertex_Operation(): Vertex_Operation { - return { type: "", value: undefined, prefix: "" }; + return { type: "", value: undefined, vertexType: "" }; } export const Vertex_Operation: MessageFns = { @@ -189,8 +189,8 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).join(); } - if (message.prefix !== "") { - writer.uint32(26).string(message.prefix); + if (message.vertexType !== "") { + writer.uint32(26).string(message.vertexType); } return writer; }, @@ -223,7 +223,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.prefix = reader.string(); + message.vertexType = reader.string(); continue; } } @@ -239,7 +239,7 @@ export const Vertex_Operation: MessageFns = { return { type: isSet(object.type) ? globalThis.String(object.type) : "", value: isSet(object?.value) ? object.value : undefined, - prefix: isSet(object.prefix) ? globalThis.String(object.prefix) : "", + vertexType: isSet(object.vertexType) ? globalThis.String(object.vertexType) : "", }; }, @@ -251,8 +251,8 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { obj.value = message.value; } - if (message.prefix !== "") { - obj.prefix = message.prefix; + if (message.vertexType !== "") { + obj.vertexType = message.vertexType; } return obj; }, @@ -264,7 +264,7 @@ export const Vertex_Operation: MessageFns = { const message = createBaseVertex_Operation(); message.type = object.type ?? ""; message.value = object.value ?? undefined; - message.prefix = object.prefix ?? ""; + message.vertexType = object.vertexType ?? ""; return message; }, }; diff --git a/packages/network/src/proto/google/protobuf/struct_pb.ts b/packages/network/src/proto/google/protobuf/struct_pb.ts index b0b633ad..2789c990 100644 --- a/packages/network/src/proto/google/protobuf/struct_pb.ts +++ b/packages/network/src/proto/google/protobuf/struct_pb.ts @@ -1,6 +1,6 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: -// protoc-gen-ts_proto v2.5.0 +// protoc-gen-ts_proto v2.6.0 // protoc unknown // source: google/protobuf/struct.proto diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index ce4086eb..9af67004 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -5,7 +5,7 @@ import { type DRPObject, type IACL, type ObjectPb, - PrefixOperation, + VertexTypeOperation, type Vertex, } from "@ts-drp/object"; import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; @@ -237,16 +237,14 @@ export async function verifyIncomingVertices( incomingVertices: ObjectPb.Vertex[], ): Promise { const vertices: Vertex[] = incomingVertices.map((vertex) => { - const prefix = vertex.operation - ? vertex.operation.prefix - : PrefixOperation.drp; + const vertexType = vertex.operation ? vertex.operation.vertexType : ""; return { hash: vertex.hash, peerId: vertex.peerId, operation: { type: vertex.operation?.type ?? "", value: vertex.operation?.value, - prefix, + vertexType: vertexType, }, dependencies: vertex.dependencies, timestamp: vertex.timestamp, diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index cef32af8..d6bc4b18 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -1,6 +1,6 @@ import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; import { AddWinsSet } from "@topology-foundation/blueprints/src/index.js"; -import { PrefixOperation } from "@topology-foundation/object/src/index.js"; +import { VertexTypeOperation } from "@topology-foundation/object/src/index.js"; import { type DRP, DRPObject } from "@ts-drp/object"; import { beforeAll, beforeEach, describe, expect, test } from "vitest"; import { @@ -109,7 +109,7 @@ describe("DPRNode with verify and sign signature", () => { operation: { type: "add", value: 1, - prefix: PrefixOperation.drp, + vertexType: VertexTypeOperation.drp, }, dependencies: [], signature: "", diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index bd78c338..91b6bdf1 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -1,5 +1,5 @@ import * as crypto from "node:crypto"; -import { PrefixOperation, log } from "../index.js"; +import { VertexTypeOperation, log } from "../index.js"; import { linearizeMultipleSemantics } from "../linearize/multipleSemantics.js"; import { linearizePairSemantics } from "../linearize/pairSemantics.js"; import type { @@ -82,7 +82,7 @@ export class HashGraph { operation: { type: OperationType.NOP, value: null, - prefix: "", + vertexType: "", }, dependencies: [], timestamp: -1, diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index c47aa5c6..babca847 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -56,7 +56,7 @@ export interface DRPObjectConfig { export let log: Logger; -export enum PrefixOperation { +export enum VertexTypeOperation { acl = "acl", drp = "drp", } @@ -128,9 +128,9 @@ export class DRPObject implements IDRPObject { return { get(target, propKey, receiver) { const value = Reflect.get(target, propKey, receiver); - let prefix = PrefixOperation.drp; + let prefix = VertexTypeOperation.drp; if (isACLInterface(target)) { - prefix = PrefixOperation.acl; + prefix = VertexTypeOperation.acl; } if (typeof value === "function") { @@ -156,11 +156,11 @@ export class DRPObject implements IDRPObject { } // biome-ignore lint: value can't be unknown because of protobuf - callFn(fn: string, args: any, prefix: PrefixOperation = PrefixOperation.drp) { + callFn(fn: string, args: any, vertexType: VertexTypeOperation = VertexTypeOperation.drp) { const vertex = this.hashGraph.addToFrontier({ type: fn, value: args, - prefix: prefix, + vertexType: vertexType, }); this._setState(vertex); @@ -181,7 +181,6 @@ export class DRPObject implements IDRPObject { */ merge(vertices: Vertex[]): [merged: boolean, missing: string[]] { const missing = []; - let needUpdateACLState = false; for (const vertex of vertices) { // Check to avoid manually crafted `undefined` operations if (!vertex.operation || this.hashGraph.vertices.has(vertex.hash)) { @@ -190,13 +189,12 @@ export class DRPObject implements IDRPObject { try { const drp = - vertex.operation.prefix === PrefixOperation.acl + vertex.operation.vertexType === VertexTypeOperation.acl ? this._computeACL(vertex.dependencies) : this._computeDRP(vertex.dependencies); if (!this._checkWriterPermission(vertex.peerId)) { throw new Error(`${vertex.peerId} does not have write permission.`); } - needUpdateACLState = vertex.operation.prefix === PrefixOperation.acl; this.hashGraph.addVertex( vertex.operation, @@ -207,7 +205,7 @@ export class DRPObject implements IDRPObject { ); this._applyOperation(drp, vertex.operation); - if (vertex.operation.prefix === PrefixOperation.acl) { + if (vertex.operation.vertexType === VertexTypeOperation.acl) { this._setACLState(vertex, this._getDRPState(drp)); this._setDRPState(vertex); } else { @@ -299,10 +297,10 @@ export class DRPObject implements IDRPObject { } for (const op of linearizedOperations) { - op.prefix === PrefixOperation.drp && this._applyOperation(drp, op); + op.vertexType === VertexTypeOperation.drp && this._applyOperation(drp, op); } if (vertexOperation) { - vertexOperation.prefix === PrefixOperation.drp && + vertexOperation.vertexType === VertexTypeOperation.drp && this._applyOperation(drp, vertexOperation); } @@ -339,10 +337,10 @@ export class DRPObject implements IDRPObject { acl[key] = value; } for (const op of linearizedOperations) { - op.prefix === PrefixOperation.acl && this._applyOperation(acl, op); + op.vertexType === VertexTypeOperation.acl && this._applyOperation(acl, op); } if (vertexOperation) { - vertexOperation.prefix === PrefixOperation.acl && + vertexOperation.vertexType === VertexTypeOperation.acl && this._applyOperation(acl, vertexOperation); } diff --git a/packages/object/src/proto/drp/object/v1/object.proto b/packages/object/src/proto/drp/object/v1/object.proto index 59e510d9..97842bc1 100644 --- a/packages/object/src/proto/drp/object/v1/object.proto +++ b/packages/object/src/proto/drp/object/v1/object.proto @@ -9,7 +9,7 @@ message Vertex { message Operation { string type = 1; google.protobuf.Value value = 2; - string prefix = 3; + string vertex_type = 3; } string hash = 1; string peer_id = 2; diff --git a/packages/object/src/proto/drp/object/v1/object_pb.ts b/packages/object/src/proto/drp/object/v1/object_pb.ts index 4b19805c..4e907eb2 100644 --- a/packages/object/src/proto/drp/object/v1/object_pb.ts +++ b/packages/object/src/proto/drp/object/v1/object_pb.ts @@ -23,7 +23,7 @@ export interface Vertex { export interface Vertex_Operation { type: string; value: any | undefined; - prefix: string; + vertexType: string; } export interface DRPObjectBase { @@ -178,7 +178,7 @@ export const Vertex: MessageFns = { }; function createBaseVertex_Operation(): Vertex_Operation { - return { type: "", value: undefined, prefix: "" }; + return { type: "", value: undefined, vertexType: "" }; } export const Vertex_Operation: MessageFns = { @@ -189,8 +189,8 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).join(); } - if (message.prefix !== "") { - writer.uint32(26).string(message.prefix); + if (message.vertexType !== "") { + writer.uint32(26).string(message.vertexType); } return writer; }, @@ -223,7 +223,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.prefix = reader.string(); + message.vertexType = reader.string(); continue; } } @@ -239,7 +239,7 @@ export const Vertex_Operation: MessageFns = { return { type: isSet(object.type) ? globalThis.String(object.type) : "", value: isSet(object?.value) ? object.value : undefined, - prefix: isSet(object.prefix) ? globalThis.String(object.prefix) : "", + vertexType: isSet(object.vertexType) ? globalThis.String(object.vertexType) : "", }; }, @@ -251,8 +251,8 @@ export const Vertex_Operation: MessageFns = { if (message.value !== undefined) { obj.value = message.value; } - if (message.prefix !== "") { - obj.prefix = message.prefix; + if (message.vertexType !== "") { + obj.vertexType = message.vertexType; } return obj; }, @@ -264,7 +264,7 @@ export const Vertex_Operation: MessageFns = { const message = createBaseVertex_Operation(); message.type = object.type ?? ""; message.value = object.value ?? undefined; - message.prefix = object.prefix ?? ""; + message.vertexType = object.vertexType ?? ""; return message; }, }; diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 6d49ae95..5f17c44a 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -51,8 +51,8 @@ describe("HashGraph construction tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { type: "add", value: 2, prefix: "drp" }, - { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 2, vertexType: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, ] as Operation[]); }); @@ -68,7 +68,7 @@ describe("HashGraph construction tests", () => { { type: "root", value: null, - prefix: "drp", + vertexType: "drp", }, [], "", @@ -79,7 +79,7 @@ describe("HashGraph construction tests", () => { { type: "add", value: 1, - prefix: "drp", + vertexType: "drp", }, [hash], "", @@ -89,7 +89,9 @@ describe("HashGraph construction tests", () => { expect(obj1.hashGraph.selfCheckConstraints()).toBe(false); const linearOps = obj1.hashGraph.linearizeOperations(); - const expectedOps: Operation[] = [{ type: "add", value: 1, prefix: "drp" }]; + const expectedOps: Operation[] = [ + { type: "add", value: 1, vertexType: "drp" }, + ]; expect(linearOps).toEqual(expectedOps); }); }); @@ -132,9 +134,9 @@ describe("HashGraph for AddWinSet tests", () => { { type: "add", value: 1, - prefix: "drp", + vertexType: "drp", }, - { type: "remove", value: 1, prefix: "drp" }, + { type: "remove", value: 1, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -162,8 +164,8 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, prefix: "drp" }, - { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -192,9 +194,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, prefix: "drp" }, - { type: "remove", value: 1, prefix: "drp" }, - { type: "add", value: 2, prefix: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "remove", value: 1, vertexType: "drp" }, + { type: "add", value: 2, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -226,10 +228,10 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, prefix: "drp" }, - { type: "add", value: 1, prefix: "drp" }, - { type: "add", value: 10, prefix: "drp" }, - { type: "remove", value: 5, prefix: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "add", value: 10, vertexType: "drp" }, + { type: "remove", value: 5, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -260,9 +262,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, prefix: "drp" }, - { type: "add", value: 2, prefix: "drp" }, - { type: "add", value: 1, prefix: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "add", value: 2, vertexType: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -314,12 +316,12 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, prefix: "drp" }, - { type: "add", value: 1, prefix: "drp" }, - { type: "remove", value: 2, prefix: "drp" }, - { type: "add", value: 2, prefix: "drp" }, - { type: "remove", value: 1, prefix: "drp" }, - { type: "add", value: 3, prefix: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "remove", value: 2, vertexType: "drp" }, + { type: "add", value: 2, vertexType: "drp" }, + { type: "remove", value: 1, vertexType: "drp" }, + { type: "add", value: 3, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -371,14 +373,14 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { type: "add", value: 1, prefix: "drp" }, - { type: "add", value: 1, prefix: "drp" }, - { type: "remove", value: 2, prefix: "drp" }, - { type: "remove", value: 2, prefix: "drp" }, - { type: "remove", value: 1, prefix: "drp" }, - { type: "add", value: 3, prefix: "drp" }, - { type: "add", value: 2, prefix: "drp" }, - { type: "remove", value: 1, prefix: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "remove", value: 2, vertexType: "drp" }, + { type: "remove", value: 2, vertexType: "drp" }, + { type: "remove", value: 1, vertexType: "drp" }, + { type: "add", value: 3, vertexType: "drp" }, + { type: "add", value: 2, vertexType: "drp" }, + { type: "remove", value: 1, vertexType: "drp" }, ]); }); @@ -410,9 +412,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, prefix: "drp" }, - { type: "add", value: 2, prefix: "drp" }, - { type: "remove", value: 2, prefix: "drp" }, + { type: "add", value: 1, vertexType: "drp" }, + { type: "add", value: 2, vertexType: "drp" }, + { type: "remove", value: 2, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -449,7 +451,7 @@ describe("HashGraph for undefined operations tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); // Should only have one, since we skipped the undefined operations - expect(linearOps).toEqual([{ type: "add", value: 2, prefix: "drp" }]); + expect(linearOps).toEqual([{ type: "add", value: 2, vertexType: "drp" }]); }); test("Test: addToFrontier with undefined operation return Vertex with NoOp operation", () => { @@ -650,7 +652,7 @@ describe("Vertex timestamp tests", () => { { type: "add", value: 1, - prefix: "drp", + vertexType: "drp", }, obj1.hashGraph.getFrontier(), "", @@ -685,7 +687,7 @@ describe("Vertex timestamp tests", () => { { type: "add", value: 1, - prefix: "drp", + vertexType: "drp", }, obj1.hashGraph.getFrontier(), "", From 68c5c99bf18ff55f47865a413827f9685f4a617a Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 18:44:51 +0700 Subject: [PATCH 16/35] feat: improve some performance --- packages/node/src/handlers.ts | 9 +-------- packages/object/src/helper.ts | 11 ----------- packages/object/src/index.ts | 34 +++++++++++++++++++++------------- 3 files changed, 22 insertions(+), 32 deletions(-) delete mode 100644 packages/object/src/helper.ts diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 9af67004..1f3c1c63 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -1,13 +1,6 @@ import type { Stream } from "@libp2p/interface"; import { NetworkPb, streamToUint8Array } from "@ts-drp/network"; -import { - type DRP, - type DRPObject, - type IACL, - type ObjectPb, - VertexTypeOperation, - type Vertex, -} from "@ts-drp/object"; +import type { DRP, DRPObject, IACL, ObjectPb, Vertex } from "@ts-drp/object"; import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; import { type DRPNode, log } from "./index.js"; diff --git a/packages/object/src/helper.ts b/packages/object/src/helper.ts deleted file mode 100644 index 752cf7d8..00000000 --- a/packages/object/src/helper.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { IACL } from "./index.js"; - -export const isACLInterface = (target: object): boolean => { - return ( - typeof (target as IACL).isWriter === "function" && - typeof (target as IACL).isAdmin === "function" && - typeof (target as IACL).grant === "function" && - typeof (target as IACL).revoke === "function" && - typeof (target as IACL).getPeerKey === "function" - ); -}; diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index babca847..81067fa0 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -14,7 +14,6 @@ import { ObjectSet } from "./utils/objectSet.js"; export * as ObjectPb from "./proto/drp/object/v1/object_pb.js"; export * from "./hashgraph/index.js"; import { cloneDeep } from "es-toolkit"; -import { isACLInterface } from "./helper.js"; export interface IACL { isWriter: (peerId: string) => boolean; @@ -98,8 +97,12 @@ export class DRPObject implements IDRPObject { this.abi = abi ?? ""; this.bytecode = new Uint8Array(); this.vertices = []; - this.drp = drp ? new Proxy(drp, this.proxyDRPHandler()) : null; - this.acl = acl ? new Proxy(acl, this.proxyDRPHandler()) : null; + this.drp = drp + ? new Proxy(drp, this.proxyDRPHandler(VertexTypeOperation.drp)) + : null; + this.acl = acl + ? new Proxy(acl, this.proxyDRPHandler(VertexTypeOperation.acl)) + : null; this.hashGraph = new HashGraph( peerId, this.resolveConflicts.bind(this), @@ -123,15 +126,14 @@ export class DRPObject implements IDRPObject { } // This function is black magic, it allows us to intercept calls to the DRP object - proxyDRPHandler(parentProp?: string): ProxyHandler { + proxyDRPHandler( + vertexType: VertexTypeOperation, + parentProp?: string, + ): ProxyHandler { const obj = this; return { get(target, propKey, receiver) { const value = Reflect.get(target, propKey, receiver); - let prefix = VertexTypeOperation.drp; - if (isACLInterface(target)) { - prefix = VertexTypeOperation.acl; - } if (typeof value === "function") { const fullPropKey = parentProp @@ -143,7 +145,7 @@ export class DRPObject implements IDRPObject { obj.callFn( fullPropKey, args.length === 1 ? args[0] : args, - prefix, + vertexType, ); return Reflect.apply(applyTarget, thisArg, args); }, @@ -155,8 +157,12 @@ export class DRPObject implements IDRPObject { }; } - // biome-ignore lint: value can't be unknown because of protobuf - callFn(fn: string, args: any, vertexType: VertexTypeOperation = VertexTypeOperation.drp) { + callFn( + fn: string, + // biome-ignore lint: value can't be unknown because of protobuf + args: any, + vertexType: VertexTypeOperation = VertexTypeOperation.drp, + ) { const vertex = this.hashGraph.addToFrontier({ type: fn, value: args, @@ -297,7 +303,8 @@ export class DRPObject implements IDRPObject { } for (const op of linearizedOperations) { - op.vertexType === VertexTypeOperation.drp && this._applyOperation(drp, op); + op.vertexType === VertexTypeOperation.drp && + this._applyOperation(drp, op); } if (vertexOperation) { vertexOperation.vertexType === VertexTypeOperation.drp && @@ -337,7 +344,8 @@ export class DRPObject implements IDRPObject { acl[key] = value; } for (const op of linearizedOperations) { - op.vertexType === VertexTypeOperation.acl && this._applyOperation(acl, op); + op.vertexType === VertexTypeOperation.acl && + this._applyOperation(acl, op); } if (vertexOperation) { vertexOperation.vertexType === VertexTypeOperation.acl && From cd21213d3fefff25816e5578077668f982d9e596 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 20:17:35 +0700 Subject: [PATCH 17/35] resolve comment --- packages/node/src/handlers.ts | 3 +-- packages/object/src/hashgraph/index.ts | 2 +- packages/object/src/index.ts | 9 ++------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 1f3c1c63..d91aefca 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -230,14 +230,13 @@ export async function verifyIncomingVertices( incomingVertices: ObjectPb.Vertex[], ): Promise { const vertices: Vertex[] = incomingVertices.map((vertex) => { - const vertexType = vertex.operation ? vertex.operation.vertexType : ""; return { hash: vertex.hash, peerId: vertex.peerId, operation: { type: vertex.operation?.type ?? "", value: vertex.operation?.value, - vertexType: vertexType, + vertexType: vertex.operation?.vertexType ?? "", }, dependencies: vertex.dependencies, timestamp: vertex.timestamp, diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index 91b6bdf1..1d4e102d 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -1,5 +1,5 @@ import * as crypto from "node:crypto"; -import { VertexTypeOperation, log } from "../index.js"; +import { log } from "../index.js"; import { linearizeMultipleSemantics } from "../linearize/multipleSemantics.js"; import { linearizePairSemantics } from "../linearize/pairSemantics.js"; import type { diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 81067fa0..6228f5e3 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -126,19 +126,14 @@ export class DRPObject implements IDRPObject { } // This function is black magic, it allows us to intercept calls to the DRP object - proxyDRPHandler( - vertexType: VertexTypeOperation, - parentProp?: string, - ): ProxyHandler { + proxyDRPHandler(vertexType: VertexTypeOperation): ProxyHandler { const obj = this; return { get(target, propKey, receiver) { const value = Reflect.get(target, propKey, receiver); if (typeof value === "function") { - const fullPropKey = parentProp - ? `${parentProp}.${String(propKey)}` - : String(propKey); + const fullPropKey = String(propKey); return new Proxy(target[propKey as keyof object], { apply(applyTarget, thisArg, args) { if ((thisArg.operations as string[]).includes(propKey as string)) From ee5e1a29dc02b5fa1af37d1c5d101fa0b42144b8 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 20:19:31 +0700 Subject: [PATCH 18/35] feat: pre compute LCA first --- packages/object/src/index.ts | 116 +++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 40 deletions(-) diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 6228f5e3..706910e3 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -53,6 +53,11 @@ export interface DRPObjectConfig { log_config?: LoggerOptions; } +export interface LcaAndOperations { + lca: string; + linearizedOperations: Operation[]; +} + export let log: Logger; export enum VertexTypeOperation { @@ -117,9 +122,13 @@ export class DRPObject implements IDRPObject { } resolveConflicts(vertices: Vertex[]): ResolveConflictsType { - if (this.acl) { + if ( + this.acl && + vertices.some((v) => v.operation?.vertexType === VertexTypeOperation.acl) + ) { const acl = this.acl as IACL & DRP; - acl.resolveConflicts(vertices); + + return acl.resolveConflicts(vertices); } const drp = this.drp as DRP; return drp.resolveConflicts(vertices); @@ -189,10 +198,11 @@ export class DRPObject implements IDRPObject { } try { + const preComputeLca = this.computeLCA(vertex.dependencies); const drp = vertex.operation.vertexType === VertexTypeOperation.acl - ? this._computeACL(vertex.dependencies) - : this._computeDRP(vertex.dependencies); + ? this._computeACL(vertex.dependencies, preComputeLca) + : this._computeDRP(vertex.dependencies, preComputeLca); if (!this._checkWriterPermission(vertex.peerId)) { throw new Error(`${vertex.peerId} does not have write permission.`); } @@ -207,11 +217,11 @@ export class DRPObject implements IDRPObject { this._applyOperation(drp, vertex.operation); if (vertex.operation.vertexType === VertexTypeOperation.acl) { - this._setACLState(vertex, this._getDRPState(drp)); - this._setDRPState(vertex); + this._setACLState(vertex, preComputeLca, this._getDRPState(drp)); + this._setDRPState(vertex, preComputeLca); } else { - this._setACLState(vertex); - this._setDRPState(vertex, this._getDRPState(drp)); + this._setACLState(vertex, preComputeLca); + this._setDRPState(vertex, preComputeLca, this._getDRPState(drp)); } } catch (e) { missing.push(vertex.hash); @@ -269,20 +279,11 @@ export class DRPObject implements IDRPObject { // compute the DRP based on all dependencies of the current vertex using partial linearization private _computeDRP( vertexDependencies: Hash[], + preCompute?: LcaAndOperations, vertexOperation?: Operation, ): DRP { - const subgraph: ObjectSet = new ObjectSet(); - const lca = - vertexDependencies.length === 1 - ? vertexDependencies[0] - : this.hashGraph.lowestCommonAncestorMultipleVertices( - vertexDependencies, - subgraph, - ); - const linearizedOperations = - vertexDependencies.length === 1 - ? [] - : this.hashGraph.linearizeOperations(lca, subgraph); + const { lca, linearizedOperations } = + preCompute ?? this.computeLCA(vertexDependencies); const drp = cloneDeep(this.originalDRP); @@ -311,20 +312,11 @@ export class DRPObject implements IDRPObject { private _computeACL( vertexDependencies: Hash[], + preCompute?: LcaAndOperations, vertexOperation?: Operation, ): DRP { - const subgraph: ObjectSet = new ObjectSet(); - const lca = - vertexDependencies.length === 1 - ? vertexDependencies[0] - : this.hashGraph.lowestCommonAncestorMultipleVertices( - vertexDependencies, - subgraph, - ); - const linearizedOperations = - vertexDependencies.length === 1 - ? [] - : this.hashGraph.linearizeOperations(lca, subgraph); + const { lca, linearizedOperations } = + preCompute ?? this.computeLCA(vertexDependencies); const acl = cloneDeep(this.originalACL); @@ -350,6 +342,22 @@ export class DRPObject implements IDRPObject { return acl; } + private computeLCA(vertexDependencies: string[]) { + const subgraph: ObjectSet = new ObjectSet(); + const lca = + vertexDependencies.length === 1 + ? vertexDependencies[0] + : this.hashGraph.lowestCommonAncestorMultipleVertices( + vertexDependencies, + subgraph, + ); + const linearizedOperations = + vertexDependencies.length === 1 + ? [] + : this.hashGraph.linearizeOperations(lca, subgraph); + return { lca, linearizedOperations }; + } + // get the map representing the state of the given DRP by mapping variable names to their corresponding values private _getDRPState(drp: DRP): DRPState { const varNames: string[] = Object.keys(drp); @@ -365,40 +373,68 @@ export class DRPObject implements IDRPObject { // compute the DRP state based on all dependencies of the current vertex private _computeDRPState( vertexDependencies: Hash[], + preCompute?: LcaAndOperations, vertexOperation?: Operation, ): DRPState { - const drp = this._computeDRP(vertexDependencies, vertexOperation); + const drp = this._computeDRP( + vertexDependencies, + preCompute, + vertexOperation, + ); return this._getDRPState(drp); } private _computeACLState( vertexDependencies: Hash[], + preCompute?: LcaAndOperations, vertexOperation?: Operation, ): DRPState { - const drp = this._computeACL(vertexDependencies, vertexOperation); + const drp = this._computeACL( + vertexDependencies, + preCompute, + vertexOperation, + ); return this._getDRPState(drp); } // store the state of the DRP corresponding to the given vertex private _setState(vertex: Vertex, drpState?: DRPState) { - this._setACLState(vertex, drpState); - this._setDRPState(vertex, drpState); + const preCompute = this.computeLCA(vertex.dependencies); + this._setACLState(vertex, preCompute, drpState); + this._setDRPState(vertex, preCompute, drpState); } - private _setACLState(vertex: Vertex, drpState?: DRPState) { + private _setACLState( + vertex: Vertex, + preCompute?: LcaAndOperations, + drpState?: DRPState, + ) { if (this.acl) { this.statesAcl.set( vertex.hash, drpState ?? - this._computeACLState(vertex.dependencies, vertex.operation), + this._computeACLState( + vertex.dependencies, + preCompute, + vertex.operation, + ), ); } } - private _setDRPState(vertex: Vertex, drpState?: DRPState) { + private _setDRPState( + vertex: Vertex, + preCompute?: LcaAndOperations, + drpState?: DRPState, + ) { this.states.set( vertex.hash, - drpState ?? this._computeDRPState(vertex.dependencies, vertex.operation), + drpState ?? + this._computeDRPState( + vertex.dependencies, + preCompute, + vertex.operation, + ), ); } From 7528f2654386e1c4db1cd8d47c19bd3a0d8bd32b Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Wed, 8 Jan 2025 23:07:03 +0700 Subject: [PATCH 19/35] feat: rename drp and acl states --- packages/object/src/index.ts | 19 +++++++++---------- packages/object/tests/hashgraph.test.ts | 14 +++++++------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 706910e3..678996da 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -75,8 +75,8 @@ export class DRPObject implements IDRPObject { acl: ProxyHandler | null; hashGraph: HashGraph; // mapping from vertex hash to the DRP state - states: Map; - statesAcl: Map; + drpStates: Map; + aclStates: Map; originalDRP: DRP; originalACL: IACL & DRP; subscriptions: DRPObjectCallback[]; @@ -114,8 +114,8 @@ export class DRPObject implements IDRPObject { drp?.semanticsType, ); this.subscriptions = []; - this.states = new Map([[HashGraph.rootHash, { state: new Map() }]]); - this.statesAcl = new Map([[HashGraph.rootHash, { state: new Map() }]]); + this.drpStates = new Map([[HashGraph.rootHash, { state: new Map() }]]); + this.aclStates = new Map([[HashGraph.rootHash, { state: new Map() }]]); this.originalDRP = cloneDeep(drp); this.originalACL = cloneDeep(acl); this.vertices = this.hashGraph.getAllVertices(); @@ -127,7 +127,6 @@ export class DRPObject implements IDRPObject { vertices.some((v) => v.operation?.vertexType === VertexTypeOperation.acl) ) { const acl = this.acl as IACL & DRP; - return acl.resolveConflicts(vertices); } const drp = this.drp as DRP; @@ -165,7 +164,7 @@ export class DRPObject implements IDRPObject { fn: string, // biome-ignore lint: value can't be unknown because of protobuf args: any, - vertexType: VertexTypeOperation = VertexTypeOperation.drp, + vertexType: VertexTypeOperation, ) { const vertex = this.hashGraph.addToFrontier({ type: fn, @@ -287,7 +286,7 @@ export class DRPObject implements IDRPObject { const drp = cloneDeep(this.originalDRP); - const fetchedState = this.states.get(lca); + const fetchedState = this.drpStates.get(lca); if (!fetchedState) { throw new Error("State is undefined"); } @@ -320,7 +319,7 @@ export class DRPObject implements IDRPObject { const acl = cloneDeep(this.originalACL); - const fetchedState = this.statesAcl.get(lca); + const fetchedState = this.aclStates.get(lca); if (!fetchedState) { throw new Error("State is undefined"); } @@ -410,7 +409,7 @@ export class DRPObject implements IDRPObject { drpState?: DRPState, ) { if (this.acl) { - this.statesAcl.set( + this.aclStates.set( vertex.hash, drpState ?? this._computeACLState( @@ -427,7 +426,7 @@ export class DRPObject implements IDRPObject { preCompute?: LcaAndOperations, drpState?: DRPState, ) { - this.states.set( + this.drpStates.set( vertex.hash, drpState ?? this._computeDRPState( diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 5f17c44a..6e6bb9f5 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -501,17 +501,17 @@ describe("Vertex state tests", () => { const vertices = obj1.hashGraph.topologicalSort(); - const drpState1 = obj1.states.get(vertices[1]); + const drpState1 = obj1.drpStates.get(vertices[1]); expect(drpState1?.state.get("state").get(1)).toBe(true); expect(drpState1?.state.get("state").get(2)).toBe(undefined); expect(drpState1?.state.get("state").get(3)).toBe(undefined); - const drpState2 = obj1.states.get(vertices[2]); + const drpState2 = obj1.drpStates.get(vertices[2]); expect(drpState2?.state.get("state").get(1)).toBe(true); expect(drpState2?.state.get("state").get(2)).toBe(true); expect(drpState2?.state.get("state").get(3)).toBe(undefined); - const drpState3 = obj1.states.get(vertices[3]); + const drpState3 = obj1.drpStates.get(vertices[3]); expect(drpState3?.state.get("state").get(1)).toBe(true); expect(drpState3?.state.get("state").get(2)).toBe(true); expect(drpState3?.state.get("state").get(3)).toBe(true); @@ -549,21 +549,21 @@ describe("Vertex state tests", () => { drp1.add(6); const hashA6 = obj1.hashGraph.getFrontier()[0]; - const drpState1 = obj1.states.get(hashA4); + const drpState1 = obj1.drpStates.get(hashA4); expect(drpState1?.state.get("state").get(1)).toBe(true); expect(drpState1?.state.get("state").get(2)).toBe(true); expect(drpState1?.state.get("state").get(3)).toBe(undefined); expect(drpState1?.state.get("state").get(4)).toBe(true); expect(drpState1?.state.get("state").get(5)).toBe(undefined); - const drpState2 = obj1.states.get(hashC5); + const drpState2 = obj1.drpStates.get(hashC5); expect(drpState2?.state.get("state").get(1)).toBe(undefined); expect(drpState2?.state.get("state").get(2)).toBe(true); expect(drpState2?.state.get("state").get(3)).toBe(true); expect(drpState2?.state.get("state").get(4)).toBe(undefined); expect(drpState2?.state.get("state").get(5)).toBe(true); - const drpState3 = obj1.states.get(hashA6); + const drpState3 = obj1.drpStates.get(hashA6); expect(drpState3?.state.get("state").get(1)).toBe(true); expect(drpState3?.state.get("state").get(2)).toBe(true); expect(drpState3?.state.get("state").get(3)).toBe(true); @@ -612,7 +612,7 @@ describe("Vertex state tests", () => { obj3.merge(obj2.hashGraph.getAllVertices()); const hashV8 = obj1.hashGraph.getFrontier()[0]; - const drpStateV8 = obj1.states.get(hashV8); + const drpStateV8 = obj1.drpStates.get(hashV8); expect(drpStateV8?.state.get("state").get(1)).toBe(false); expect(drpStateV8?.state.get("state").get(2)).toBe(true); expect(drpStateV8?.state.get("state").get(3)).toBe(undefined); From 54bd49f4cfb5193d2c74746f883bd997c5b5b6d1 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Thu, 9 Jan 2025 10:42:24 +0700 Subject: [PATCH 20/35] feat: improve if else drp type --- packages/object/src/index.ts | 43 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 678996da..3b319f70 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -197,30 +197,39 @@ export class DRPObject implements IDRPObject { } try { - const preComputeLca = this.computeLCA(vertex.dependencies); - const drp = - vertex.operation.vertexType === VertexTypeOperation.acl - ? this._computeACL(vertex.dependencies, preComputeLca) - : this._computeDRP(vertex.dependencies, preComputeLca); if (!this._checkWriterPermission(vertex.peerId)) { throw new Error(`${vertex.peerId} does not have write permission.`); } + const preComputeLca = this.computeLCA(vertex.dependencies); - this.hashGraph.addVertex( - vertex.operation, - vertex.dependencies, - vertex.peerId, - vertex.timestamp, - vertex.signature, - ); + if (vertex.operation.vertexType === VertexTypeOperation.drp) { + const drp = this._computeDRP(vertex.dependencies, preComputeLca); + + this.hashGraph.addVertex( + vertex.operation, + vertex.dependencies, + vertex.peerId, + vertex.timestamp, + vertex.signature, + ); + this._applyOperation(drp, vertex.operation); - this._applyOperation(drp, vertex.operation); - if (vertex.operation.vertexType === VertexTypeOperation.acl) { - this._setACLState(vertex, preComputeLca, this._getDRPState(drp)); - this._setDRPState(vertex, preComputeLca); - } else { this._setACLState(vertex, preComputeLca); this._setDRPState(vertex, preComputeLca, this._getDRPState(drp)); + } else { + const drp = this._computeACL(vertex.dependencies, preComputeLca); + + this.hashGraph.addVertex( + vertex.operation, + vertex.dependencies, + vertex.peerId, + vertex.timestamp, + vertex.signature, + ); + this._applyOperation(drp, vertex.operation); + + this._setACLState(vertex, preComputeLca, this._getDRPState(drp)); + this._setDRPState(vertex, preComputeLca); } } catch (e) { missing.push(vertex.hash); From bfab6704e00b26446ba76fd7020f162865bf71a5 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Fri, 10 Jan 2025 15:19:35 +0700 Subject: [PATCH 21/35] resolve comment --- packages/node/src/handlers.ts | 1 - packages/object/benchmark-output.txt | 3 +++ packages/object/src/index.ts | 12 ++++++------ 3 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 packages/object/benchmark-output.txt diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index d91aefca..d7c468e8 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -244,7 +244,6 @@ export async function verifyIncomingVertices( }; }); - const drp = object.drp as DRP; const acl: IACL & DRP = object.acl as IACL & DRP; if (!acl) { return vertices; diff --git a/packages/object/benchmark-output.txt b/packages/object/benchmark-output.txt new file mode 100644 index 00000000..0e2166dd --- /dev/null +++ b/packages/object/benchmark-output.txt @@ -0,0 +1,3 @@ +Create HashGraph with 1000 vertices x 23.21 ops/sec ±2.81% (44 runs sampled) +Create 2 DRP Objects (1000 vertices each) and Merge x 0.57 ops/sec ±4.55% (6 runs sampled) +Fastest is Create HashGraph with 1000 vertices diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 3b319f70..d1fca4da 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -217,7 +217,7 @@ export class DRPObject implements IDRPObject { this._setACLState(vertex, preComputeLca); this._setDRPState(vertex, preComputeLca, this._getDRPState(drp)); } else { - const drp = this._computeACL(vertex.dependencies, preComputeLca); + const acl = this._computeACL(vertex.dependencies, preComputeLca); this.hashGraph.addVertex( vertex.operation, @@ -226,9 +226,9 @@ export class DRPObject implements IDRPObject { vertex.timestamp, vertex.signature, ); - this._applyOperation(drp, vertex.operation); + this._applyOperation(acl, vertex.operation); - this._setACLState(vertex, preComputeLca, this._getDRPState(drp)); + this._setACLState(vertex, preComputeLca, this._getDRPState(acl)); this._setDRPState(vertex, preComputeLca); } } catch (e) { @@ -322,7 +322,7 @@ export class DRPObject implements IDRPObject { vertexDependencies: Hash[], preCompute?: LcaAndOperations, vertexOperation?: Operation, - ): DRP { + ): (IACL & DRP) { const { lca, linearizedOperations } = preCompute ?? this.computeLCA(vertexDependencies); @@ -397,12 +397,12 @@ export class DRPObject implements IDRPObject { preCompute?: LcaAndOperations, vertexOperation?: Operation, ): DRPState { - const drp = this._computeACL( + const acl = this._computeACL( vertexDependencies, preCompute, vertexOperation, ); - return this._getDRPState(drp); + return this._getDRPState(acl); } // store the state of the DRP corresponding to the given vertex From ef2250ca32094f54c883663eb164893af25b4ffe Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Sun, 12 Jan 2025 11:22:21 +0700 Subject: [PATCH 22/35] delete file proto auto generate --- .gitignore | 3 ++- packages/network/src/proto/drp/network/v1/messages_grpc_pb.js | 1 - packages/object/src/proto/drp/object/v1/object_grpc_pb.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) delete mode 100644 packages/network/src/proto/drp/network/v1/messages_grpc_pb.js delete mode 100644 packages/object/src/proto/drp/object/v1/object_grpc_pb.js diff --git a/.gitignore b/.gitignore index b2c616ea..e2d9284b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ node_modules/ **/tsconfig.tsbuildinfo coverage/* -.vscode/* \ No newline at end of file +.vscode/* +**/object_grpc_pb.js \ No newline at end of file diff --git a/packages/network/src/proto/drp/network/v1/messages_grpc_pb.js b/packages/network/src/proto/drp/network/v1/messages_grpc_pb.js deleted file mode 100644 index 97b3a246..00000000 --- a/packages/network/src/proto/drp/network/v1/messages_grpc_pb.js +++ /dev/null @@ -1 +0,0 @@ -// GENERATED CODE -- NO SERVICES IN PROTO \ No newline at end of file diff --git a/packages/object/src/proto/drp/object/v1/object_grpc_pb.js b/packages/object/src/proto/drp/object/v1/object_grpc_pb.js deleted file mode 100644 index 97b3a246..00000000 --- a/packages/object/src/proto/drp/object/v1/object_grpc_pb.js +++ /dev/null @@ -1 +0,0 @@ -// GENERATED CODE -- NO SERVICES IN PROTO \ No newline at end of file From 5477f3497d57e4bbac816457c61cc1c676c1dcbf Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Sun, 12 Jan 2025 11:36:21 +0700 Subject: [PATCH 23/35] resolve comment --- packages/node/src/handlers.ts | 2 +- packages/object/src/index.ts | 30 +++++++++++++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 83cf439d..a3544f8b 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -248,7 +248,7 @@ export async function verifyIncomingVertices( }; }); - const acl: IACL & DRP = object.acl as IACL & DRP; + const acl: IACL = object.acl as IACL; if (!acl) { return vertices; } diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index c2984516..46529494 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -152,7 +152,11 @@ export class DRPObject implements IDRPObject { ?.trim() .split(" ")[1]; if (!callerName?.startsWith("Proxy.")) - obj.callFn(fullPropKey, args.length === 1 ? args[0] : args, vertexType); + obj.callFn( + fullPropKey, + args.length === 1 ? args[0] : args, + vertexType, + ); return Reflect.apply(applyTarget, thisArg, args); }, }); @@ -163,7 +167,6 @@ export class DRPObject implements IDRPObject { }; } - callFn( fn: string, // biome-ignore lint: value can't be unknown because of protobuf @@ -171,14 +174,13 @@ export class DRPObject implements IDRPObject { vertexType: VertexTypeOperation, ) { // biome-ignore lint/suspicious/noExplicitAny: - let preOperationDRP: any - if (vertexType === VertexTypeOperation.acl) { - preOperationDRP = this._computeDRP(this.hashGraph.getFrontier()); - - } else { + let preOperationDRP: any; + if (vertexType === VertexTypeOperation.acl) { preOperationDRP = this._computeACL(this.hashGraph.getFrontier()); + } else { + preOperationDRP = this._computeDRP(this.hashGraph.getFrontier()); } - const drp = cloneDeep(preOperationDRP); + const drp = cloneDeep(preOperationDRP); this._applyOperation(drp, { type: fn, value: args, vertexType }); let stateChanged = false; @@ -193,7 +195,11 @@ export class DRPObject implements IDRPObject { return; } - const vertex = this.hashGraph.addToFrontier({ type: fn, value: args, vertexType }); + const vertex = this.hashGraph.addToFrontier({ + type: fn, + value: args, + vertexType, + }); this._setState(vertex, this._getDRPState(drp)); @@ -280,9 +286,7 @@ export class DRPObject implements IDRPObject { // check if the given peer has write permission private _checkWriterPermission(peerId: string): boolean { - return this.acl - ? Reflect.get(this.acl, "isWriter").call(this.acl, peerId) - : true; + return this.acl ? (this.acl as IACL).query_isAdmin(peerId) : true; } // apply the operation to the DRP @@ -346,7 +350,7 @@ export class DRPObject implements IDRPObject { vertexDependencies: Hash[], preCompute?: LcaAndOperations, vertexOperation?: Operation, - ): (IACL & DRP) { + ): DRP { const { lca, linearizedOperations } = preCompute ?? this.computeLCA(vertexDependencies); From 762433a75bc3f02d1a27f0fe118640907a0325d9 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Sun, 12 Jan 2025 11:37:30 +0700 Subject: [PATCH 24/35] feat: remove file --- packages/object/benchmark-output.txt | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 packages/object/benchmark-output.txt diff --git a/packages/object/benchmark-output.txt b/packages/object/benchmark-output.txt deleted file mode 100644 index 0e2166dd..00000000 --- a/packages/object/benchmark-output.txt +++ /dev/null @@ -1,3 +0,0 @@ -Create HashGraph with 1000 vertices x 23.21 ops/sec ±2.81% (44 runs sampled) -Create 2 DRP Objects (1000 vertices each) and Merge x 0.57 ops/sec ±4.55% (6 runs sampled) -Fastest is Create HashGraph with 1000 vertices From 50b42db76336eca1a643d9c3c9c7ffb5606f7578 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Sun, 12 Jan 2025 17:56:54 +0700 Subject: [PATCH 25/35] feat: fix all testcase --- packages/node/src/version.ts | 2 +- packages/object/src/index.ts | 5 ++++- packages/object/tests/hashgraph.test.ts | 4 ++-- pnpm-lock.yaml | 28 ++++++++++++------------- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/node/src/version.ts b/packages/node/src/version.ts index 86305dfd..4cae557f 100644 --- a/packages/node/src/version.ts +++ b/packages/node/src/version.ts @@ -1 +1 @@ -export const VERSION = "0.4.4"; +export const VERSION = "0.5.0"; diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index a2ea323a..899a1e82 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -151,6 +151,9 @@ export class DRPObject implements IDRPObject { ?.split("\n")[2] ?.trim() .split(" ")[1]; + if (callerName?.startsWith("DRPObject.resolveConflicts")) { + return Reflect.apply(applyTarget, thisArg, args); + } if (!callerName?.startsWith("Proxy.")) obj.callFn( fullPropKey, @@ -285,7 +288,7 @@ export class DRPObject implements IDRPObject { // check if the given peer has write permission private _checkWriterPermission(peerId: string): boolean { - return this.acl ? (this.acl as IACL).query_isAdmin(peerId) : true; + return this.acl ? (this.acl as IACL).query_isWriter(peerId) : true; } // apply the operation to the DRP diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 3f6d9219..17f98839 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -166,7 +166,7 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ { type: "add", value: 1, vertexType: "drp" }, - { type: "add", value: 1, vertexType: "drp" }, + { type: "remove", value: 1, vertexType: "drp" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -743,7 +743,7 @@ describe("Writer permission tests", () => { obj2.merge(obj1.hashGraph.getAllVertices()); expect(drp2.query_contains(1)).toBe(true); - expect(acl2.query_isAdmin("peer2")).toBe(true); + expect(acl2.query_isWriter("peer2")).toBe(true); drp2.add(4); obj1.merge(obj2.hashGraph.getAllVertices()); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cba94e64..3bc36095 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,10 +54,10 @@ importers: examples/canvas: dependencies: '@ts-drp/node': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../../packages/node '@ts-drp/object': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../../packages/object devDependencies: '@types/node': @@ -76,10 +76,10 @@ importers: examples/chat: dependencies: '@ts-drp/node': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../../packages/node '@ts-drp/object': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../../packages/object devDependencies: '@types/node': @@ -98,10 +98,10 @@ importers: examples/grid: dependencies: '@ts-drp/node': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../../packages/node '@ts-drp/object': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../../packages/object devDependencies: '@types/node': @@ -120,7 +120,7 @@ importers: examples/local-bootstrap: dependencies: '@ts-drp/node': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../../packages/node devDependencies: '@types/node': @@ -143,7 +143,7 @@ importers: version: 4.1.5 devDependencies: '@ts-drp/object': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../object packages/logger: @@ -209,7 +209,7 @@ importers: specifier: ^12.3.1 version: 12.3.4 '@ts-drp/logger': - specifier: ^0.4.4 + specifier: ^0.5.0 version: link:../logger it-length-prefixed: specifier: ^9.1.0 @@ -249,16 +249,16 @@ importers: specifier: ^2.1.3 version: 2.3.0 '@ts-drp/blueprints': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../blueprints '@ts-drp/logger': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../logger '@ts-drp/network': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../network '@ts-drp/object': - specifier: 0.4.4 + specifier: 0.5.0 version: link:../object commander: specifier: ^13.0.0 @@ -289,7 +289,7 @@ importers: packages/object: dependencies: '@ts-drp/logger': - specifier: ^0.4.4 + specifier: ^0.5.0 version: link:../logger fast-deep-equal: specifier: ^3.1.3 From 85ae5dc9392369ef7376f7936a8e10004b8696bf Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Sun, 12 Jan 2025 17:59:00 +0700 Subject: [PATCH 26/35] fix biome --- packages/node/src/handlers.ts | 2 +- packages/object/tests/hashgraph.test.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index c76f282f..69bad817 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -1,6 +1,6 @@ import type { Stream } from "@libp2p/interface"; import { NetworkPb, streamToUint8Array } from "@ts-drp/network"; -import type { DRP, DRPObject, IACL, ObjectPb, Vertex } from "@ts-drp/object"; +import type { DRPObject, IACL, ObjectPb, Vertex } from "@ts-drp/object"; import { fromString as uint8ArrayFromString } from "uint8arrays/from-string"; import { type DRPNode, log } from "./index.js"; diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 17f98839..bdb6adaa 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -694,7 +694,6 @@ describe("Vertex timestamp tests", () => { }); }); - describe("Writer permission tests", () => { let obj1: DRPObject; let obj2: DRPObject; From 0d1544eacf3b2d4f0a15c6556f75a1edc5d55ac0 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 13 Jan 2025 02:14:14 +0700 Subject: [PATCH 27/35] feat: change vertexType to drpType, type to opType --- packages/blueprints/src/ACL/index.ts | 6 +- packages/blueprints/src/AddWinsSet/index.ts | 4 +- .../blueprints/src/AddWinsSetWithACL/index.ts | 12 +-- .../src/proto/drp/object/v1/object_pb.ts | 42 +++++----- packages/node/src/handlers.ts | 4 +- packages/node/tests/node.test.ts | 4 +- packages/object/src/hashgraph/index.ts | 6 +- packages/object/src/index.ts | 44 +++++------ .../src/proto/drp/object/v1/object.proto | 6 +- .../src/proto/drp/object/v1/object_pb.ts | 42 +++++----- packages/object/tests/hashgraph.test.ts | 78 +++++++++---------- 11 files changed, 123 insertions(+), 125 deletions(-) diff --git a/packages/blueprints/src/ACL/index.ts b/packages/blueprints/src/ACL/index.ts index 91c0e15c..eee88340 100644 --- a/packages/blueprints/src/ACL/index.ts +++ b/packages/blueprints/src/ACL/index.ts @@ -72,7 +72,7 @@ export class ACL implements IACL, DRP { if (!vertices[0].operation || !vertices[1].operation) return { action: ActionType.Nop }; if ( - vertices[0].operation.type === vertices[1].operation.type || + vertices[0].operation.opType === vertices[1].operation.opType || vertices[0].operation.value !== vertices[1].operation.value ) return { action: ActionType.Nop }; @@ -80,13 +80,13 @@ export class ACL implements IACL, DRP { return this._conflictResolution === ACLConflictResolution.GrantWins ? { action: - vertices[0].operation.type === "grant" + vertices[0].operation.opType === "grant" ? ActionType.DropRight : ActionType.DropLeft, } : { action: - vertices[0].operation.type === "grant" + vertices[0].operation.opType === "grant" ? ActionType.DropLeft : ActionType.DropRight, }; diff --git a/packages/blueprints/src/AddWinsSet/index.ts b/packages/blueprints/src/AddWinsSet/index.ts index 2d030063..81e4e87b 100644 --- a/packages/blueprints/src/AddWinsSet/index.ts +++ b/packages/blueprints/src/AddWinsSet/index.ts @@ -38,10 +38,10 @@ export class AddWinsSet implements DRP { if ( vertices[0].operation && vertices[1].operation && - vertices[0].operation?.type !== vertices[1].operation?.type && + vertices[0].operation?.opType !== vertices[1].operation?.opType && vertices[0].operation?.value === vertices[1].operation?.value ) { - return vertices[0].operation.type === "add" + return vertices[0].operation.opType === "add" ? { action: ActionType.DropRight } : { action: ActionType.DropLeft }; } diff --git a/packages/blueprints/src/AddWinsSetWithACL/index.ts b/packages/blueprints/src/AddWinsSetWithACL/index.ts index 91c0e9b8..65ac649c 100644 --- a/packages/blueprints/src/AddWinsSetWithACL/index.ts +++ b/packages/blueprints/src/AddWinsSetWithACL/index.ts @@ -41,23 +41,23 @@ export class AddWinsSetWithACL implements DRP { if (!vertices[0].operation || !vertices[1].operation) return { action: ActionType.Nop }; if ( - vertices[0].operation.type === vertices[1].operation.type || + vertices[0].operation.opType === vertices[1].operation.opType || vertices[0].operation.value !== vertices[1].operation.value ) return { action: ActionType.Nop }; if ( - ["grant", "revoke"].includes(vertices[0].operation.type) && - ["grant", "revoke"].includes(vertices[1].operation.type) + ["grant", "revoke"].includes(vertices[0].operation.opType) && + ["grant", "revoke"].includes(vertices[1].operation.opType) ) { return this.acl.resolveConflicts(vertices); } if ( - this.operations.includes(vertices[0].operation.type) && - this.operations.includes(vertices[1].operation.type) + this.operations.includes(vertices[0].operation.opType) && + this.operations.includes(vertices[1].operation.opType) ) { - return vertices[0].operation.type === "add" + return vertices[0].operation.opType === "add" ? { action: ActionType.DropRight } : { action: ActionType.DropLeft }; } diff --git a/packages/network/src/proto/drp/object/v1/object_pb.ts b/packages/network/src/proto/drp/object/v1/object_pb.ts index 4e907eb2..3bf8b74f 100644 --- a/packages/network/src/proto/drp/object/v1/object_pb.ts +++ b/packages/network/src/proto/drp/object/v1/object_pb.ts @@ -21,9 +21,9 @@ export interface Vertex { } export interface Vertex_Operation { - type: string; + drpType: string; + opType: string; value: any | undefined; - vertexType: string; } export interface DRPObjectBase { @@ -178,19 +178,19 @@ export const Vertex: MessageFns = { }; function createBaseVertex_Operation(): Vertex_Operation { - return { type: "", value: undefined, vertexType: "" }; + return { drpType: "", opType: "", value: undefined }; } export const Vertex_Operation: MessageFns = { encode(message: Vertex_Operation, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.type !== "") { - writer.uint32(10).string(message.type); + if (message.drpType !== "") { + writer.uint32(10).string(message.drpType); } - if (message.value !== undefined) { - Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).join(); + if (message.opType !== "") { + writer.uint32(18).string(message.opType); } - if (message.vertexType !== "") { - writer.uint32(26).string(message.vertexType); + if (message.value !== undefined) { + Value.encode(Value.wrap(message.value), writer.uint32(26).fork()).join(); } return writer; }, @@ -207,7 +207,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.type = reader.string(); + message.drpType = reader.string(); continue; } case 2: { @@ -215,7 +215,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + message.opType = reader.string(); continue; } case 3: { @@ -223,7 +223,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.vertexType = reader.string(); + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); continue; } } @@ -237,23 +237,23 @@ export const Vertex_Operation: MessageFns = { fromJSON(object: any): Vertex_Operation { return { - type: isSet(object.type) ? globalThis.String(object.type) : "", + drpType: isSet(object.drpType) ? globalThis.String(object.drpType) : "", + opType: isSet(object.opType) ? globalThis.String(object.opType) : "", value: isSet(object?.value) ? object.value : undefined, - vertexType: isSet(object.vertexType) ? globalThis.String(object.vertexType) : "", }; }, toJSON(message: Vertex_Operation): unknown { const obj: any = {}; - if (message.type !== "") { - obj.type = message.type; + if (message.drpType !== "") { + obj.drpType = message.drpType; + } + if (message.opType !== "") { + obj.opType = message.opType; } if (message.value !== undefined) { obj.value = message.value; } - if (message.vertexType !== "") { - obj.vertexType = message.vertexType; - } return obj; }, @@ -262,9 +262,9 @@ export const Vertex_Operation: MessageFns = { }, fromPartial, I>>(object: I): Vertex_Operation { const message = createBaseVertex_Operation(); - message.type = object.type ?? ""; + message.drpType = object.drpType ?? ""; + message.opType = object.opType ?? ""; message.value = object.value ?? undefined; - message.vertexType = object.vertexType ?? ""; return message; }, }; diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 69bad817..2e2f4ebc 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -238,9 +238,9 @@ export async function verifyIncomingVertices( hash: vertex.hash, peerId: vertex.peerId, operation: { - type: vertex.operation?.type ?? "", + drpType: vertex.operation?.drpType ?? "", + opType: vertex.operation?.opType ?? "", value: vertex.operation?.value, - vertexType: vertex.operation?.vertexType ?? "", }, dependencies: vertex.dependencies, timestamp: vertex.timestamp, diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index 252178f9..95e7d3f9 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -1,6 +1,6 @@ import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; import { AddWinsSet } from "@topology-foundation/blueprints/src/index.js"; -import { VertexTypeOperation } from "@topology-foundation/object/src/index.js"; +import { DrpTypeOperation } from "@topology-foundation/object/src/index.js"; import { type DRP, DRPObject } from "@ts-drp/object"; import { beforeAll, beforeEach, describe, expect, test } from "vitest"; import { @@ -108,7 +108,7 @@ describe("DPRNode with verify and sign signature", () => { operation: { type: "add", value: 1, - vertexType: VertexTypeOperation.drp, + vertexType: DrpTypeOperation.Drp, }, dependencies: [], signature: "", diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index 1d4e102d..94eb0387 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -80,9 +80,9 @@ export class HashGraph { hash: HashGraph.rootHash, peerId: "", operation: { - type: OperationType.NOP, + drpType: "", + opType: OperationType.NOP, value: null, - vertexType: "", }, dependencies: [], timestamp: -1, @@ -104,7 +104,7 @@ export class HashGraph { const vertex: Vertex = { hash, peerId: this.peerId, - operation: operation ?? { type: OperationType.NOP }, + operation: operation ?? { opType: OperationType.NOP }, dependencies: deps, timestamp: currentTimestamp, signature: "", diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index 899a1e82..afecd428 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -60,9 +60,9 @@ export interface LcaAndOperations { export let log: Logger; -export enum VertexTypeOperation { - acl = "acl", - drp = "drp", +export enum DrpTypeOperation { + Acl = "ACL", + Drp = "DRP", } export class DRPObject implements IDRPObject { @@ -103,10 +103,10 @@ export class DRPObject implements IDRPObject { this.bytecode = new Uint8Array(); this.vertices = []; this.drp = drp - ? new Proxy(drp, this.proxyDRPHandler(VertexTypeOperation.drp)) + ? new Proxy(drp, this.proxyDRPHandler(DrpTypeOperation.Drp)) : null; this.acl = acl - ? new Proxy(acl, this.proxyDRPHandler(VertexTypeOperation.acl)) + ? new Proxy(acl, this.proxyDRPHandler(DrpTypeOperation.Acl)) : null; this.hashGraph = new HashGraph( peerId, @@ -124,7 +124,7 @@ export class DRPObject implements IDRPObject { resolveConflicts(vertices: Vertex[]): ResolveConflictsType { if ( this.acl && - vertices.some((v) => v.operation?.vertexType === VertexTypeOperation.acl) + vertices.some((v) => v.operation?.drpType === DrpTypeOperation.Acl) ) { const acl = this.acl as IACL & DRP; return acl.resolveConflicts(vertices); @@ -134,7 +134,7 @@ export class DRPObject implements IDRPObject { } // This function is black magic, it allows us to intercept calls to the DRP object - proxyDRPHandler(vertexType: VertexTypeOperation): ProxyHandler { + proxyDRPHandler(vertexType: DrpTypeOperation): ProxyHandler { const obj = this; return { get(target, propKey, receiver) { @@ -174,17 +174,17 @@ export class DRPObject implements IDRPObject { fn: string, // biome-ignore lint: value can't be unknown because of protobuf args: any, - vertexType: VertexTypeOperation, + drpType: DrpTypeOperation, ) { // biome-ignore lint/suspicious/noExplicitAny: let preOperationDRP: any; - if (vertexType === VertexTypeOperation.acl) { + if (drpType === DrpTypeOperation.Acl) { preOperationDRP = this._computeACL(this.hashGraph.getFrontier()); } else { preOperationDRP = this._computeDRP(this.hashGraph.getFrontier()); } const drp = cloneDeep(preOperationDRP); - this._applyOperation(drp, { type: fn, value: args, vertexType }); + this._applyOperation(drp, { opType: fn, value: args, drpType }); let stateChanged = false; for (const key of Object.keys(preOperationDRP)) { @@ -199,9 +199,9 @@ export class DRPObject implements IDRPObject { } const vertex = this.hashGraph.addToFrontier({ - type: fn, + drpType: drpType, + opType: fn, value: args, - vertexType, }); this._setState(vertex, this._getDRPState(drp)); @@ -235,7 +235,7 @@ export class DRPObject implements IDRPObject { } const preComputeLca = this.computeLCA(vertex.dependencies); - if (vertex.operation.vertexType === VertexTypeOperation.drp) { + if (vertex.operation.drpType === DrpTypeOperation.Drp) { const drp = this._computeDRP(vertex.dependencies, preComputeLca); this.hashGraph.addVertex( vertex.operation, @@ -293,21 +293,21 @@ export class DRPObject implements IDRPObject { // apply the operation to the DRP private _applyOperation(drp: DRP, operation: Operation) { - const { type, value } = operation; + const { opType, value } = operation; - const typeParts = type.split("."); + const typeParts = opType.split("."); // biome-ignore lint: target can be anything let target: any = drp; for (let i = 0; i < typeParts.length - 1; i++) { target = target[typeParts[i]]; if (!target) { - throw new Error(`Invalid operation type: ${type}`); + throw new Error(`Invalid operation type: ${opType}`); } } const methodName = typeParts[typeParts.length - 1]; if (typeof target[methodName] !== "function") { - throw new Error(`${type} is not a function`); + throw new Error(`${opType} is not a function`); } const args = Array.isArray(value) ? value : [value]; @@ -337,11 +337,10 @@ export class DRPObject implements IDRPObject { } for (const op of linearizedOperations) { - op.vertexType === VertexTypeOperation.drp && - this._applyOperation(drp, op); + op.drpType === DrpTypeOperation.Drp && this._applyOperation(drp, op); } if (vertexOperation) { - vertexOperation.vertexType === VertexTypeOperation.drp && + vertexOperation.drpType === DrpTypeOperation.Drp && this._applyOperation(drp, vertexOperation); } @@ -369,11 +368,10 @@ export class DRPObject implements IDRPObject { acl[key] = value; } for (const op of linearizedOperations) { - op.vertexType === VertexTypeOperation.acl && - this._applyOperation(acl, op); + op.drpType === DrpTypeOperation.Acl && this._applyOperation(acl, op); } if (vertexOperation) { - vertexOperation.vertexType === VertexTypeOperation.acl && + vertexOperation.drpType === DrpTypeOperation.Acl && this._applyOperation(acl, vertexOperation); } diff --git a/packages/object/src/proto/drp/object/v1/object.proto b/packages/object/src/proto/drp/object/v1/object.proto index 97842bc1..009e65aa 100644 --- a/packages/object/src/proto/drp/object/v1/object.proto +++ b/packages/object/src/proto/drp/object/v1/object.proto @@ -7,9 +7,9 @@ import "google/protobuf/struct.proto"; // Supposed to be the RIBLT stuff message Vertex { message Operation { - string type = 1; - google.protobuf.Value value = 2; - string vertex_type = 3; + string drp_type = 1; + string op_type = 2; + google.protobuf.Value value = 3; } string hash = 1; string peer_id = 2; diff --git a/packages/object/src/proto/drp/object/v1/object_pb.ts b/packages/object/src/proto/drp/object/v1/object_pb.ts index 4e907eb2..3bf8b74f 100644 --- a/packages/object/src/proto/drp/object/v1/object_pb.ts +++ b/packages/object/src/proto/drp/object/v1/object_pb.ts @@ -21,9 +21,9 @@ export interface Vertex { } export interface Vertex_Operation { - type: string; + drpType: string; + opType: string; value: any | undefined; - vertexType: string; } export interface DRPObjectBase { @@ -178,19 +178,19 @@ export const Vertex: MessageFns = { }; function createBaseVertex_Operation(): Vertex_Operation { - return { type: "", value: undefined, vertexType: "" }; + return { drpType: "", opType: "", value: undefined }; } export const Vertex_Operation: MessageFns = { encode(message: Vertex_Operation, writer: BinaryWriter = new BinaryWriter()): BinaryWriter { - if (message.type !== "") { - writer.uint32(10).string(message.type); + if (message.drpType !== "") { + writer.uint32(10).string(message.drpType); } - if (message.value !== undefined) { - Value.encode(Value.wrap(message.value), writer.uint32(18).fork()).join(); + if (message.opType !== "") { + writer.uint32(18).string(message.opType); } - if (message.vertexType !== "") { - writer.uint32(26).string(message.vertexType); + if (message.value !== undefined) { + Value.encode(Value.wrap(message.value), writer.uint32(26).fork()).join(); } return writer; }, @@ -207,7 +207,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.type = reader.string(); + message.drpType = reader.string(); continue; } case 2: { @@ -215,7 +215,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.value = Value.unwrap(Value.decode(reader, reader.uint32())); + message.opType = reader.string(); continue; } case 3: { @@ -223,7 +223,7 @@ export const Vertex_Operation: MessageFns = { break; } - message.vertexType = reader.string(); + message.value = Value.unwrap(Value.decode(reader, reader.uint32())); continue; } } @@ -237,23 +237,23 @@ export const Vertex_Operation: MessageFns = { fromJSON(object: any): Vertex_Operation { return { - type: isSet(object.type) ? globalThis.String(object.type) : "", + drpType: isSet(object.drpType) ? globalThis.String(object.drpType) : "", + opType: isSet(object.opType) ? globalThis.String(object.opType) : "", value: isSet(object?.value) ? object.value : undefined, - vertexType: isSet(object.vertexType) ? globalThis.String(object.vertexType) : "", }; }, toJSON(message: Vertex_Operation): unknown { const obj: any = {}; - if (message.type !== "") { - obj.type = message.type; + if (message.drpType !== "") { + obj.drpType = message.drpType; + } + if (message.opType !== "") { + obj.opType = message.opType; } if (message.value !== undefined) { obj.value = message.value; } - if (message.vertexType !== "") { - obj.vertexType = message.vertexType; - } return obj; }, @@ -262,9 +262,9 @@ export const Vertex_Operation: MessageFns = { }, fromPartial, I>>(object: I): Vertex_Operation { const message = createBaseVertex_Operation(); - message.type = object.type ?? ""; + message.drpType = object.drpType ?? ""; + message.opType = object.opType ?? ""; message.value = object.value ?? undefined; - message.vertexType = object.vertexType ?? ""; return message; }, }; diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index bdb6adaa..4bcf2c65 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -51,8 +51,8 @@ describe("HashGraph construction tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { type: "add", value: 2, vertexType: "drp" }, - { type: "add", value: 1, vertexType: "drp" }, + { opType: "add", value: 2, drpType: "DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, ] as Operation[]); }); @@ -66,9 +66,9 @@ describe("HashGraph construction tests", () => { // add fake root const hash = obj1.hashGraph.addVertex( { - type: "root", + opType: "root", value: null, - vertexType: "drp", + drpType:"DRP", }, [], "", @@ -77,9 +77,9 @@ describe("HashGraph construction tests", () => { ); obj1.hashGraph.addVertex( { - type: "add", + opType: "add", value: 1, - vertexType: "drp", + drpType:"DRP", }, [hash], "", @@ -90,7 +90,7 @@ describe("HashGraph construction tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -132,11 +132,11 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ { - type: "add", + opType: "add", value: 1, - vertexType: "drp", + drpType:"DRP", }, - { type: "remove", value: 1, vertexType: "drp" }, + { opType: "remove", value: 1, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -165,8 +165,8 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, vertexType: "drp" }, - { type: "remove", value: 1, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, + { opType: "remove", value: 1, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -195,9 +195,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, vertexType: "drp" }, - { type: "remove", value: 1, vertexType: "drp" }, - { type: "add", value: 2, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, + { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "add", value: 2, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -230,9 +230,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, vertexType: "drp" }, - { type: "remove", value: 1, vertexType: "drp" }, - { type: "add", value: 10, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, + { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "add", value: 10, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -263,9 +263,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, vertexType: "drp" }, - { type: "remove", value: 1, vertexType: "drp" }, - { type: "add", value: 2, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, + { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "add", value: 2, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -317,11 +317,11 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, vertexType: "drp" }, - { type: "remove", value: 1, vertexType: "drp" }, - { type: "add", value: 2, vertexType: "drp" }, - { type: "add", value: 3, vertexType: "drp" }, - { type: "remove", value: 1, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, + { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "add", value: 2, drpType:"DRP" }, + { opType: "add", value: 3, drpType:"DRP" }, + { opType: "remove", value: 1, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -373,10 +373,10 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { type: "add", value: 1, vertexType: "drp" }, - { type: "remove", value: 1, vertexType: "drp" }, - { type: "add", value: 3, vertexType: "drp" }, - { type: "add", value: 2, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, + { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "add", value: 3, drpType:"DRP" }, + { opType: "add", value: 2, drpType:"DRP" }, ]); }); @@ -408,9 +408,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { type: "add", value: 1, vertexType: "drp" }, - { type: "add", value: 2, vertexType: "drp" }, - { type: "remove", value: 2, vertexType: "drp" }, + { opType: "add", value: 1, drpType:"DRP" }, + { opType: "add", value: 2, drpType:"DRP" }, + { opType: "remove", value: 2, drpType:"DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -447,7 +447,7 @@ describe("HashGraph for undefined operations tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); // Should only have one, since we skipped the undefined operations - expect(linearOps).toEqual([{ type: "add", value: 2, vertexType: "drp" }]); + expect(linearOps).toEqual([{ opType: "add", value: 2, drpType:"DRP" }]); }); test("Test: addToFrontier with undefined operation return Vertex with NoOp operation", () => { @@ -457,7 +457,7 @@ describe("HashGraph for undefined operations tests", () => { ); expect(createdVertex.operation).toEqual({ - type: OperationType.NOP, + opType: OperationType.NOP, } as Operation); }); }); @@ -646,9 +646,9 @@ describe("Vertex timestamp tests", () => { expect(() => obj1.hashGraph.addVertex( { - type: "add", + opType: "add", value: 1, - vertexType: "drp", + drpType:"DRP", }, obj1.hashGraph.getFrontier(), "", @@ -681,9 +681,9 @@ describe("Vertex timestamp tests", () => { expect(() => obj1.hashGraph.addVertex( { - type: "add", + opType: "add", value: 1, - vertexType: "drp", + drpType:"DRP", }, obj1.hashGraph.getFrontier(), "", From cf0ff806d33d7d7258d254d1011369a1d0a4ddb7 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 13 Jan 2025 02:19:25 +0700 Subject: [PATCH 28/35] fix testcase --- .../tests/AddWinsSetWithACL.test.ts | 4 +- packages/object/tests/hashgraph.test.ts | 62 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/blueprints/tests/AddWinsSetWithACL.test.ts b/packages/blueprints/tests/AddWinsSetWithACL.test.ts index 7e435959..e741278e 100644 --- a/packages/blueprints/tests/AddWinsSetWithACL.test.ts +++ b/packages/blueprints/tests/AddWinsSetWithACL.test.ts @@ -43,7 +43,7 @@ describe("AccessControl tests with RevokeWins resolution", () => { { hash: "", peerId: "peer1", - operation: { type: "grant", value: "peer3" }, + operation: { opType: "grant", value: "peer3" }, dependencies: [], signature: "", timestamp: 0, @@ -51,7 +51,7 @@ describe("AccessControl tests with RevokeWins resolution", () => { { hash: "", peerId: "peer2", - operation: { type: "revoke", value: "peer3" }, + operation: { opType: "revoke", value: "peer3" }, dependencies: [], signature: "", timestamp: 0, diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 4bcf2c65..192b28fd 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -68,7 +68,7 @@ describe("HashGraph construction tests", () => { { opType: "root", value: null, - drpType:"DRP", + drpType: "DRP", }, [], "", @@ -79,7 +79,7 @@ describe("HashGraph construction tests", () => { { opType: "add", value: 1, - drpType:"DRP", + drpType: "DRP", }, [hash], "", @@ -90,7 +90,7 @@ describe("HashGraph construction tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -134,9 +134,9 @@ describe("HashGraph for AddWinSet tests", () => { { opType: "add", value: 1, - drpType:"DRP", + drpType: "DRP", }, - { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -165,8 +165,8 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType:"DRP" }, - { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -195,9 +195,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType:"DRP" }, - { opType: "remove", value: 1, drpType:"DRP" }, - { opType: "add", value: 2, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "add", value: 2, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -230,9 +230,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType:"DRP" }, - { opType: "remove", value: 1, drpType:"DRP" }, - { opType: "add", value: 10, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "add", value: 10, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -263,9 +263,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType:"DRP" }, - { opType: "remove", value: 1, drpType:"DRP" }, - { opType: "add", value: 2, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "add", value: 2, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -317,11 +317,11 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType:"DRP" }, - { opType: "remove", value: 1, drpType:"DRP" }, - { opType: "add", value: 2, drpType:"DRP" }, - { opType: "add", value: 3, drpType:"DRP" }, - { opType: "remove", value: 1, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "add", value: 2, drpType: "DRP" }, + { opType: "add", value: 3, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -373,10 +373,10 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { opType: "add", value: 1, drpType:"DRP" }, - { opType: "remove", value: 1, drpType:"DRP" }, - { opType: "add", value: 3, drpType:"DRP" }, - { opType: "add", value: 2, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "add", value: 3, drpType: "DRP" }, + { opType: "add", value: 2, drpType: "DRP" }, ]); }); @@ -408,9 +408,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType:"DRP" }, - { opType: "add", value: 2, drpType:"DRP" }, - { opType: "remove", value: 2, drpType:"DRP" }, + { opType: "add", value: 1, drpType: "DRP" }, + { opType: "add", value: 2, drpType: "DRP" }, + { opType: "remove", value: 2, drpType: "DRP" }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -447,7 +447,7 @@ describe("HashGraph for undefined operations tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); // Should only have one, since we skipped the undefined operations - expect(linearOps).toEqual([{ opType: "add", value: 2, drpType:"DRP" }]); + expect(linearOps).toEqual([{ opType: "add", value: 2, drpType: "DRP" }]); }); test("Test: addToFrontier with undefined operation return Vertex with NoOp operation", () => { @@ -648,7 +648,7 @@ describe("Vertex timestamp tests", () => { { opType: "add", value: 1, - drpType:"DRP", + drpType: "DRP", }, obj1.hashGraph.getFrontier(), "", @@ -683,7 +683,7 @@ describe("Vertex timestamp tests", () => { { opType: "add", value: 1, - drpType:"DRP", + drpType: "DRP", }, obj1.hashGraph.getFrontier(), "", From c28c30d5d606c5627ed45097e5f67e0b74624ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ho=C3=A0ng=20Qu=E1=BB=91c=20Vi=E1=BB=87t?= Date: Mon, 13 Jan 2025 10:12:39 +0700 Subject: [PATCH 29/35] fix: performance PR 318 (#348) --- packages/object/src/hashgraph/index.ts | 16 +++++++++++++--- packages/object/src/index.ts | 3 ++- .../object/src/linearize/multipleSemantics.ts | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index 94eb0387..025ec70b 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -44,7 +44,8 @@ export type VertexDistance = { export class HashGraph { peerId: string; - resolveConflicts: (vertices: Vertex[]) => ResolveConflictsType; + resolveConflictsDRP: (vertices: Vertex[]) => ResolveConflictsType; + resolveConflictsACL: (vertices: Vertex[]) => ResolveConflictsType; semanticsType: SemanticsType; vertices: Map = new Map(); @@ -69,11 +70,13 @@ export class HashGraph { constructor( peerId: string, - resolveConflicts: (vertices: Vertex[]) => ResolveConflictsType, + resolveConflictsDRP: (vertices: Vertex[]) => ResolveConflictsType, + resolveConflictsACL: (vertices: Vertex[]) => ResolveConflictsType, semanticsType: SemanticsType, ) { this.peerId = peerId; - this.resolveConflicts = resolveConflicts; + this.resolveConflictsDRP = resolveConflictsDRP; + this.resolveConflictsACL = resolveConflictsACL this.semanticsType = semanticsType; const rootVertex: Vertex = { @@ -96,6 +99,13 @@ export class HashGraph { }); } + resolveConflicts(vertices: Vertex[]): ResolveConflictsType { + if (vertices.some((vertex) => vertex.operation?.vertexType === "acl")) { + return this.resolveConflictsACL(vertices); + } + return this.resolveConflictsDRP(vertices); + } + addToFrontier(operation: Operation): Vertex { const deps = this.getFrontier(); const currentTimestamp = Date.now(); diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index afecd428..c1bded5e 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -110,7 +110,8 @@ export class DRPObject implements IDRPObject { : null; this.hashGraph = new HashGraph( peerId, - this.resolveConflicts.bind(this), + drp?.resolveConflicts?.bind(this), + acl?.resolveConflicts?.bind(this), drp?.semanticsType, ); this.subscriptions = []; diff --git a/packages/object/src/linearize/multipleSemantics.ts b/packages/object/src/linearize/multipleSemantics.ts index b0b58fb1..549d389a 100644 --- a/packages/object/src/linearize/multipleSemantics.ts +++ b/packages/object/src/linearize/multipleSemantics.ts @@ -63,8 +63,9 @@ export function linearizeMultipleSemantics( } k++; } + const resolved = hashGraph.resolveConflicts( - concurrentOps.map((hash) => hashGraph.vertices.get(hash) as Vertex), + concurrentOps.map((hash) => hashGraph.vertices.get(hash) as Vertex) ); switch (resolved.action) { From 05398b250a5e13107bc96ac44034a8cbf1864d9c Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 13 Jan 2025 10:16:18 +0700 Subject: [PATCH 30/35] fix update drpType --- packages/object/src/hashgraph/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index 025ec70b..a00cfbbe 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -100,7 +100,7 @@ export class HashGraph { } resolveConflicts(vertices: Vertex[]): ResolveConflictsType { - if (vertices.some((vertex) => vertex.operation?.vertexType === "acl")) { + if (vertices.some((vertex) => vertex.operation?.drpType === "ACL")) { return this.resolveConflictsACL(vertices); } return this.resolveConflictsDRP(vertices); From bb59631b2b6cd1b680896b02f78c8f61d8967f13 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 13 Jan 2025 10:31:59 +0700 Subject: [PATCH 31/35] fix testcase --- packages/node/tests/node.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index 8fd8888f..031d3ab7 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -70,7 +70,7 @@ describe("DPRNode with verify and sign signature", () => { hash: "hash", peerId: drpNode.networkNode.peerId, operation: { - type: "add", + opType: "add", value: 1, }, dependencies: [], From 4be0f0b25041ba5174b590b24c1018b758fc4b58 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 13 Jan 2025 10:40:02 +0700 Subject: [PATCH 32/35] fix: follow issue #242 --- packages/object/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index c1bded5e..f818fe3a 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -110,8 +110,8 @@ export class DRPObject implements IDRPObject { : null; this.hashGraph = new HashGraph( peerId, - drp?.resolveConflicts?.bind(this), - acl?.resolveConflicts?.bind(this), + drp?.resolveConflicts?.bind(drp ?? this), + acl?.resolveConflicts?.bind(acl ?? this), drp?.semanticsType, ); this.subscriptions = []; From 0087443dfa83a050abd162130d3e4c2779211fcc Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 13 Jan 2025 10:41:13 +0700 Subject: [PATCH 33/35] fix biome --- packages/object/src/hashgraph/index.ts | 2 +- packages/object/src/linearize/multipleSemantics.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index 41e84a3c..59bae0c7 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -76,7 +76,7 @@ export class HashGraph { ) { this.peerId = peerId; this.resolveConflictsDRP = resolveConflictsDRP; - this.resolveConflictsACL = resolveConflictsACL + this.resolveConflictsACL = resolveConflictsACL; this.semanticsType = semanticsType; const rootVertex: Vertex = { diff --git a/packages/object/src/linearize/multipleSemantics.ts b/packages/object/src/linearize/multipleSemantics.ts index 549d389a..e6f2b561 100644 --- a/packages/object/src/linearize/multipleSemantics.ts +++ b/packages/object/src/linearize/multipleSemantics.ts @@ -65,7 +65,7 @@ export function linearizeMultipleSemantics( } const resolved = hashGraph.resolveConflicts( - concurrentOps.map((hash) => hashGraph.vertices.get(hash) as Vertex) + concurrentOps.map((hash) => hashGraph.vertices.get(hash) as Vertex), ); switch (resolved.action) { From 9650147958ad67e704c0211c1a22900c99ef9696 Mon Sep 17 00:00:00 2001 From: anhnd350309 Date: Mon, 13 Jan 2025 17:08:29 +0700 Subject: [PATCH 34/35] fix: change check some verties to check first vertex --- packages/object/src/hashgraph/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/object/src/hashgraph/index.ts b/packages/object/src/hashgraph/index.ts index 59bae0c7..8da4ab3c 100644 --- a/packages/object/src/hashgraph/index.ts +++ b/packages/object/src/hashgraph/index.ts @@ -100,7 +100,7 @@ export class HashGraph { } resolveConflicts(vertices: Vertex[]): ResolveConflictsType { - if (vertices.some((vertex) => vertex.operation?.drpType === "ACL")) { + if (vertices[0].operation?.drpType === "ACL") { return this.resolveConflictsACL(vertices); } return this.resolveConflictsDRP(vertices); From a09352cd38f5ca349367bab79e1df965985b3eec Mon Sep 17 00:00:00 2001 From: droak Date: Thu, 16 Jan 2025 02:38:12 +0530 Subject: [PATCH 35/35] rename DrpTypeOperation; use that instead of strings --- packages/node/src/version.ts | 2 +- packages/node/tests/node.test.ts | 5 +- packages/object/src/index.ts | 28 ++++----- packages/object/tests/hashgraph.test.ts | 77 ++++++++++++++----------- pnpm-lock.yaml | 28 ++++----- 5 files changed, 71 insertions(+), 69 deletions(-) diff --git a/packages/node/src/version.ts b/packages/node/src/version.ts index 5090edbd..5c8df723 100644 --- a/packages/node/src/version.ts +++ b/packages/node/src/version.ts @@ -1 +1 @@ -export const VERSION = "0.5.1"; +export const VERSION = "0.5.2"; diff --git a/packages/node/tests/node.test.ts b/packages/node/tests/node.test.ts index 031d3ab7..58c857aa 100644 --- a/packages/node/tests/node.test.ts +++ b/packages/node/tests/node.test.ts @@ -1,7 +1,6 @@ import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; import { AddWinsSet } from "@topology-foundation/blueprints/src/index.js"; -import { DrpTypeOperation } from "@topology-foundation/object/src/index.js"; -import { type DRP, DRPObject } from "@ts-drp/object"; +import { type DRP, DRPObject, DrpType } from "@ts-drp/object"; import { beforeAll, beforeEach, describe, expect, test } from "vitest"; import { signGeneratedVertices, @@ -112,7 +111,7 @@ describe("DPRNode with verify and sign signature", () => { operation: { type: "add", value: 1, - vertexType: DrpTypeOperation.Drp, + vertexType: DrpType.Drp, }, dependencies: [], timestamp: Date.now(), diff --git a/packages/object/src/index.ts b/packages/object/src/index.ts index f818fe3a..2a69df8d 100644 --- a/packages/object/src/index.ts +++ b/packages/object/src/index.ts @@ -60,7 +60,7 @@ export interface LcaAndOperations { export let log: Logger; -export enum DrpTypeOperation { +export enum DrpType { Acl = "ACL", Drp = "DRP", } @@ -102,12 +102,8 @@ export class DRPObject implements IDRPObject { this.abi = abi ?? ""; this.bytecode = new Uint8Array(); this.vertices = []; - this.drp = drp - ? new Proxy(drp, this.proxyDRPHandler(DrpTypeOperation.Drp)) - : null; - this.acl = acl - ? new Proxy(acl, this.proxyDRPHandler(DrpTypeOperation.Acl)) - : null; + this.drp = drp ? new Proxy(drp, this.proxyDRPHandler(DrpType.Drp)) : null; + this.acl = acl ? new Proxy(acl, this.proxyDRPHandler(DrpType.Acl)) : null; this.hashGraph = new HashGraph( peerId, drp?.resolveConflicts?.bind(drp ?? this), @@ -125,7 +121,7 @@ export class DRPObject implements IDRPObject { resolveConflicts(vertices: Vertex[]): ResolveConflictsType { if ( this.acl && - vertices.some((v) => v.operation?.drpType === DrpTypeOperation.Acl) + vertices.some((v) => v.operation?.drpType === DrpType.Acl) ) { const acl = this.acl as IACL & DRP; return acl.resolveConflicts(vertices); @@ -135,7 +131,7 @@ export class DRPObject implements IDRPObject { } // This function is black magic, it allows us to intercept calls to the DRP object - proxyDRPHandler(vertexType: DrpTypeOperation): ProxyHandler { + proxyDRPHandler(vertexType: DrpType): ProxyHandler { const obj = this; return { get(target, propKey, receiver) { @@ -175,11 +171,11 @@ export class DRPObject implements IDRPObject { fn: string, // biome-ignore lint: value can't be unknown because of protobuf args: any, - drpType: DrpTypeOperation, + drpType: DrpType, ) { // biome-ignore lint/suspicious/noExplicitAny: let preOperationDRP: any; - if (drpType === DrpTypeOperation.Acl) { + if (drpType === DrpType.Acl) { preOperationDRP = this._computeACL(this.hashGraph.getFrontier()); } else { preOperationDRP = this._computeDRP(this.hashGraph.getFrontier()); @@ -236,7 +232,7 @@ export class DRPObject implements IDRPObject { } const preComputeLca = this.computeLCA(vertex.dependencies); - if (vertex.operation.drpType === DrpTypeOperation.Drp) { + if (vertex.operation.drpType === DrpType.Drp) { const drp = this._computeDRP(vertex.dependencies, preComputeLca); this.hashGraph.addVertex( vertex.operation, @@ -338,10 +334,10 @@ export class DRPObject implements IDRPObject { } for (const op of linearizedOperations) { - op.drpType === DrpTypeOperation.Drp && this._applyOperation(drp, op); + op.drpType === DrpType.Drp && this._applyOperation(drp, op); } if (vertexOperation) { - vertexOperation.drpType === DrpTypeOperation.Drp && + vertexOperation.drpType === DrpType.Drp && this._applyOperation(drp, vertexOperation); } @@ -369,10 +365,10 @@ export class DRPObject implements IDRPObject { acl[key] = value; } for (const op of linearizedOperations) { - op.drpType === DrpTypeOperation.Acl && this._applyOperation(acl, op); + op.drpType === DrpType.Acl && this._applyOperation(acl, op); } if (vertexOperation) { - vertexOperation.drpType === DrpTypeOperation.Acl && + vertexOperation.drpType === DrpType.Acl && this._applyOperation(acl, vertexOperation); } diff --git a/packages/object/tests/hashgraph.test.ts b/packages/object/tests/hashgraph.test.ts index 7e174970..33cbbd0a 100644 --- a/packages/object/tests/hashgraph.test.ts +++ b/packages/object/tests/hashgraph.test.ts @@ -1,7 +1,12 @@ import { ACL } from "@topology-foundation/blueprints/src/ACL/index.js"; import { beforeEach, describe, expect, test } from "vitest"; import { AddWinsSet } from "../../blueprints/src/AddWinsSet/index.js"; -import { DRPObject, type Operation, OperationType } from "../src/index.js"; +import { + DRPObject, + DrpType, + type Operation, + OperationType, +} from "../src/index.js"; describe("HashGraph construction tests", () => { let obj1: DRPObject; @@ -51,8 +56,8 @@ describe("HashGraph construction tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { opType: "add", value: 2, drpType: "DRP" }, - { opType: "add", value: 1, drpType: "DRP" }, + { opType: "add", value: 2, drpType: DrpType.Drp }, + { opType: "add", value: 1, drpType: DrpType.Drp }, ] as Operation[]); }); @@ -68,7 +73,7 @@ describe("HashGraph construction tests", () => { { opType: "root", value: null, - drpType: "DRP", + drpType: DrpType.Drp, }, [], "", @@ -79,7 +84,7 @@ describe("HashGraph construction tests", () => { { opType: "add", value: 1, - drpType: "DRP", + drpType: DrpType.Drp, }, [hash], "", @@ -90,7 +95,7 @@ describe("HashGraph construction tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -134,9 +139,9 @@ describe("HashGraph for AddWinSet tests", () => { { opType: "add", value: 1, - drpType: "DRP", + drpType: DrpType.Drp, }, - { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -165,8 +170,8 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType: "DRP" }, - { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -195,9 +200,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType: "DRP" }, - { opType: "remove", value: 1, drpType: "DRP" }, - { opType: "add", value: 2, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, + { opType: "add", value: 2, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -230,9 +235,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType: "DRP" }, - { opType: "remove", value: 1, drpType: "DRP" }, - { opType: "add", value: 10, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, + { opType: "add", value: 10, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -263,9 +268,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType: "DRP" }, - { opType: "remove", value: 1, drpType: "DRP" }, - { opType: "add", value: 2, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, + { opType: "add", value: 2, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -317,11 +322,11 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType: "DRP" }, - { opType: "remove", value: 1, drpType: "DRP" }, - { opType: "add", value: 2, drpType: "DRP" }, - { opType: "add", value: 3, drpType: "DRP" }, - { opType: "remove", value: 1, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, + { opType: "add", value: 2, drpType: DrpType.Drp }, + { opType: "add", value: 3, drpType: DrpType.Drp }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -373,10 +378,10 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); expect(linearOps).toEqual([ - { opType: "add", value: 1, drpType: "DRP" }, - { opType: "remove", value: 1, drpType: "DRP" }, - { opType: "add", value: 3, drpType: "DRP" }, - { opType: "add", value: 2, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, + { opType: "remove", value: 1, drpType: DrpType.Drp }, + { opType: "add", value: 3, drpType: DrpType.Drp }, + { opType: "add", value: 2, drpType: DrpType.Drp }, ]); }); @@ -408,9 +413,9 @@ describe("HashGraph for AddWinSet tests", () => { const linearOps = obj1.hashGraph.linearizeOperations(); const expectedOps: Operation[] = [ - { opType: "add", value: 1, drpType: "DRP" }, - { opType: "add", value: 2, drpType: "DRP" }, - { opType: "remove", value: 2, drpType: "DRP" }, + { opType: "add", value: 1, drpType: DrpType.Drp }, + { opType: "add", value: 2, drpType: DrpType.Drp }, + { opType: "remove", value: 2, drpType: DrpType.Drp }, ]; expect(linearOps).toEqual(expectedOps); }); @@ -447,7 +452,9 @@ describe("HashGraph for undefined operations tests", () => { const linearOps = obj2.hashGraph.linearizeOperations(); // Should only have one, since we skipped the undefined operations - expect(linearOps).toEqual([{ opType: "add", value: 2, drpType: "DRP" }]); + expect(linearOps).toEqual([ + { opType: "add", value: 2, drpType: DrpType.Drp }, + ]); }); test("Test: addToFrontier with undefined operation return Vertex with NoOp operation", () => { @@ -648,7 +655,7 @@ describe("Vertex timestamp tests", () => { { opType: "add", value: 1, - drpType: "DRP", + drpType: DrpType.Drp, }, obj1.hashGraph.getFrontier(), "", @@ -661,7 +668,7 @@ describe("Vertex timestamp tests", () => { test("Test: Vertex's timestamp must not be less than any of its dependencies' timestamps", () => { /* __ V1:ADD(1) __ - / \ + / \ ROOT -- V2:ADD(2) ---- V4:ADD(4) (invalid) \ / -- V3:ADD(3) -- @@ -683,7 +690,7 @@ describe("Vertex timestamp tests", () => { { opType: "add", value: 1, - drpType: "DRP", + drpType: DrpType.Drp, }, obj1.hashGraph.getFrontier(), "", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index efd0a85f..6c9f54c5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,10 +54,10 @@ importers: examples/canvas: dependencies: '@ts-drp/node': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../../packages/node '@ts-drp/object': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../../packages/object devDependencies: '@types/node': @@ -76,10 +76,10 @@ importers: examples/chat: dependencies: '@ts-drp/node': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../../packages/node '@ts-drp/object': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../../packages/object devDependencies: '@types/node': @@ -98,10 +98,10 @@ importers: examples/grid: dependencies: '@ts-drp/node': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../../packages/node '@ts-drp/object': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../../packages/object devDependencies: '@types/node': @@ -120,7 +120,7 @@ importers: examples/local-bootstrap: dependencies: '@ts-drp/node': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../../packages/node devDependencies: '@types/node': @@ -143,7 +143,7 @@ importers: version: 4.1.5 devDependencies: '@ts-drp/object': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../object packages/logger: @@ -209,7 +209,7 @@ importers: specifier: ^12.3.1 version: 12.3.4 '@ts-drp/logger': - specifier: ^0.5.1 + specifier: ^0.5.2 version: link:../logger it-length-prefixed: specifier: ^9.1.0 @@ -249,16 +249,16 @@ importers: specifier: ^2.1.3 version: 2.3.0 '@ts-drp/blueprints': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../blueprints '@ts-drp/logger': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../logger '@ts-drp/network': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../network '@ts-drp/object': - specifier: 0.5.1 + specifier: 0.5.2 version: link:../object commander: specifier: ^13.0.0 @@ -289,7 +289,7 @@ importers: packages/object: dependencies: '@ts-drp/logger': - specifier: ^0.5.1 + specifier: ^0.5.2 version: link:../logger es-toolkit: specifier: 1.30.1