@optimystic/db-p2p 0.2.2 → 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 +34 -22
- 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 +48 -19
- 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,66 @@
|
|
|
1
|
+
import type { Startable } from '@libp2p/interface';
|
|
2
|
+
import type { IRepo, PeerId, IPeerNetwork } from '@optimystic/db-core';
|
|
3
|
+
import { ProtocolClient } from '../protocol-client.js';
|
|
4
|
+
export declare const buildBlockTransferProtocol: (protocolPrefix?: string) => string;
|
|
5
|
+
/** Request to transfer blocks */
|
|
6
|
+
export interface BlockTransferRequest {
|
|
7
|
+
type: 'pull' | 'push';
|
|
8
|
+
/** Block IDs being transferred */
|
|
9
|
+
blockIds: string[];
|
|
10
|
+
/** Reason for transfer */
|
|
11
|
+
reason: 'rebalance' | 'replication' | 'recovery';
|
|
12
|
+
/** For push: base64-encoded block data per block ID */
|
|
13
|
+
blockData?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
/** Response with block data */
|
|
16
|
+
export interface BlockTransferResponse {
|
|
17
|
+
/** Blocks successfully transferred: blockId → base64-encoded data */
|
|
18
|
+
blocks: Record<string, string>;
|
|
19
|
+
/** Block IDs that couldn't be found/transferred */
|
|
20
|
+
missing: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface BlockTransferServiceInit {
|
|
23
|
+
protocolPrefix?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface BlockTransferServiceComponents {
|
|
26
|
+
registrar: {
|
|
27
|
+
handle: (...args: any[]) => Promise<void>;
|
|
28
|
+
unhandle: (...args: any[]) => Promise<void>;
|
|
29
|
+
};
|
|
30
|
+
repo: IRepo;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Libp2p service that handles incoming block transfer requests.
|
|
34
|
+
*
|
|
35
|
+
* Responds to pull requests by reading blocks from local storage.
|
|
36
|
+
* Handles push requests by accepting block data and storing it locally.
|
|
37
|
+
*/
|
|
38
|
+
export declare class BlockTransferService implements Startable {
|
|
39
|
+
private readonly components;
|
|
40
|
+
private running;
|
|
41
|
+
private readonly protocol;
|
|
42
|
+
private readonly repo;
|
|
43
|
+
private readonly registrar;
|
|
44
|
+
constructor(components: BlockTransferServiceComponents, init?: BlockTransferServiceInit);
|
|
45
|
+
start(): Promise<void>;
|
|
46
|
+
stop(): Promise<void>;
|
|
47
|
+
private handleRequest;
|
|
48
|
+
private handlePull;
|
|
49
|
+
private handlePush;
|
|
50
|
+
private readRequest;
|
|
51
|
+
private sendResponse;
|
|
52
|
+
}
|
|
53
|
+
/** Factory for creating BlockTransferService following the libp2p service pattern. */
|
|
54
|
+
export declare const blockTransferService: (init?: BlockTransferServiceInit) => (components: BlockTransferServiceComponents) => BlockTransferService;
|
|
55
|
+
/**
|
|
56
|
+
* Client for sending block transfer requests to remote peers.
|
|
57
|
+
*/
|
|
58
|
+
export declare class BlockTransferClient extends ProtocolClient {
|
|
59
|
+
private readonly protocol;
|
|
60
|
+
constructor(peerId: PeerId, peerNetwork: IPeerNetwork, protocolPrefix?: string);
|
|
61
|
+
/** Pull blocks from the remote peer. */
|
|
62
|
+
pullBlocks(blockIds: string[], reason?: BlockTransferRequest['reason']): Promise<BlockTransferResponse>;
|
|
63
|
+
/** Push blocks to the remote peer. */
|
|
64
|
+
pushBlocks(blockIds: string[], blockDataBuffers: Uint8Array[], reason?: BlockTransferRequest['reason']): Promise<BlockTransferResponse>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=block-transfer-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-transfer-service.d.ts","sourceRoot":"","sources":["../../../src/cluster/block-transfer-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAU,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKvE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AASvD,eAAO,MAAM,0BAA0B,GAAI,iBAAgB,MAAW,KAAG,MACJ,CAAC;AAEtE,iCAAiC;AACjC,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,0BAA0B;IAC1B,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,UAAU,CAAC;IACjD,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,+BAA+B;AAC/B,MAAM,WAAW,qBAAqB;IACrC,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,mDAAmD;IACnD,OAAO,EAAE,MAAM,EAAE,CAAC;CAClB;AAID,MAAM,WAAW,wBAAwB;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,8BAA8B;IAC9C,SAAS,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAAC,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IACtG,IAAI,EAAE,KAAK,CAAC;CACZ;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,SAAS;IAOpD,OAAO,CAAC,QAAQ,CAAC,UAAU;IAN5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8C;gBAGtD,UAAU,EAAE,8BAA8B,EAC3D,IAAI,GAAE,wBAA6B;IAO9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAOb,aAAa;YA0Bb,UAAU;YAkBV,UAAU;YA2BV,WAAW;YAmBX,YAAY;CAO1B;AAED,sFAAsF;AACtF,eAAO,MAAM,oBAAoB,GAAI,OAAM,wBAA6B,MACtE,YAAY,8BAA8B,yBAA+C,CAAC;AAI5F;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,cAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAGjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,YAAY,EACzB,cAAc,GAAE,MAAW;IAM5B,wCAAwC;IAClC,UAAU,CACf,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,GAAE,oBAAoB,CAAC,QAAQ,CAAe,GAClD,OAAO,CAAC,qBAAqB,CAAC;IAKjC,sCAAsC;IAChC,UAAU,CACf,QAAQ,EAAE,MAAM,EAAE,EAClB,gBAAgB,EAAE,UAAU,EAAE,EAC9B,MAAM,GAAE,oBAAoB,CAAC,QAAQ,CAAe,GAClD,OAAO,CAAC,qBAAqB,CAAC;CAQjC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { pipe } from 'it-pipe';
|
|
2
|
+
import * as lp from 'it-length-prefixed';
|
|
3
|
+
import { fromString as u8FromString } from 'uint8arrays/from-string';
|
|
4
|
+
import { toString as u8ToString } from 'uint8arrays/to-string';
|
|
5
|
+
import { ProtocolClient } from '../protocol-client.js';
|
|
6
|
+
import { createLogger } from '../logger.js';
|
|
7
|
+
const log = createLogger('block-transfer-service');
|
|
8
|
+
/** Protocol path */
|
|
9
|
+
const BLOCK_TRANSFER_PREFIX = '/db-p2p/block-transfer/';
|
|
10
|
+
const BLOCK_TRANSFER_VERSION = '1.0.0';
|
|
11
|
+
export const buildBlockTransferProtocol = (protocolPrefix = '') => `${protocolPrefix}${BLOCK_TRANSFER_PREFIX}${BLOCK_TRANSFER_VERSION}`;
|
|
12
|
+
/**
|
|
13
|
+
* Libp2p service that handles incoming block transfer requests.
|
|
14
|
+
*
|
|
15
|
+
* Responds to pull requests by reading blocks from local storage.
|
|
16
|
+
* Handles push requests by accepting block data and storing it locally.
|
|
17
|
+
*/
|
|
18
|
+
export class BlockTransferService {
|
|
19
|
+
components;
|
|
20
|
+
running = false;
|
|
21
|
+
protocol;
|
|
22
|
+
repo;
|
|
23
|
+
registrar;
|
|
24
|
+
constructor(components, init = {}) {
|
|
25
|
+
this.components = components;
|
|
26
|
+
this.protocol = buildBlockTransferProtocol(init.protocolPrefix ?? '');
|
|
27
|
+
this.repo = components.repo;
|
|
28
|
+
this.registrar = components.registrar;
|
|
29
|
+
}
|
|
30
|
+
async start() {
|
|
31
|
+
if (this.running)
|
|
32
|
+
return;
|
|
33
|
+
await this.registrar.handle(this.protocol, async (data) => {
|
|
34
|
+
await this.handleRequest(data.stream);
|
|
35
|
+
});
|
|
36
|
+
this.running = true;
|
|
37
|
+
log('started on %s', this.protocol);
|
|
38
|
+
}
|
|
39
|
+
async stop() {
|
|
40
|
+
if (!this.running)
|
|
41
|
+
return;
|
|
42
|
+
await this.registrar.unhandle(this.protocol);
|
|
43
|
+
this.running = false;
|
|
44
|
+
log('stopped');
|
|
45
|
+
}
|
|
46
|
+
async handleRequest(stream) {
|
|
47
|
+
try {
|
|
48
|
+
const request = await this.readRequest(stream);
|
|
49
|
+
log('request type=%s blocks=%d reason=%s', request.type, request.blockIds.length, request.reason);
|
|
50
|
+
let response;
|
|
51
|
+
if (request.type === 'pull') {
|
|
52
|
+
response = await this.handlePull(request);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
response = await this.handlePush(request);
|
|
56
|
+
}
|
|
57
|
+
await this.sendResponse(stream, response);
|
|
58
|
+
log('response blocks=%d missing=%d', Object.keys(response.blocks).length, response.missing.length);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
log('error: %s', error.message);
|
|
62
|
+
try {
|
|
63
|
+
await this.sendResponse(stream, { blocks: {}, missing: [] });
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// ignore send errors
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
try {
|
|
71
|
+
await stream.close();
|
|
72
|
+
}
|
|
73
|
+
catch { /* ignore */ }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async handlePull(request) {
|
|
77
|
+
const blocks = {};
|
|
78
|
+
const missing = [];
|
|
79
|
+
const result = await this.repo.get({ blockIds: request.blockIds });
|
|
80
|
+
for (const blockId of request.blockIds) {
|
|
81
|
+
const blockResult = result[blockId];
|
|
82
|
+
if (blockResult?.block) {
|
|
83
|
+
blocks[blockId] = Buffer.from(JSON.stringify(blockResult.block)).toString('base64');
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
missing.push(blockId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { blocks, missing };
|
|
90
|
+
}
|
|
91
|
+
async handlePush(request) {
|
|
92
|
+
const blocks = {};
|
|
93
|
+
const missing = [];
|
|
94
|
+
if (!request.blockData) {
|
|
95
|
+
return { blocks: {}, missing: request.blockIds };
|
|
96
|
+
}
|
|
97
|
+
// Accept pushed blocks — for each block, check if we already have it (idempotent)
|
|
98
|
+
for (const blockId of request.blockIds) {
|
|
99
|
+
const data = request.blockData[blockId];
|
|
100
|
+
if (data) {
|
|
101
|
+
// Verify we received valid data
|
|
102
|
+
try {
|
|
103
|
+
JSON.parse(Buffer.from(data, 'base64').toString('utf8'));
|
|
104
|
+
blocks[blockId] = data;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
missing.push(blockId);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
missing.push(blockId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { blocks, missing };
|
|
115
|
+
}
|
|
116
|
+
async readRequest(stream) {
|
|
117
|
+
const messages = [];
|
|
118
|
+
await pipe(stream, lp.decode, async (source) => {
|
|
119
|
+
for await (const msg of source) {
|
|
120
|
+
messages.push(msg.subarray());
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
if (messages.length === 0) {
|
|
124
|
+
throw new Error('No request received');
|
|
125
|
+
}
|
|
126
|
+
return JSON.parse(u8ToString(messages[0], 'utf8'));
|
|
127
|
+
}
|
|
128
|
+
async sendResponse(stream, response) {
|
|
129
|
+
const bytes = u8FromString(JSON.stringify(response), 'utf8');
|
|
130
|
+
const encoded = pipe([bytes], lp.encode);
|
|
131
|
+
for await (const chunk of encoded) {
|
|
132
|
+
stream.send(chunk);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/** Factory for creating BlockTransferService following the libp2p service pattern. */
|
|
137
|
+
export const blockTransferService = (init = {}) => (components) => new BlockTransferService(components, init);
|
|
138
|
+
// --- Client ---
|
|
139
|
+
/**
|
|
140
|
+
* Client for sending block transfer requests to remote peers.
|
|
141
|
+
*/
|
|
142
|
+
export class BlockTransferClient extends ProtocolClient {
|
|
143
|
+
protocol;
|
|
144
|
+
constructor(peerId, peerNetwork, protocolPrefix = '') {
|
|
145
|
+
super(peerId, peerNetwork);
|
|
146
|
+
this.protocol = buildBlockTransferProtocol(protocolPrefix);
|
|
147
|
+
}
|
|
148
|
+
/** Pull blocks from the remote peer. */
|
|
149
|
+
async pullBlocks(blockIds, reason = 'rebalance') {
|
|
150
|
+
const request = { type: 'pull', blockIds, reason };
|
|
151
|
+
return await this.processMessage(request, this.protocol);
|
|
152
|
+
}
|
|
153
|
+
/** Push blocks to the remote peer. */
|
|
154
|
+
async pushBlocks(blockIds, blockDataBuffers, reason = 'rebalance') {
|
|
155
|
+
const blockData = {};
|
|
156
|
+
for (let i = 0; i < blockIds.length; i++) {
|
|
157
|
+
blockData[blockIds[i]] = Buffer.from(blockDataBuffers[i]).toString('base64');
|
|
158
|
+
}
|
|
159
|
+
const request = { type: 'push', blockIds, reason, blockData };
|
|
160
|
+
return await this.processMessage(request, this.protocol);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=block-transfer-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-transfer-service.js","sourceRoot":"","sources":["../../../src/cluster/block-transfer-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { IRepo } from '@optimystic/db-core';
|
|
2
|
+
import type { IPeerNetwork } from '@optimystic/db-core';
|
|
3
|
+
import type { PartitionDetector } from './partition-detector.js';
|
|
4
|
+
import type { RestorationCoordinator } from '../storage/restoration-coordinator-v2.js';
|
|
5
|
+
/**
|
|
6
|
+
* Rebalance event describing gained/lost block responsibilities.
|
|
7
|
+
* Matches the RebalanceMonitor spec from the sibling ticket.
|
|
8
|
+
*/
|
|
9
|
+
export interface RebalanceEvent {
|
|
10
|
+
/** Block IDs this node has gained responsibility for */
|
|
11
|
+
gained: string[];
|
|
12
|
+
/** Block IDs this node has lost responsibility for */
|
|
13
|
+
lost: string[];
|
|
14
|
+
/** Peers that are now closer for the lost blocks: blockId → peerId[] */
|
|
15
|
+
newOwners: Map<string, string[]>;
|
|
16
|
+
/** Timestamp of the topology change that triggered this */
|
|
17
|
+
triggeredAt: number;
|
|
18
|
+
}
|
|
19
|
+
export interface BlockTransferConfig {
|
|
20
|
+
/** Max concurrent transfers. Default: 4 */
|
|
21
|
+
maxConcurrency?: number;
|
|
22
|
+
/** Timeout per block transfer (ms). Default: 30000 */
|
|
23
|
+
transferTimeoutMs?: number;
|
|
24
|
+
/** Retry attempts for failed transfers. Default: 2 */
|
|
25
|
+
maxRetries?: number;
|
|
26
|
+
/** Whether to push blocks to new owners proactively. Default: true */
|
|
27
|
+
enablePush?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Coordinates block transfers in response to rebalance events.
|
|
31
|
+
*
|
|
32
|
+
* For gained blocks: delegates to RestorationCoordinator.restore() which
|
|
33
|
+
* already handles ring-based discovery and fetching.
|
|
34
|
+
*
|
|
35
|
+
* For lost blocks: proactively pushes block data to new responsible peers
|
|
36
|
+
* via the BlockTransfer protocol.
|
|
37
|
+
*/
|
|
38
|
+
export declare class BlockTransferCoordinator {
|
|
39
|
+
private readonly repo;
|
|
40
|
+
private readonly peerNetwork;
|
|
41
|
+
private readonly restorationCoordinator;
|
|
42
|
+
private readonly partitionDetector;
|
|
43
|
+
private readonly protocolPrefix;
|
|
44
|
+
private readonly maxConcurrency;
|
|
45
|
+
private readonly transferTimeoutMs;
|
|
46
|
+
private readonly maxRetries;
|
|
47
|
+
private readonly enablePush;
|
|
48
|
+
private inFlight;
|
|
49
|
+
private concurrency;
|
|
50
|
+
private readonly waitQueue;
|
|
51
|
+
constructor(repo: IRepo, peerNetwork: IPeerNetwork, restorationCoordinator: RestorationCoordinator, partitionDetector: PartitionDetector, protocolPrefix?: string, config?: BlockTransferConfig);
|
|
52
|
+
/**
|
|
53
|
+
* Pull blocks that this node has gained responsibility for.
|
|
54
|
+
* Uses RestorationCoordinator to discover holders and fetch block data.
|
|
55
|
+
*/
|
|
56
|
+
pullBlocks(blockIds: string[]): Promise<{
|
|
57
|
+
succeeded: string[];
|
|
58
|
+
failed: string[];
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Push blocks that this node has lost responsibility for to new owners.
|
|
62
|
+
*/
|
|
63
|
+
pushBlocks(blockIds: string[], newOwners: Map<string, string[]>): Promise<{
|
|
64
|
+
succeeded: string[];
|
|
65
|
+
failed: string[];
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Handle a complete rebalance event — pull gained, push lost.
|
|
69
|
+
*/
|
|
70
|
+
handleRebalanceEvent(event: RebalanceEvent): Promise<void>;
|
|
71
|
+
private executePull;
|
|
72
|
+
private executePush;
|
|
73
|
+
private acquireSemaphore;
|
|
74
|
+
private releaseSemaphore;
|
|
75
|
+
private backoffMs;
|
|
76
|
+
private delay;
|
|
77
|
+
private withTimeout;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=block-transfer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-transfer.d.ts","sourceRoot":"","sources":["../../../src/cluster/block-transfer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAMvF;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,wDAAwD;IACxD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sDAAsD;IACtD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,wEAAwE;IACxE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACjC,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IACnC,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAOD;;;;;;;;GAQG;AACH,qBAAa,wBAAwB;IAUnC,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAbhC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;gBAGjC,IAAI,EAAE,KAAK,EACX,WAAW,EAAE,YAAY,EACzB,sBAAsB,EAAE,sBAAsB,EAC9C,iBAAiB,EAAE,iBAAiB,EACpC,cAAc,GAAE,MAAW,EAC5C,MAAM,GAAE,mBAAwB;IAQjC;;;OAGG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAkBxF;;OAEG;IACG,UAAU,CACf,QAAQ,EAAE,MAAM,EAAE,EAClB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAC9B,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAqBrD;;OAEG;IACG,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;YAelD,WAAW;YAsCX,WAAW;YA0EX,gBAAgB;IAS9B,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,WAAW;CAMnB"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { peerIdFromString } from '@libp2p/peer-id';
|
|
2
|
+
import { BlockTransferClient } from './block-transfer-service.js';
|
|
3
|
+
import { createLogger } from '../logger.js';
|
|
4
|
+
const log = createLogger('block-transfer');
|
|
5
|
+
/**
|
|
6
|
+
* Coordinates block transfers in response to rebalance events.
|
|
7
|
+
*
|
|
8
|
+
* For gained blocks: delegates to RestorationCoordinator.restore() which
|
|
9
|
+
* already handles ring-based discovery and fetching.
|
|
10
|
+
*
|
|
11
|
+
* For lost blocks: proactively pushes block data to new responsible peers
|
|
12
|
+
* via the BlockTransfer protocol.
|
|
13
|
+
*/
|
|
14
|
+
export class BlockTransferCoordinator {
|
|
15
|
+
repo;
|
|
16
|
+
peerNetwork;
|
|
17
|
+
restorationCoordinator;
|
|
18
|
+
partitionDetector;
|
|
19
|
+
protocolPrefix;
|
|
20
|
+
maxConcurrency;
|
|
21
|
+
transferTimeoutMs;
|
|
22
|
+
maxRetries;
|
|
23
|
+
enablePush;
|
|
24
|
+
inFlight = new Set();
|
|
25
|
+
concurrency = 0;
|
|
26
|
+
waitQueue = [];
|
|
27
|
+
constructor(repo, peerNetwork, restorationCoordinator, partitionDetector, protocolPrefix = '', config = {}) {
|
|
28
|
+
this.repo = repo;
|
|
29
|
+
this.peerNetwork = peerNetwork;
|
|
30
|
+
this.restorationCoordinator = restorationCoordinator;
|
|
31
|
+
this.partitionDetector = partitionDetector;
|
|
32
|
+
this.protocolPrefix = protocolPrefix;
|
|
33
|
+
this.maxConcurrency = config.maxConcurrency ?? 4;
|
|
34
|
+
this.transferTimeoutMs = config.transferTimeoutMs ?? 30000;
|
|
35
|
+
this.maxRetries = config.maxRetries ?? 2;
|
|
36
|
+
this.enablePush = config.enablePush ?? true;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Pull blocks that this node has gained responsibility for.
|
|
40
|
+
* Uses RestorationCoordinator to discover holders and fetch block data.
|
|
41
|
+
*/
|
|
42
|
+
async pullBlocks(blockIds) {
|
|
43
|
+
if (this.partitionDetector.detectPartition()) {
|
|
44
|
+
log('pull:partition-detected, skipping %d blocks', blockIds.length);
|
|
45
|
+
return { succeeded: [], failed: blockIds };
|
|
46
|
+
}
|
|
47
|
+
const succeeded = [];
|
|
48
|
+
const failed = [];
|
|
49
|
+
const tasks = blockIds
|
|
50
|
+
.filter(id => !this.inFlight.has(`pull:${id}`))
|
|
51
|
+
.map(id => ({ blockId: id, attempt: 0 }));
|
|
52
|
+
await Promise.all(tasks.map(task => this.executePull(task, succeeded, failed)));
|
|
53
|
+
return { succeeded, failed };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Push blocks that this node has lost responsibility for to new owners.
|
|
57
|
+
*/
|
|
58
|
+
async pushBlocks(blockIds, newOwners) {
|
|
59
|
+
if (!this.enablePush) {
|
|
60
|
+
return { succeeded: [], failed: [] };
|
|
61
|
+
}
|
|
62
|
+
if (this.partitionDetector.detectPartition()) {
|
|
63
|
+
log('push:partition-detected, skipping %d blocks', blockIds.length);
|
|
64
|
+
return { succeeded: [], failed: blockIds };
|
|
65
|
+
}
|
|
66
|
+
const succeeded = [];
|
|
67
|
+
const failed = [];
|
|
68
|
+
const tasks = blockIds
|
|
69
|
+
.filter(id => !this.inFlight.has(`push:${id}`) && newOwners.has(id))
|
|
70
|
+
.map(id => ({ blockId: id, attempt: 0 }));
|
|
71
|
+
await Promise.all(tasks.map(task => this.executePush(task, newOwners, succeeded, failed)));
|
|
72
|
+
return { succeeded, failed };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Handle a complete rebalance event — pull gained, push lost.
|
|
76
|
+
*/
|
|
77
|
+
async handleRebalanceEvent(event) {
|
|
78
|
+
log('rebalance:start gained=%d lost=%d', event.gained.length, event.lost.length);
|
|
79
|
+
const [pullResult, pushResult] = await Promise.all([
|
|
80
|
+
event.gained.length > 0 ? this.pullBlocks(event.gained) : { succeeded: [], failed: [] },
|
|
81
|
+
event.lost.length > 0 && event.newOwners.size > 0
|
|
82
|
+
? this.pushBlocks(event.lost, event.newOwners)
|
|
83
|
+
: { succeeded: [], failed: [] }
|
|
84
|
+
]);
|
|
85
|
+
log('rebalance:done pull=%d/%d push=%d/%d', pullResult.succeeded.length, event.gained.length, pushResult.succeeded.length, event.lost.length);
|
|
86
|
+
}
|
|
87
|
+
async executePull(task, succeeded, failed) {
|
|
88
|
+
const key = `pull:${task.blockId}`;
|
|
89
|
+
if (this.inFlight.has(key))
|
|
90
|
+
return;
|
|
91
|
+
this.inFlight.add(key);
|
|
92
|
+
try {
|
|
93
|
+
await this.acquireSemaphore();
|
|
94
|
+
try {
|
|
95
|
+
const archive = await this.withTimeout(this.restorationCoordinator.restore(task.blockId), this.transferTimeoutMs);
|
|
96
|
+
if (archive) {
|
|
97
|
+
log('pull:ok block=%s', task.blockId);
|
|
98
|
+
succeeded.push(task.blockId);
|
|
99
|
+
}
|
|
100
|
+
else if (task.attempt < this.maxRetries) {
|
|
101
|
+
log('pull:retry block=%s attempt=%d', task.blockId, task.attempt + 1);
|
|
102
|
+
this.inFlight.delete(key);
|
|
103
|
+
await this.delay(this.backoffMs(task.attempt));
|
|
104
|
+
await this.executePull({ ...task, attempt: task.attempt + 1 }, succeeded, failed);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
log('pull:failed block=%s', task.blockId);
|
|
109
|
+
failed.push(task.blockId);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
this.releaseSemaphore();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
this.inFlight.delete(key);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async executePush(task, newOwners, succeeded, failed) {
|
|
121
|
+
const key = `push:${task.blockId}`;
|
|
122
|
+
if (this.inFlight.has(key))
|
|
123
|
+
return;
|
|
124
|
+
this.inFlight.add(key);
|
|
125
|
+
try {
|
|
126
|
+
await this.acquireSemaphore();
|
|
127
|
+
try {
|
|
128
|
+
const owners = newOwners.get(task.blockId);
|
|
129
|
+
if (!owners || owners.length === 0) {
|
|
130
|
+
failed.push(task.blockId);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// Read block data from local storage
|
|
134
|
+
const result = await this.repo.get({ blockIds: [task.blockId] });
|
|
135
|
+
const blockResult = result[task.blockId];
|
|
136
|
+
if (!blockResult?.block) {
|
|
137
|
+
log('push:no-local-data block=%s', task.blockId);
|
|
138
|
+
failed.push(task.blockId);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const blockData = new TextEncoder().encode(JSON.stringify(blockResult.block));
|
|
142
|
+
// Push to at least one new owner
|
|
143
|
+
let pushed = false;
|
|
144
|
+
for (const ownerPeerIdStr of owners) {
|
|
145
|
+
try {
|
|
146
|
+
const peerId = peerIdFromString(ownerPeerIdStr);
|
|
147
|
+
const client = new BlockTransferClient(peerId, this.peerNetwork, this.protocolPrefix);
|
|
148
|
+
const response = await this.withTimeout(client.pushBlocks([task.blockId], [blockData]), this.transferTimeoutMs);
|
|
149
|
+
if (response && !response.missing.includes(task.blockId)) {
|
|
150
|
+
pushed = true;
|
|
151
|
+
log('push:ok block=%s peer=%s', task.blockId, ownerPeerIdStr);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
log('push:peer-error block=%s peer=%s err=%s', task.blockId, ownerPeerIdStr, err.message);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (pushed) {
|
|
160
|
+
succeeded.push(task.blockId);
|
|
161
|
+
}
|
|
162
|
+
else if (task.attempt < this.maxRetries) {
|
|
163
|
+
log('push:retry block=%s attempt=%d', task.blockId, task.attempt + 1);
|
|
164
|
+
this.inFlight.delete(key);
|
|
165
|
+
await this.delay(this.backoffMs(task.attempt));
|
|
166
|
+
await this.executePush({ ...task, attempt: task.attempt + 1 }, newOwners, succeeded, failed);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
log('push:failed block=%s', task.blockId);
|
|
171
|
+
failed.push(task.blockId);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
this.releaseSemaphore();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
this.inFlight.delete(key);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// --- Semaphore for concurrency limiting ---
|
|
183
|
+
async acquireSemaphore() {
|
|
184
|
+
if (this.concurrency < this.maxConcurrency) {
|
|
185
|
+
this.concurrency++;
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
await new Promise(resolve => this.waitQueue.push(resolve));
|
|
189
|
+
this.concurrency++;
|
|
190
|
+
}
|
|
191
|
+
releaseSemaphore() {
|
|
192
|
+
this.concurrency--;
|
|
193
|
+
const next = this.waitQueue.shift();
|
|
194
|
+
if (next)
|
|
195
|
+
next();
|
|
196
|
+
}
|
|
197
|
+
// --- Helpers ---
|
|
198
|
+
backoffMs(attempt) {
|
|
199
|
+
return Math.min(1000 * Math.pow(2, attempt), 10000);
|
|
200
|
+
}
|
|
201
|
+
delay(ms) {
|
|
202
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
203
|
+
}
|
|
204
|
+
withTimeout(promise, ms) {
|
|
205
|
+
return Promise.race([
|
|
206
|
+
promise,
|
|
207
|
+
new Promise(resolve => setTimeout(() => resolve(undefined), ms))
|
|
208
|
+
]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=block-transfer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-transfer.js","sourceRoot":"","sources":["../../../src/cluster/block-transfer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import type { IRepo, ClusterRecord, ITransactionValidator } from "@optimystic/db-core";
|
|
1
|
+
import type { IRepo, ClusterRecord, ITransactionValidator, ClusterConsensusConfig } from "@optimystic/db-core";
|
|
2
2
|
import type { ICluster } from "@optimystic/db-core";
|
|
3
3
|
import type { IPeerNetwork } from "@optimystic/db-core";
|
|
4
|
-
import type { PeerId } from "@libp2p/interface";
|
|
4
|
+
import type { PeerId, PrivateKey } from "@libp2p/interface";
|
|
5
5
|
import type { PartitionDetector } from "./partition-detector.js";
|
|
6
6
|
import type { FretService } from "p2p-fret";
|
|
7
|
+
import type { IPeerReputation } from "../reputation/types.js";
|
|
7
8
|
interface ClusterMemberComponents {
|
|
8
9
|
storageRepo: IRepo;
|
|
9
10
|
peerNetwork: IPeerNetwork;
|
|
10
11
|
peerId: PeerId;
|
|
12
|
+
privateKey: PrivateKey;
|
|
11
13
|
protocolPrefix?: string;
|
|
12
14
|
partitionDetector?: PartitionDetector;
|
|
13
15
|
fretService?: FretService;
|
|
14
16
|
validator?: ITransactionValidator;
|
|
17
|
+
reputation?: IPeerReputation;
|
|
18
|
+
consensusConfig?: ClusterConsensusConfig;
|
|
15
19
|
}
|
|
16
20
|
export declare function clusterMember(components: ClusterMemberComponents): ClusterMember;
|
|
17
21
|
/**
|
|
@@ -22,15 +26,20 @@ export declare class ClusterMember implements ICluster {
|
|
|
22
26
|
private readonly storageRepo;
|
|
23
27
|
private readonly peerNetwork;
|
|
24
28
|
private readonly peerId;
|
|
29
|
+
private readonly privateKey;
|
|
25
30
|
private readonly protocolPrefix?;
|
|
26
31
|
private readonly partitionDetector?;
|
|
27
32
|
private readonly fretService?;
|
|
28
33
|
private readonly validator?;
|
|
34
|
+
private readonly reputation?;
|
|
29
35
|
private activeTransactions;
|
|
30
36
|
private executedTransactions;
|
|
31
37
|
private cleanupQueue;
|
|
32
38
|
private pendingUpdates;
|
|
33
|
-
|
|
39
|
+
private currentValidationRecord?;
|
|
40
|
+
/** Effective super-majority threshold. Defaults to 1.0 (unanimity) for backward compatibility. */
|
|
41
|
+
private readonly superMajorityThreshold;
|
|
42
|
+
constructor(storageRepo: IRepo, peerNetwork: IPeerNetwork, peerId: PeerId, privateKey: PrivateKey, protocolPrefix?: string | undefined, partitionDetector?: PartitionDetector | undefined, fretService?: FretService | undefined, validator?: ITransactionValidator | undefined, reputation?: IPeerReputation | undefined, consensusConfig?: ClusterConsensusConfig);
|
|
34
43
|
/**
|
|
35
44
|
* Checks if a transaction's operations were already executed during consensus.
|
|
36
45
|
* Used by the coordinator to avoid duplicate execution in CoordinatorRepo.
|
|
@@ -55,6 +64,8 @@ export declare class ClusterMember implements ICluster {
|
|
|
55
64
|
private validateSignatures;
|
|
56
65
|
private computePromiseHash;
|
|
57
66
|
private computeCommitHash;
|
|
67
|
+
private computeSigningPayload;
|
|
68
|
+
private signVote;
|
|
58
69
|
private verifySignature;
|
|
59
70
|
private getTransactionPhase;
|
|
60
71
|
private hasMajority;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cluster-repo.d.ts","sourceRoot":"","sources":["../../../src/cluster/cluster-repo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAA0B,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"cluster-repo.d.ts","sourceRoot":"","sources":["../../../src/cluster/cluster-repo.ts"],"names":[],"mappings":"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"}
|