@optimystic/db-p2p 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cluster/block-transfer-service.d.ts +66 -0
- package/dist/src/cluster/block-transfer-service.d.ts.map +1 -0
- package/dist/src/cluster/block-transfer-service.js +163 -0
- package/dist/src/cluster/block-transfer-service.js.map +1 -0
- package/dist/src/cluster/block-transfer.d.ts +79 -0
- package/dist/src/cluster/block-transfer.d.ts.map +1 -0
- package/dist/src/cluster/block-transfer.js +211 -0
- package/dist/src/cluster/block-transfer.js.map +1 -0
- package/dist/src/cluster/cluster-repo.d.ts +14 -3
- package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
- package/dist/src/cluster/cluster-repo.js +80 -35
- package/dist/src/cluster/cluster-repo.js.map +1 -1
- package/dist/src/cluster/rebalance-monitor.d.ts +64 -0
- package/dist/src/cluster/rebalance-monitor.d.ts.map +1 -0
- package/dist/src/cluster/rebalance-monitor.js +159 -0
- package/dist/src/cluster/rebalance-monitor.js.map +1 -0
- package/dist/src/cluster/service.js +1 -1
- package/dist/src/cluster/service.js.map +1 -1
- package/dist/src/dispute/arbitrator-selection.d.ts +10 -0
- package/dist/src/dispute/arbitrator-selection.d.ts.map +1 -0
- package/dist/src/dispute/arbitrator-selection.js +22 -0
- package/dist/src/dispute/arbitrator-selection.js.map +1 -0
- package/dist/src/dispute/client.d.ts +17 -0
- package/dist/src/dispute/client.d.ts.map +1 -0
- package/dist/src/dispute/client.js +28 -0
- package/dist/src/dispute/client.js.map +1 -0
- package/dist/src/dispute/dispute-service.d.ts +81 -0
- package/dist/src/dispute/dispute-service.d.ts.map +1 -0
- package/dist/src/dispute/dispute-service.js +365 -0
- package/dist/src/dispute/dispute-service.js.map +1 -0
- package/dist/src/dispute/engine-health-monitor.d.ts +22 -0
- package/dist/src/dispute/engine-health-monitor.d.ts.map +1 -0
- package/dist/src/dispute/engine-health-monitor.js +75 -0
- package/dist/src/dispute/engine-health-monitor.js.map +1 -0
- package/dist/src/dispute/index.d.ts +7 -0
- package/dist/src/dispute/index.d.ts.map +1 -0
- package/dist/src/dispute/index.js +7 -0
- package/dist/src/dispute/index.js.map +1 -0
- package/dist/src/dispute/service.d.ts +41 -0
- package/dist/src/dispute/service.d.ts.map +1 -0
- package/dist/src/dispute/service.js +82 -0
- package/dist/src/dispute/service.js.map +1 -0
- package/dist/src/dispute/types.d.ts +106 -0
- package/dist/src/dispute/types.d.ts.map +1 -0
- package/dist/src/dispute/types.js +7 -0
- package/dist/src/dispute/types.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/libp2p-key-network.d.ts +23 -2
- package/dist/src/libp2p-key-network.d.ts.map +1 -1
- package/dist/src/libp2p-key-network.js +100 -15
- package/dist/src/libp2p-key-network.js.map +1 -1
- package/dist/src/libp2p-node-base.d.ts +6 -0
- package/dist/src/libp2p-node-base.d.ts.map +1 -1
- package/dist/src/libp2p-node-base.js +66 -12
- package/dist/src/libp2p-node-base.js.map +1 -1
- package/dist/src/logger.d.ts +1 -0
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +2 -0
- package/dist/src/logger.js.map +1 -1
- package/dist/src/network/network-manager-service.d.ts +15 -4
- package/dist/src/network/network-manager-service.d.ts.map +1 -1
- package/dist/src/network/network-manager-service.js +33 -20
- package/dist/src/network/network-manager-service.js.map +1 -1
- package/dist/src/protocol-client.d.ts +1 -0
- package/dist/src/protocol-client.d.ts.map +1 -1
- package/dist/src/protocol-client.js +23 -2
- package/dist/src/protocol-client.js.map +1 -1
- package/dist/src/repo/client.d.ts +1 -0
- package/dist/src/repo/client.d.ts.map +1 -1
- package/dist/src/repo/client.js +18 -1
- package/dist/src/repo/client.js.map +1 -1
- package/dist/src/repo/cluster-coordinator.d.ts +3 -1
- package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
- package/dist/src/repo/cluster-coordinator.js +42 -2
- package/dist/src/repo/cluster-coordinator.js.map +1 -1
- package/dist/src/repo/coordinator-repo.d.ts +18 -2
- package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
- package/dist/src/repo/coordinator-repo.js +62 -6
- package/dist/src/repo/coordinator-repo.js.map +1 -1
- package/dist/src/repo/service.d.ts +18 -2
- package/dist/src/repo/service.d.ts.map +1 -1
- package/dist/src/repo/service.js +88 -91
- package/dist/src/repo/service.js.map +1 -1
- package/dist/src/reputation/index.d.ts +3 -0
- package/dist/src/reputation/index.d.ts.map +1 -0
- package/dist/src/reputation/index.js +3 -0
- package/dist/src/reputation/index.js.map +1 -0
- package/dist/src/reputation/peer-reputation.d.ts +23 -0
- package/dist/src/reputation/peer-reputation.d.ts.map +1 -0
- package/dist/src/reputation/peer-reputation.js +121 -0
- package/dist/src/reputation/peer-reputation.js.map +1 -0
- package/dist/src/reputation/types.d.ts +89 -0
- package/dist/src/reputation/types.d.ts.map +1 -0
- package/dist/src/reputation/types.js +42 -0
- package/dist/src/reputation/types.js.map +1 -0
- package/dist/src/storage/arachnode-fret-adapter.d.ts +5 -0
- package/dist/src/storage/arachnode-fret-adapter.d.ts.map +1 -1
- package/dist/src/storage/arachnode-fret-adapter.js +10 -0
- package/dist/src/storage/arachnode-fret-adapter.js.map +1 -1
- package/dist/src/storage/block-storage.d.ts.map +1 -1
- package/dist/src/storage/block-storage.js +5 -0
- package/dist/src/storage/block-storage.js.map +1 -1
- package/dist/src/storage/storage-repo.d.ts.map +1 -1
- package/dist/src/storage/storage-repo.js +8 -0
- package/dist/src/storage/storage-repo.js.map +1 -1
- package/package.json +11 -10
- package/src/cluster/block-transfer-service.ts +228 -0
- package/src/cluster/block-transfer.ts +284 -0
- package/src/cluster/cluster-repo.ts +93 -38
- package/src/cluster/rebalance-monitor.ts +225 -0
- package/src/dispute/arbitrator-selection.ts +28 -0
- package/src/dispute/client.ts +41 -0
- package/src/dispute/dispute-service.ts +453 -0
- package/src/dispute/engine-health-monitor.ts +86 -0
- package/src/dispute/index.ts +17 -0
- package/src/dispute/service.ts +119 -0
- package/src/dispute/types.ts +114 -0
- package/src/index.ts +3 -0
- package/src/libp2p-key-network.ts +120 -22
- package/src/libp2p-node-base.ts +77 -13
- package/src/logger.ts +2 -1
- package/src/network/network-manager-service.ts +47 -16
- package/src/protocol-client.ts +29 -7
- package/src/repo/client.ts +20 -6
- package/src/repo/cluster-coordinator.ts +43 -2
- package/src/repo/coordinator-repo.ts +70 -7
- package/src/repo/redirect.ts +0 -2
- package/src/repo/service.ts +95 -87
- package/src/reputation/index.ts +12 -0
- package/src/reputation/peer-reputation.ts +147 -0
- package/src/reputation/types.ts +117 -0
- package/src/storage/arachnode-fret-adapter.ts +11 -0
- package/src/storage/block-storage.ts +6 -0
- package/src/storage/storage-repo.ts +9 -0
- package/dist/index.min.js +0 -53
- package/dist/index.min.js.map +0 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arbitrator-selection.d.ts","sourceRoot":"","sources":["../../../src/dispute/arbitrator-selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEnF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,SAAS,EAAE,EACrB,YAAY,EAAE,UAAU,EACxB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,KAAK,EAAE,MAAM,GACX,MAAM,EAAE,CAaV"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { sortPeersByDistance } from '../routing/responsibility.js';
|
|
2
|
+
/**
|
|
3
|
+
* Select arbitrators for a dispute using XOR-distance from the block ID.
|
|
4
|
+
* Selects the next K peers beyond the original cluster (positions K+1 through 2K).
|
|
5
|
+
* This ensures independence (arbitrators are not in the original cluster)
|
|
6
|
+
* and determinism (all parties agree on who arbitrates).
|
|
7
|
+
*/
|
|
8
|
+
export function selectArbitrators(allPeers, blockIdBytes, excludePeerIds, count) {
|
|
9
|
+
// Sort all peers by XOR distance to the block ID
|
|
10
|
+
const sorted = sortPeersByDistance(allPeers, blockIdBytes);
|
|
11
|
+
// Skip peers in the original cluster (and self), select the next K
|
|
12
|
+
const arbitrators = [];
|
|
13
|
+
for (const peer of sorted) {
|
|
14
|
+
if (arbitrators.length >= count)
|
|
15
|
+
break;
|
|
16
|
+
if (excludePeerIds.has(peer.id.toString()))
|
|
17
|
+
continue;
|
|
18
|
+
arbitrators.push(peer.id);
|
|
19
|
+
}
|
|
20
|
+
return arbitrators;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=arbitrator-selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arbitrator-selection.js","sourceRoot":"","sources":["../../../src/dispute/arbitrator-selection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAkB,MAAM,8BAA8B,CAAC;AAEnF;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAChC,QAAqB,EACrB,YAAwB,EACxB,cAA2B,EAC3B,KAAa;IAEb,iDAAiD;IACjD,MAAM,MAAM,GAAG,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAE3D,mEAAmE;IACnE,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,WAAW,CAAC,MAAM,IAAI,KAAK;YAAE,MAAM;QACvC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;YAAE,SAAS;QACrD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,WAAW,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PeerId, IPeerNetwork } from '@optimystic/db-core';
|
|
2
|
+
import { ProtocolClient } from '../protocol-client.js';
|
|
3
|
+
import type { DisputeChallenge, DisputeResolution, ArbitrationVote } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Client for the dispute protocol. Sends challenges to arbitrators
|
|
6
|
+
* and broadcasts resolutions.
|
|
7
|
+
*/
|
|
8
|
+
export declare class DisputeClient extends ProtocolClient {
|
|
9
|
+
private readonly protocol;
|
|
10
|
+
constructor(peerId: PeerId, peerNetwork: IPeerNetwork, protocolPrefix?: string);
|
|
11
|
+
static create(peerId: PeerId, peerNetwork: IPeerNetwork, protocolPrefix?: string): DisputeClient;
|
|
12
|
+
/** Send a challenge to an arbitrator and get their vote */
|
|
13
|
+
sendChallenge(challenge: DisputeChallenge, timeoutMs?: number): Promise<ArbitrationVote>;
|
|
14
|
+
/** Send a resolution to a peer (broadcast) */
|
|
15
|
+
sendResolution(resolution: DisputeResolution): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/dispute/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAkB,MAAM,YAAY,CAAC;AAEvG;;;GAGG;AACH,qBAAa,aAAc,SAAQ,cAAc;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,MAAM;IAK9E,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,aAAa;IAIhG,2DAA2D;IACrD,aAAa,CAAC,SAAS,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAW9F,8CAA8C;IACxC,cAAc,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;CAOlE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ProtocolClient } from '../protocol-client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Client for the dispute protocol. Sends challenges to arbitrators
|
|
4
|
+
* and broadcasts resolutions.
|
|
5
|
+
*/
|
|
6
|
+
export class DisputeClient extends ProtocolClient {
|
|
7
|
+
protocol;
|
|
8
|
+
constructor(peerId, peerNetwork, protocolPrefix) {
|
|
9
|
+
super(peerId, peerNetwork);
|
|
10
|
+
this.protocol = (protocolPrefix ?? '/db-p2p') + '/dispute/1.0.0';
|
|
11
|
+
}
|
|
12
|
+
static create(peerId, peerNetwork, protocolPrefix) {
|
|
13
|
+
return new DisputeClient(peerId, peerNetwork, protocolPrefix);
|
|
14
|
+
}
|
|
15
|
+
/** Send a challenge to an arbitrator and get their vote */
|
|
16
|
+
async sendChallenge(challenge, timeoutMs) {
|
|
17
|
+
const message = { type: 'challenge', challenge };
|
|
18
|
+
const signal = timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined;
|
|
19
|
+
const response = await this.processMessage(message, this.protocol, { signal });
|
|
20
|
+
return response.vote;
|
|
21
|
+
}
|
|
22
|
+
/** Send a resolution to a peer (broadcast) */
|
|
23
|
+
async sendResolution(resolution) {
|
|
24
|
+
const message = { type: 'resolution', resolution };
|
|
25
|
+
await this.processMessage(message, this.protocol);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/dispute/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvD;;;GAGG;AACH,MAAM,OAAO,aAAc,SAAQ,cAAc;IAC/B,QAAQ,CAAS;IAElC,YAAY,MAAc,EAAE,WAAyB,EAAE,cAAuB;QAC7E,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,CAAC,cAAc,IAAI,SAAS,CAAC,GAAG,gBAAgB,CAAC;IAClE,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,MAAc,EAAE,WAAyB,EAAE,cAAuB;QAC/E,OAAO,IAAI,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;IAC/D,CAAC;IAED,2DAA2D;IAC3D,KAAK,CAAC,aAAa,CAAC,SAA2B,EAAE,SAAkB;QAClE,MAAM,OAAO,GAAmB,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CACzC,OAAO,EACP,IAAI,CAAC,QAAQ,EACb,EAAE,MAAM,EAAE,CACV,CAAC;QACF,OAAO,QAAQ,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,cAAc,CAAC,UAA6B;QACjD,MAAM,OAAO,GAAmB,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;QACnE,MAAM,IAAI,CAAC,cAAc,CACxB,OAAO,EACP,IAAI,CAAC,QAAQ,CACb,CAAC;IACH,CAAC;CACD"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { ClusterRecord, ITransactionValidator } from '@optimystic/db-core';
|
|
2
|
+
import type { PeerId, PrivateKey } from '@libp2p/interface';
|
|
3
|
+
import type { ValidationEvidence, DisputeChallenge, ArbitrationVote, DisputeResolution, DisputeConfig, DisputeStatus } from './types.js';
|
|
4
|
+
import { EngineHealthMonitor } from './engine-health-monitor.js';
|
|
5
|
+
import type { IPeerReputation } from '../reputation/types.js';
|
|
6
|
+
import type { IPeerNetwork } from '@optimystic/db-core';
|
|
7
|
+
import type { DisputeClient } from './client.js';
|
|
8
|
+
/** Callback to create a DisputeClient for a given peer */
|
|
9
|
+
export type CreateDisputeClient = (peerId: PeerId) => DisputeClient;
|
|
10
|
+
/** Callback to re-execute a transaction and produce validation evidence */
|
|
11
|
+
export type RevalidateTransaction = (record: ClusterRecord) => Promise<ValidationEvidence | undefined>;
|
|
12
|
+
export interface DisputeServiceInit {
|
|
13
|
+
peerId: PeerId;
|
|
14
|
+
privateKey: PrivateKey;
|
|
15
|
+
peerNetwork: IPeerNetwork;
|
|
16
|
+
createDisputeClient: CreateDisputeClient;
|
|
17
|
+
reputation?: IPeerReputation;
|
|
18
|
+
validator?: ITransactionValidator;
|
|
19
|
+
revalidate?: RevalidateTransaction;
|
|
20
|
+
config?: Partial<DisputeConfig>;
|
|
21
|
+
/** Select arbitrators for a dispute (next K peers beyond the original cluster) */
|
|
22
|
+
selectArbitrators: (blockId: string, excludePeers: string[], count: number) => Promise<PeerId[]>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Manages the dispute escalation protocol.
|
|
26
|
+
*
|
|
27
|
+
* When a transaction proceeds despite minority rejections, the overridden
|
|
28
|
+
* minority can escalate to independent arbitrators. The service coordinates
|
|
29
|
+
* challenge initiation, arbitration vote collection, and resolution.
|
|
30
|
+
*/
|
|
31
|
+
export declare class DisputeService {
|
|
32
|
+
private readonly peerId;
|
|
33
|
+
private readonly privateKey;
|
|
34
|
+
private readonly createDisputeClient;
|
|
35
|
+
private readonly reputation?;
|
|
36
|
+
private readonly revalidate?;
|
|
37
|
+
private readonly config;
|
|
38
|
+
private readonly engineHealth;
|
|
39
|
+
private readonly selectArbitrators;
|
|
40
|
+
/** Active disputes initiated by this node */
|
|
41
|
+
private activeDisputes;
|
|
42
|
+
/** Resolved disputes (disputeId -> resolution) */
|
|
43
|
+
private resolvedDisputes;
|
|
44
|
+
/** Track which transactions we've already disputed (prevent spam) */
|
|
45
|
+
private disputedTransactions;
|
|
46
|
+
constructor(init: DisputeServiceInit);
|
|
47
|
+
/** Get the engine health monitor */
|
|
48
|
+
getEngineHealth(): EngineHealthMonitor;
|
|
49
|
+
/** Check if disputes are enabled */
|
|
50
|
+
isEnabled(): boolean;
|
|
51
|
+
/** Get the dispute status for a transaction, if any */
|
|
52
|
+
getDisputeStatus(messageHash: string): DisputeStatus | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Initiate a dispute when this node's rejection was overridden.
|
|
55
|
+
* Called by ClusterMember when it detects a disputed commit.
|
|
56
|
+
*/
|
|
57
|
+
initiateDispute(record: ClusterRecord, evidence: ValidationEvidence): Promise<DisputeResolution | undefined>;
|
|
58
|
+
/**
|
|
59
|
+
* Handle an incoming dispute challenge (when this node is selected as arbitrator).
|
|
60
|
+
* Re-executes the transaction and returns a vote.
|
|
61
|
+
*/
|
|
62
|
+
handleChallenge(challenge: DisputeChallenge): Promise<ArbitrationVote>;
|
|
63
|
+
/**
|
|
64
|
+
* Handle an incoming dispute resolution (broadcast from the dispute initiator).
|
|
65
|
+
*/
|
|
66
|
+
handleResolution(resolution: DisputeResolution): void;
|
|
67
|
+
/** Collect votes from arbitrators with a timeout */
|
|
68
|
+
private collectVotes;
|
|
69
|
+
/** Determine dispute resolution from collected votes */
|
|
70
|
+
resolveDispute(challenge: DisputeChallenge, votes: ArbitrationVote[]): DisputeResolution;
|
|
71
|
+
/** Apply reputation effects based on dispute resolution */
|
|
72
|
+
private applyReputationEffects;
|
|
73
|
+
/** Broadcast resolution to all interested parties */
|
|
74
|
+
private broadcastResolution;
|
|
75
|
+
private makeVote;
|
|
76
|
+
private computeDisputeId;
|
|
77
|
+
private signDispute;
|
|
78
|
+
private verifyDisputeSignature;
|
|
79
|
+
private findChallengeForDispute;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=dispute-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispute-service.d.ts","sourceRoot":"","sources":["../../../src/dispute/dispute-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { sha256 } from 'multiformats/hashes/sha2';
|
|
2
|
+
import { base58btc } from 'multiformats/bases/base58';
|
|
3
|
+
import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';
|
|
4
|
+
import { publicKeyFromRaw } from '@libp2p/crypto/keys';
|
|
5
|
+
import { DEFAULT_DISPUTE_CONFIG } from './types.js';
|
|
6
|
+
import { EngineHealthMonitor } from './engine-health-monitor.js';
|
|
7
|
+
import { PenaltyReason } from '../reputation/types.js';
|
|
8
|
+
import { createLogger } from '../logger.js';
|
|
9
|
+
const log = createLogger('dispute');
|
|
10
|
+
/**
|
|
11
|
+
* Manages the dispute escalation protocol.
|
|
12
|
+
*
|
|
13
|
+
* When a transaction proceeds despite minority rejections, the overridden
|
|
14
|
+
* minority can escalate to independent arbitrators. The service coordinates
|
|
15
|
+
* challenge initiation, arbitration vote collection, and resolution.
|
|
16
|
+
*/
|
|
17
|
+
export class DisputeService {
|
|
18
|
+
peerId;
|
|
19
|
+
privateKey;
|
|
20
|
+
createDisputeClient;
|
|
21
|
+
reputation;
|
|
22
|
+
revalidate;
|
|
23
|
+
config;
|
|
24
|
+
engineHealth;
|
|
25
|
+
selectArbitrators;
|
|
26
|
+
/** Active disputes initiated by this node */
|
|
27
|
+
activeDisputes = new Map();
|
|
28
|
+
/** Resolved disputes (disputeId -> resolution) */
|
|
29
|
+
resolvedDisputes = new Map();
|
|
30
|
+
/** Track which transactions we've already disputed (prevent spam) */
|
|
31
|
+
disputedTransactions = new Set();
|
|
32
|
+
constructor(init) {
|
|
33
|
+
this.peerId = init.peerId;
|
|
34
|
+
this.privateKey = init.privateKey;
|
|
35
|
+
this.createDisputeClient = init.createDisputeClient;
|
|
36
|
+
this.reputation = init.reputation;
|
|
37
|
+
this.revalidate = init.revalidate;
|
|
38
|
+
this.config = { ...DEFAULT_DISPUTE_CONFIG, ...init.config };
|
|
39
|
+
this.engineHealth = new EngineHealthMonitor(this.config);
|
|
40
|
+
this.selectArbitrators = init.selectArbitrators;
|
|
41
|
+
}
|
|
42
|
+
/** Get the engine health monitor */
|
|
43
|
+
getEngineHealth() {
|
|
44
|
+
return this.engineHealth;
|
|
45
|
+
}
|
|
46
|
+
/** Check if disputes are enabled */
|
|
47
|
+
isEnabled() {
|
|
48
|
+
return this.config.disputeEnabled;
|
|
49
|
+
}
|
|
50
|
+
/** Get the dispute status for a transaction, if any */
|
|
51
|
+
getDisputeStatus(messageHash) {
|
|
52
|
+
// Check if there's an active dispute for this transaction
|
|
53
|
+
for (const [, challenge] of this.activeDisputes) {
|
|
54
|
+
if (challenge.originalMessageHash === messageHash) {
|
|
55
|
+
return 'committed-disputed';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Check resolved disputes
|
|
59
|
+
for (const [, resolution] of this.resolvedDisputes) {
|
|
60
|
+
const challenge = this.findChallengeForDispute(resolution.disputeId);
|
|
61
|
+
if (challenge && challenge.originalMessageHash === messageHash) {
|
|
62
|
+
if (resolution.outcome === 'challenger-wins')
|
|
63
|
+
return 'committed-invalidated';
|
|
64
|
+
if (resolution.outcome === 'majority-wins')
|
|
65
|
+
return 'committed-validated';
|
|
66
|
+
return 'committed-disputed'; // inconclusive
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Initiate a dispute when this node's rejection was overridden.
|
|
73
|
+
* Called by ClusterMember when it detects a disputed commit.
|
|
74
|
+
*/
|
|
75
|
+
async initiateDispute(record, evidence) {
|
|
76
|
+
if (!this.config.disputeEnabled) {
|
|
77
|
+
log('dispute-disabled', { messageHash: record.messageHash });
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
// One dispute per transaction
|
|
81
|
+
if (this.disputedTransactions.has(record.messageHash)) {
|
|
82
|
+
log('dispute-already-initiated', { messageHash: record.messageHash });
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
// Don't dispute if our engine is unhealthy
|
|
86
|
+
if (this.engineHealth.isUnhealthy()) {
|
|
87
|
+
log('dispute-skipped-unhealthy', { messageHash: record.messageHash });
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
this.disputedTransactions.add(record.messageHash);
|
|
91
|
+
const timestamp = Date.now();
|
|
92
|
+
const disputeId = await this.computeDisputeId(record.messageHash, this.peerId.toString(), timestamp);
|
|
93
|
+
const signature = await this.signDispute(disputeId);
|
|
94
|
+
const defaultTtl = record.message.expiration
|
|
95
|
+
? (record.message.expiration - Date.now()) * 2
|
|
96
|
+
: this.config.disputeArbitrationTimeoutMs * 2;
|
|
97
|
+
const expiration = timestamp + Math.max(defaultTtl, this.config.disputeArbitrationTimeoutMs);
|
|
98
|
+
const challenge = {
|
|
99
|
+
disputeId,
|
|
100
|
+
originalMessageHash: record.messageHash,
|
|
101
|
+
originalRecord: record,
|
|
102
|
+
challengerPeerId: this.peerId.toString(),
|
|
103
|
+
challengerEvidence: evidence,
|
|
104
|
+
signature,
|
|
105
|
+
timestamp,
|
|
106
|
+
expiration,
|
|
107
|
+
};
|
|
108
|
+
this.activeDisputes.set(disputeId, challenge);
|
|
109
|
+
log('dispute-initiated', { disputeId, messageHash: record.messageHash });
|
|
110
|
+
// Select arbitrators and collect votes
|
|
111
|
+
const blockIds = record.coordinatingBlockIds ?? [];
|
|
112
|
+
const blockId = blockIds[0] ?? record.messageHash;
|
|
113
|
+
const originalPeers = Object.keys(record.peers);
|
|
114
|
+
const arbitratorCount = this.config.arbitratorCount ?? originalPeers.length;
|
|
115
|
+
let arbitrators;
|
|
116
|
+
try {
|
|
117
|
+
arbitrators = await this.selectArbitrators(blockId, originalPeers, arbitratorCount);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
log('dispute-arbitrator-selection-failed', { disputeId, error: err instanceof Error ? err.message : String(err) });
|
|
121
|
+
this.activeDisputes.delete(disputeId);
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
if (arbitrators.length === 0) {
|
|
125
|
+
log('dispute-no-arbitrators', { disputeId });
|
|
126
|
+
this.activeDisputes.delete(disputeId);
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
// Send challenge to all arbitrators and collect votes
|
|
130
|
+
const votes = await this.collectVotes(challenge, arbitrators);
|
|
131
|
+
const resolution = this.resolveDispute(challenge, votes);
|
|
132
|
+
this.activeDisputes.delete(disputeId);
|
|
133
|
+
this.resolvedDisputes.set(disputeId, resolution);
|
|
134
|
+
// Apply reputation effects
|
|
135
|
+
this.applyReputationEffects(resolution, record);
|
|
136
|
+
// Broadcast resolution
|
|
137
|
+
await this.broadcastResolution(resolution, arbitrators, originalPeers);
|
|
138
|
+
log('dispute-resolved', {
|
|
139
|
+
disputeId,
|
|
140
|
+
outcome: resolution.outcome,
|
|
141
|
+
votes: votes.length,
|
|
142
|
+
affectedPeers: resolution.affectedPeers.length,
|
|
143
|
+
});
|
|
144
|
+
return resolution;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Handle an incoming dispute challenge (when this node is selected as arbitrator).
|
|
148
|
+
* Re-executes the transaction and returns a vote.
|
|
149
|
+
*/
|
|
150
|
+
async handleChallenge(challenge) {
|
|
151
|
+
log('dispute-handle-challenge', { disputeId: challenge.disputeId });
|
|
152
|
+
// Verify the challenge signature
|
|
153
|
+
const validSignature = await this.verifyDisputeSignature(challenge.disputeId, challenge.signature, challenge.originalRecord.peers[challenge.challengerPeerId]?.publicKey);
|
|
154
|
+
if (!validSignature) {
|
|
155
|
+
log('dispute-invalid-challenge-signature', { disputeId: challenge.disputeId });
|
|
156
|
+
return this.makeVote(challenge.disputeId, 'inconclusive', {
|
|
157
|
+
computedHash: '',
|
|
158
|
+
engineId: 'unknown',
|
|
159
|
+
schemaHash: '',
|
|
160
|
+
blockStateHashes: {},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// Re-execute the transaction to produce our own evidence
|
|
164
|
+
let evidence;
|
|
165
|
+
if (this.revalidate) {
|
|
166
|
+
try {
|
|
167
|
+
evidence = await this.revalidate(challenge.originalRecord);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
log('dispute-revalidation-failed', {
|
|
171
|
+
disputeId: challenge.disputeId,
|
|
172
|
+
error: err instanceof Error ? err.message : String(err),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (!evidence) {
|
|
177
|
+
// Can't re-execute — vote inconclusive
|
|
178
|
+
return this.makeVote(challenge.disputeId, 'inconclusive', {
|
|
179
|
+
computedHash: '',
|
|
180
|
+
engineId: 'unknown',
|
|
181
|
+
schemaHash: '',
|
|
182
|
+
blockStateHashes: {},
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
// Compare our evidence with the challenger's
|
|
186
|
+
let vote;
|
|
187
|
+
if (evidence.computedHash === challenge.challengerEvidence.computedHash) {
|
|
188
|
+
// Our re-execution matches the challenger — the challenger is right
|
|
189
|
+
vote = 'agree-with-challenger';
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Our re-execution differs from the challenger — the majority is likely right
|
|
193
|
+
vote = 'agree-with-majority';
|
|
194
|
+
}
|
|
195
|
+
return this.makeVote(challenge.disputeId, vote, evidence);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Handle an incoming dispute resolution (broadcast from the dispute initiator).
|
|
199
|
+
*/
|
|
200
|
+
handleResolution(resolution) {
|
|
201
|
+
this.resolvedDisputes.set(resolution.disputeId, resolution);
|
|
202
|
+
log('dispute-resolution-received', {
|
|
203
|
+
disputeId: resolution.disputeId,
|
|
204
|
+
outcome: resolution.outcome,
|
|
205
|
+
});
|
|
206
|
+
// If we were penalized and the challenger won, check engine health
|
|
207
|
+
const ourId = this.peerId.toString();
|
|
208
|
+
const ourPenalty = resolution.affectedPeers.find(p => p.peerId === ourId);
|
|
209
|
+
if (ourPenalty && ourPenalty.reason === 'false-approval') {
|
|
210
|
+
this.engineHealth.recordDisputeLoss();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/** Collect votes from arbitrators with a timeout */
|
|
214
|
+
async collectVotes(challenge, arbitrators) {
|
|
215
|
+
const timeoutMs = this.config.disputeArbitrationTimeoutMs;
|
|
216
|
+
const votes = [];
|
|
217
|
+
const votePromises = arbitrators.map(async (arbitratorPeerId) => {
|
|
218
|
+
try {
|
|
219
|
+
const client = this.createDisputeClient(arbitratorPeerId);
|
|
220
|
+
const vote = await client.sendChallenge(challenge, timeoutMs);
|
|
221
|
+
return vote;
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
log('dispute-vote-collection-failed', {
|
|
225
|
+
disputeId: challenge.disputeId,
|
|
226
|
+
arbitrator: arbitratorPeerId.toString(),
|
|
227
|
+
error: err instanceof Error ? err.message : String(err),
|
|
228
|
+
});
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
const results = await Promise.allSettled(votePromises);
|
|
233
|
+
for (const result of results) {
|
|
234
|
+
if (result.status === 'fulfilled' && result.value) {
|
|
235
|
+
votes.push(result.value);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return votes;
|
|
239
|
+
}
|
|
240
|
+
/** Determine dispute resolution from collected votes */
|
|
241
|
+
resolveDispute(challenge, votes) {
|
|
242
|
+
const challengerVotes = votes.filter(v => v.vote === 'agree-with-challenger').length;
|
|
243
|
+
const majorityVotes = votes.filter(v => v.vote === 'agree-with-majority').length;
|
|
244
|
+
const totalDecisive = challengerVotes + majorityVotes;
|
|
245
|
+
// Need super-majority of decisive votes (>2/3)
|
|
246
|
+
const superMajorityThreshold = Math.ceil(totalDecisive * 2 / 3);
|
|
247
|
+
let outcome;
|
|
248
|
+
const affectedPeers = [];
|
|
249
|
+
if (totalDecisive === 0) {
|
|
250
|
+
outcome = 'inconclusive';
|
|
251
|
+
}
|
|
252
|
+
else if (challengerVotes >= superMajorityThreshold) {
|
|
253
|
+
outcome = 'challenger-wins';
|
|
254
|
+
// Penalize majority peers who approved the transaction
|
|
255
|
+
const originalRecord = challenge.originalRecord;
|
|
256
|
+
for (const [peerId, signature] of Object.entries(originalRecord.promises)) {
|
|
257
|
+
if (signature.type === 'approve' && peerId !== challenge.challengerPeerId) {
|
|
258
|
+
affectedPeers.push({ peerId, reason: 'false-approval' });
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
else if (majorityVotes >= superMajorityThreshold) {
|
|
263
|
+
outcome = 'majority-wins';
|
|
264
|
+
// Penalize the challenger
|
|
265
|
+
affectedPeers.push({ peerId: challenge.challengerPeerId, reason: 'dispute-lost' });
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
outcome = 'inconclusive';
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
disputeId: challenge.disputeId,
|
|
272
|
+
outcome,
|
|
273
|
+
votes,
|
|
274
|
+
affectedPeers,
|
|
275
|
+
timestamp: Date.now(),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/** Apply reputation effects based on dispute resolution */
|
|
279
|
+
applyReputationEffects(resolution, record) {
|
|
280
|
+
if (!this.reputation)
|
|
281
|
+
return;
|
|
282
|
+
for (const affected of resolution.affectedPeers) {
|
|
283
|
+
if (affected.reason === 'false-approval') {
|
|
284
|
+
// Weight: 40 as specified in ticket
|
|
285
|
+
this.reputation.reportPeer(affected.peerId, PenaltyReason.FalseApproval, `dispute:false-approval:${resolution.disputeId}`);
|
|
286
|
+
}
|
|
287
|
+
else if (affected.reason === 'dispute-lost') {
|
|
288
|
+
// Weight: 30 as specified in ticket
|
|
289
|
+
this.reputation.reportPeer(affected.peerId, PenaltyReason.DisputeLost, `dispute:dispute-lost:${resolution.disputeId}`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// If challenger wins, track engine health for majority peers
|
|
293
|
+
if (resolution.outcome === 'challenger-wins') {
|
|
294
|
+
const ourId = this.peerId.toString();
|
|
295
|
+
if (resolution.affectedPeers.some(p => p.peerId === ourId)) {
|
|
296
|
+
this.engineHealth.recordDisputeLoss();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
/** Broadcast resolution to all interested parties */
|
|
301
|
+
async broadcastResolution(resolution, arbitrators, originalPeers) {
|
|
302
|
+
const allTargets = new Set();
|
|
303
|
+
for (const arb of arbitrators)
|
|
304
|
+
allTargets.add(arb.toString());
|
|
305
|
+
for (const peer of originalPeers)
|
|
306
|
+
allTargets.add(peer);
|
|
307
|
+
// Don't send to self
|
|
308
|
+
allTargets.delete(this.peerId.toString());
|
|
309
|
+
const promises = Array.from(allTargets).map(async (peerIdStr) => {
|
|
310
|
+
try {
|
|
311
|
+
const { peerIdFromString } = await import('@libp2p/peer-id');
|
|
312
|
+
const client = this.createDisputeClient(peerIdFromString(peerIdStr));
|
|
313
|
+
await client.sendResolution(resolution);
|
|
314
|
+
}
|
|
315
|
+
catch (err) {
|
|
316
|
+
log('dispute-broadcast-failed', {
|
|
317
|
+
disputeId: resolution.disputeId,
|
|
318
|
+
peer: peerIdStr,
|
|
319
|
+
error: err instanceof Error ? err.message : String(err),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
await Promise.allSettled(promises);
|
|
324
|
+
}
|
|
325
|
+
async makeVote(disputeId, vote, evidence) {
|
|
326
|
+
const payload = `${disputeId}:${vote}:${evidence.computedHash}`;
|
|
327
|
+
const payloadBytes = new TextEncoder().encode(payload);
|
|
328
|
+
const sigBytes = await this.privateKey.sign(payloadBytes);
|
|
329
|
+
return {
|
|
330
|
+
disputeId,
|
|
331
|
+
arbitratorPeerId: this.peerId.toString(),
|
|
332
|
+
vote,
|
|
333
|
+
evidence,
|
|
334
|
+
signature: uint8ArrayToString(sigBytes, 'base64url'),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
async computeDisputeId(messageHash, peerId, timestamp) {
|
|
338
|
+
const input = `${messageHash}+${peerId}+${timestamp}`;
|
|
339
|
+
const inputBytes = new TextEncoder().encode(input);
|
|
340
|
+
const hashBytes = await sha256.digest(inputBytes);
|
|
341
|
+
return base58btc.encode(hashBytes.digest);
|
|
342
|
+
}
|
|
343
|
+
async signDispute(disputeId) {
|
|
344
|
+
const payload = new TextEncoder().encode(disputeId);
|
|
345
|
+
const sigBytes = await this.privateKey.sign(payload);
|
|
346
|
+
return uint8ArrayToString(sigBytes, 'base64url');
|
|
347
|
+
}
|
|
348
|
+
async verifyDisputeSignature(disputeId, signature, publicKey) {
|
|
349
|
+
if (!publicKey?.length)
|
|
350
|
+
return false;
|
|
351
|
+
try {
|
|
352
|
+
const pubKey = publicKeyFromRaw(publicKey);
|
|
353
|
+
const payload = new TextEncoder().encode(disputeId);
|
|
354
|
+
const sigBytes = uint8ArrayFromString(signature, 'base64url');
|
|
355
|
+
return pubKey.verify(payload, sigBytes);
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
findChallengeForDispute(disputeId) {
|
|
362
|
+
return this.activeDisputes.get(disputeId);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=dispute-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispute-service.js","sourceRoot":"","sources":["../../../src/dispute/dispute-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { EngineHealthState, DisputeConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks local engine health based on dispute outcomes.
|
|
4
|
+
* When the node repeatedly loses disputes (its validations are wrong),
|
|
5
|
+
* it flags itself as unhealthy and stops participating in promise voting.
|
|
6
|
+
*/
|
|
7
|
+
export declare class EngineHealthMonitor {
|
|
8
|
+
private state;
|
|
9
|
+
private readonly threshold;
|
|
10
|
+
private readonly windowMs;
|
|
11
|
+
constructor(config?: Partial<DisputeConfig>);
|
|
12
|
+
/** Record a dispute loss (our validation was wrong) */
|
|
13
|
+
recordDisputeLoss(): void;
|
|
14
|
+
/** Check if the engine is currently unhealthy */
|
|
15
|
+
isUnhealthy(): boolean;
|
|
16
|
+
/** Get the current health state */
|
|
17
|
+
getState(): Readonly<EngineHealthState>;
|
|
18
|
+
/** Reset health state (for testing or admin recovery) */
|
|
19
|
+
reset(): void;
|
|
20
|
+
private pruneOldLosses;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=engine-health-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-health-monitor.d.ts","sourceRoot":"","sources":["../../../src/dispute/engine-health-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMnE;;;;GAIG;AACH,qBAAa,mBAAmB;IAC/B,OAAO,CAAC,KAAK,CAIX;IAEF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAK3C,uDAAuD;IACvD,iBAAiB,IAAI,IAAI;IAuBzB,iDAAiD;IACjD,WAAW,IAAI,OAAO;IActB,mCAAmC;IACnC,QAAQ,IAAI,QAAQ,CAAC,iBAAiB,CAAC;IAKvC,yDAAyD;IACzD,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,cAAc;CAKtB"}
|