UNPKG

25.5 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const client_common_1 = require("@neo-one/client-common");
4const logger_1 = require("@neo-one/logger");
5const utils_1 = require("@neo-one/utils");
6const asynciterablex_1 = require("@reactivex/ix-es2015-cjs/asynciterable/asynciterablex");
7const scan_1 = require("@reactivex/ix-es2015-cjs/asynciterable/pipe/scan");
8const common_1 = require("./common");
9const ConsensusContext_1 = require("./ConsensusContext");
10const ConsensusQueue_1 = require("./ConsensusQueue");
11const handleConsensusPayload_1 = require("./handleConsensusPayload");
12const handlePersistBlock_1 = require("./handlePersistBlock");
13const handleTransactionReceived_1 = require("./handleTransactionReceived");
14const runConsensus_1 = require("./runConsensus");
15const logger = logger_1.createChild(logger_1.nodeLogger, { component: 'consensus' });
16const MS_IN_SECOND = 1000;
17class Consensus {
18 constructor({ options, node }) {
19 this.mutableQueue = new ConsensusQueue_1.ConsensusQueue();
20 const privateKey = client_common_1.common.stringToPrivateKey(options.privateKey);
21 const publicKey = client_common_1.crypto.privateKeyToPublicKey(privateKey);
22 const feeAddress = client_common_1.crypto.publicKeyToScriptHash(publicKey);
23 this.options = {
24 privateKey,
25 publicKey,
26 feeAddress,
27 privateNet: options.privateNet,
28 };
29 this.node = node;
30 this.mutableConsensusContext = new ConsensusContext_1.ConsensusContext();
31 }
32 async start() {
33 let disposable = utils_1.noopDisposable;
34 try {
35 await this.pause();
36 this.doStart(this.options);
37 disposable = utils_1.composeDisposables(disposable, async () => {
38 await this.pause();
39 });
40 return disposable;
41 }
42 catch (err) {
43 await disposable();
44 throw err;
45 }
46 }
47 onPersistBlock() {
48 this.mutableQueue.write({ type: 'handlePersistBlock' });
49 }
50 onConsensusPayloadReceived(payload) {
51 this.mutableQueue.write({
52 type: 'handleConsensusPayload',
53 payload,
54 });
55 }
56 onTransactionReceived(transaction) {
57 this.mutableQueue.write({
58 type: 'handleTransactionReceived',
59 transaction,
60 });
61 }
62 async runConsensusNow() {
63 if (this.options.privateNet) {
64 await new Promise((resolve, reject) => {
65 this.mutableQueue.write({ type: 'timer', promise: { resolve, reject } });
66 });
67 }
68 else {
69 throw new Error('Can only force consensus on a private network.');
70 }
71 }
72 nowSeconds() {
73 return this.mutableConsensusContext.nowSeconds();
74 }
75 async fastForwardOffset(seconds) {
76 if (this.options.privateNet) {
77 this.mutableConsensusContext.fastForwardOffset(seconds);
78 }
79 else {
80 throw new Error('Can only fast forward on a private network.');
81 }
82 }
83 async fastForwardToTime(seconds) {
84 if (this.options.privateNet) {
85 this.mutableConsensusContext.fastForwardToTime(seconds);
86 }
87 else {
88 throw new Error('Can only fast forward on a private network.');
89 }
90 }
91 async pause() {
92 this.clearTimer();
93 this.mutableQueue.done();
94 this.mutableQueue = new ConsensusQueue_1.ConsensusQueue();
95 if (this.mutableStartPromise !== undefined) {
96 await this.mutableStartPromise;
97 }
98 }
99 async reset() {
100 this.mutableConsensusContext = new ConsensusContext_1.ConsensusContext();
101 }
102 async resume() {
103 this.doStart(this.options);
104 }
105 doStart(options) {
106 let completed = false;
107 const mutableStartPromise = this.startInternal(options).then(() => {
108 completed = true;
109 this.mutableStartPromise = undefined;
110 });
111 if (!completed) {
112 this.mutableStartPromise = mutableStartPromise;
113 }
114 }
115 async startInternal(options) {
116 logger.info({ name: 'neo_consensus_start' }, 'Consensus started.');
117 const initialResult = await common_1.initializeNewConsensus({
118 blockchain: this.node.blockchain,
119 publicKey: options.publicKey,
120 consensusContext: this.mutableConsensusContext,
121 });
122 await asynciterablex_1.AsyncIterableX.from(this.mutableQueue)
123 .pipe(scan_1.scan(async (context, event) => {
124 let result;
125 switch (event.type) {
126 case 'handlePersistBlock':
127 result = await handlePersistBlock_1.handlePersistBlock({
128 blockchain: this.node.blockchain,
129 publicKey: options.publicKey,
130 consensusContext: this.mutableConsensusContext,
131 });
132 break;
133 case 'handleConsensusPayload':
134 result = await handleConsensusPayload_1.handleConsensusPayload({
135 context,
136 node: this.node,
137 privateKey: options.privateKey,
138 payload: event.payload,
139 consensusContext: this.mutableConsensusContext,
140 });
141 break;
142 case 'handleTransactionReceived':
143 result = await handleTransactionReceived_1.handleTransactionReceived({
144 context,
145 node: this.node,
146 privateKey: options.privateKey,
147 transaction: event.transaction,
148 consensusContext: this.mutableConsensusContext,
149 });
150 break;
151 case 'timer':
152 result = await runConsensus_1.runConsensus({
153 context,
154 node: this.node,
155 options,
156 consensusContext: this.mutableConsensusContext,
157 }).catch((err) => {
158 if (event.promise !== undefined) {
159 event.promise.reject(err);
160 }
161 throw err;
162 });
163 if (event.promise !== undefined) {
164 event.promise.resolve();
165 }
166 break;
167 default:
168 utils_1.utils.assertNever(event);
169 throw new Error('For TS');
170 }
171 return this.handleResult(result);
172 }, this.handleResult(initialResult)))
173 .forEach(() => {
174 });
175 logger.info({ name: 'neo_consensus_stop' }, 'Consensus stopped.');
176 }
177 handleResult(result) {
178 if (result.timerSeconds !== undefined) {
179 this.handleTimer(result.timerSeconds);
180 }
181 return result.context;
182 }
183 handleTimer(mutableTimerSeconds) {
184 this.clearTimer();
185 this.mutableTimer = setTimeout(() => this.mutableQueue.write({ type: 'timer' }), mutableTimerSeconds * MS_IN_SECOND);
186 }
187 clearTimer() {
188 if (this.mutableTimer !== undefined) {
189 clearTimeout(this.mutableTimer);
190 this.mutableTimer = undefined;
191 }
192 }
193}
194exports.Consensus = Consensus;
195
196//# sourceMappingURL=data:application/json;charset=utf8;base64,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LEtBQUssQ0FBQyxDQUFDO29CQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQzdCO1lBRUQsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ25DLENBQUMsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQ3JDO2FBQ0EsT0FBTyxDQUFDLEdBQUcsRUFBRTtRQUVkLENBQUMsQ0FBQyxDQUFDO1FBRUwsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxvQkFBb0IsRUFBRSxFQUFFLG9CQUFvQixDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUVPLFlBQVksQ0FBQyxNQUF1QjtRQUMxQyxJQUFJLE1BQU0sQ0FBQyxZQUFZLEtBQUssU0FBUyxFQUFFO1lBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO1NBQ3ZDO1FBRUQsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDO0lBQ3hCLENBQUM7SUFFTyxXQUFXLENBQUMsbUJBQTJCO1FBQzdDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsWUFBWSxHQUFHLFVBQVUsQ0FDNUIsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFDaEQsbUJBQW1CLEdBQUcsWUFBWSxDQUU1QixDQUFDO0lBQ1gsQ0FBQztJQUVPLFVBQVU7UUFDaEIsSUFBSSxJQUFJLENBQUMsWUFBWSxLQUFLLFNBQVMsRUFBRTtZQUNuQyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2hDLElBQUksQ0FBQyxZQUFZLEdBQUcsU0FBUyxDQUFDO1NBQy9CO0lBQ0gsQ0FBQztDQUNGO0FBeE5ELDhCQXdOQyIsImZpbGUiOiJuZW8tb25lLW5vZGUtY29uc2Vuc3VzL3NyYy9Db25zZW5zdXMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLy8gPHJlZmVyZW5jZSB0eXBlcz1cIkByZWFjdGl2ZXgvaXgtZXMyMDE1LWNqc1wiIC8+XG5pbXBvcnQgeyBjb21tb24sIGNyeXB0bywgRUNQb2ludCwgUHJpdmF0ZUtleSwgVUludDE2MCB9IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb21tb24nO1xuaW1wb3J0IHsgY3JlYXRlQ2hpbGQsIG5vZGVMb2dnZXIgfSBmcm9tICdAbmVvLW9uZS9sb2dnZXInO1xuaW1wb3J0IHsgQ29uc2Vuc3VzUGF5bG9hZCwgTm9kZSwgVHJhbnNhY3Rpb24gfSBmcm9tICdAbmVvLW9uZS9ub2RlLWNvcmUnO1xuaW1wb3J0IHsgY29tcG9zZURpc3Bvc2FibGVzLCBEaXNwb3NhYmxlLCBub29wRGlzcG9zYWJsZSwgdXRpbHMgYXMgY29tbW9uVXRpbHMgfSBmcm9tICdAbmVvLW9uZS91dGlscyc7XG5pbXBvcnQgeyBBc3luY0l0ZXJhYmxlWCB9IGZyb20gJ0ByZWFjdGl2ZXgvaXgtZXMyMDE1LWNqcy9hc3luY2l0ZXJhYmxlL2FzeW5jaXRlcmFibGV4JztcbmltcG9ydCB7IHNjYW4gfSBmcm9tICdAcmVhY3RpdmV4L2l4LWVzMjAxNS1janMvYXN5bmNpdGVyYWJsZS9waXBlL3NjYW4nO1xuaW1wb3J0IHsgaW5pdGlhbGl6ZU5ld0NvbnNlbnN1cyB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IENvbnNlbnN1c0NvbnRleHQgfSBmcm9tICcuL0NvbnNlbnN1c0NvbnRleHQnO1xuaW1wb3J0IHsgQ29uc2Vuc3VzUXVldWUgfSBmcm9tICcuL0NvbnNlbnN1c1F1ZXVlJztcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tICcuL2NvbnRleHQnO1xuaW1wb3J0IHsgaGFuZGxlQ29uc2Vuc3VzUGF5bG9hZCB9IGZyb20gJy4vaGFuZGxlQ29uc2Vuc3VzUGF5bG9hZCc7XG5pbXBvcnQgeyBoYW5kbGVQZXJzaXN0QmxvY2sgfSBmcm9tICcuL2hhbmRsZVBlcnNpc3RCbG9jayc7XG5pbXBvcnQgeyBoYW5kbGVUcmFuc2FjdGlvblJlY2VpdmVkIH0gZnJvbSAnLi9oYW5kbGVUcmFuc2FjdGlvblJlY2VpdmVkJztcbmltcG9ydCB7IHJ1bkNvbnNlbnN1cyB9IGZyb20gJy4vcnVuQ29uc2Vuc3VzJztcbmltcG9ydCB7IEV2ZW50LCBSZXN1bHQgfSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlQ2hpbGQobm9kZUxvZ2dlciwgeyBjb21wb25lbnQ6ICdjb25zZW5zdXMnIH0pO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9wdGlvbnMge1xuICByZWFkb25seSBwcml2YXRlS2V5OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHByaXZhdGVOZXQ6IGJvb2xlYW47XG59XG5leHBvcnQgaW50ZXJmYWNlIEludGVybmFsT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHByaXZhdGVLZXk6IFByaXZhdGVLZXk7XG4gIHJlYWRvbmx5IHB1YmxpY0tleTogRUNQb2ludDtcbiAgcmVhZG9ubHkgZmVlQWRkcmVzczogVUludDE2MDtcbiAgcmVhZG9ubHkgcHJpdmF0ZU5ldDogYm9vbGVhbjtcbn1cblxuY29uc3QgTVNfSU5fU0VDT05EID0gMTAwMDtcblxuZXhwb3J0IGNsYXNzIENvbnNlbnN1cyB7XG4gIHByaXZhdGUgbXV0YWJsZVF1ZXVlOiBDb25zZW5zdXNRdWV1ZTtcbiAgcHJpdmF0ZSBtdXRhYmxlVGltZXI6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBJbnRlcm5hbE9wdGlvbnM7XG4gIHByaXZhdGUgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcHJpdmF0ZSBtdXRhYmxlQ29uc2Vuc3VzQ29udGV4dDogQ29uc2Vuc3VzQ29udGV4dDtcbiAgcHJpdmF0ZSBtdXRhYmxlU3RhcnRQcm9taXNlOiBQcm9taXNlPHZvaWQ+IHwgdW5kZWZpbmVkO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcih7IG9wdGlvbnMsIG5vZGUgfTogeyByZWFkb25seSBvcHRpb25zOiBPcHRpb25zOyByZWFkb25seSBub2RlOiBOb2RlIH0pIHtcbiAgICB0aGlzLm11dGFibGVRdWV1ZSA9IG5ldyBDb25zZW5zdXNRdWV1ZSgpO1xuXG4gICAgY29uc3QgcHJpdmF0ZUtleSA9IGNvbW1vbi5zdHJpbmdUb1ByaXZhdGVLZXkob3B0aW9ucy5wcml2YXRlS2V5KTtcbiAgICBjb25zdCBwdWJsaWNLZXkgPSBjcnlwdG8ucHJpdmF0ZUtleVRvUHVibGljS2V5KHByaXZhdGVLZXkpO1xuICAgIGNvbnN0IGZlZUFkZHJlc3MgPSBjcnlwdG8ucHVibGljS2V5VG9TY3JpcHRIYXNoKHB1YmxpY0tleSk7XG4gICAgdGhpcy5vcHRpb25zID0ge1xuICAgICAgcHJpdmF0ZUtleSxcbiAgICAgIHB1YmxpY0tleSxcbiAgICAgIGZlZUFkZHJlc3MsXG4gICAgICBwcml2YXRlTmV0OiBvcHRpb25zLnByaXZhdGVOZXQsXG4gICAgfTtcblxuICAgIHRoaXMubm9kZSA9IG5vZGU7XG4gICAgdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dCA9IG5ldyBDb25zZW5zdXNDb250ZXh0KCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTxEaXNwb3NhYmxlPiB7XG4gICAgbGV0IGRpc3Bvc2FibGUgPSBub29wRGlzcG9zYWJsZTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5wYXVzZSgpO1xuICAgICAgdGhpcy5kb1N0YXJ0KHRoaXMub3B0aW9ucyk7XG5cbiAgICAgIGRpc3Bvc2FibGUgPSBjb21wb3NlRGlzcG9zYWJsZXMoZGlzcG9zYWJsZSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLnBhdXNlKCk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGRpc3Bvc2FibGU7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBhd2FpdCBkaXNwb3NhYmxlKCk7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG9uUGVyc2lzdEJsb2NrKCk6IHZvaWQge1xuICAgIHRoaXMubXV0YWJsZVF1ZXVlLndyaXRlKHsgdHlwZTogJ2hhbmRsZVBlcnNpc3RCbG9jaycgfSk7XG4gIH1cblxuICBwdWJsaWMgb25Db25zZW5zdXNQYXlsb2FkUmVjZWl2ZWQocGF5bG9hZDogQ29uc2Vuc3VzUGF5bG9hZCk6IHZvaWQge1xuICAgIHRoaXMubXV0YWJsZVF1ZXVlLndyaXRlKHtcbiAgICAgIHR5cGU6ICdoYW5kbGVDb25zZW5zdXNQYXlsb2FkJyxcbiAgICAgIHBheWxvYWQsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgb25UcmFuc2FjdGlvblJlY2VpdmVkKHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbik6IHZvaWQge1xuICAgIHRoaXMubXV0YWJsZVF1ZXVlLndyaXRlKHtcbiAgICAgIHR5cGU6ICdoYW5kbGVUcmFuc2FjdGlvblJlY2VpdmVkJyxcbiAgICAgIHRyYW5zYWN0aW9uLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHJ1bkNvbnNlbnN1c05vdygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5vcHRpb25zLnByaXZhdGVOZXQpIHtcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBwcm9taXNlLW11c3QtY29tcGxldGVcbiAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgdGhpcy5tdXRhYmxlUXVldWUud3JpdGUoeyB0eXBlOiAndGltZXInLCBwcm9taXNlOiB7IHJlc29sdmUsIHJlamVjdCB9IH0pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG9ubHkgZm9yY2UgY29uc2Vuc3VzIG9uIGEgcHJpdmF0ZSBuZXR3b3JrLicpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBub3dTZWNvbmRzKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMubXV0YWJsZUNvbnNlbnN1c0NvbnRleHQubm93U2Vjb25kcygpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGZhc3RGb3J3YXJkT2Zmc2V0KHNlY29uZHM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm9wdGlvbnMucHJpdmF0ZU5ldCkge1xuICAgICAgdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dC5mYXN0Rm9yd2FyZE9mZnNldChzZWNvbmRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gb25seSBmYXN0IGZvcndhcmQgb24gYSBwcml2YXRlIG5ldHdvcmsuJyk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGZhc3RGb3J3YXJkVG9UaW1lKHNlY29uZHM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm9wdGlvbnMucHJpdmF0ZU5ldCkge1xuICAgICAgdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dC5mYXN0Rm9yd2FyZFRvVGltZShzZWNvbmRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gb25seSBmYXN0IGZvcndhcmQgb24gYSBwcml2YXRlIG5ldHdvcmsuJyk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHBhdXNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuY2xlYXJUaW1lcigpO1xuICAgIHRoaXMubXV0YWJsZVF1ZXVlLmRvbmUoKTtcbiAgICB0aGlzLm11dGFibGVRdWV1ZSA9IG5ldyBDb25zZW5zdXNRdWV1ZSgpO1xuICAgIGlmICh0aGlzLm11dGFibGVTdGFydFByb21pc2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgYXdhaXQgdGhpcy5tdXRhYmxlU3RhcnRQcm9taXNlO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZXNldCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLm11dGFibGVDb25zZW5zdXNDb250ZXh0ID0gbmV3IENvbnNlbnN1c0NvbnRleHQoKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZXN1bWUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgdGhpcy5kb1N0YXJ0KHRoaXMub3B0aW9ucyk7XG4gIH1cblxuICBwcml2YXRlIGRvU3RhcnQob3B0aW9uczogSW50ZXJuYWxPcHRpb25zKTogdm9pZCB7XG4gICAgbGV0IGNvbXBsZXRlZCA9IGZhbHNlO1xuICAgIGNvbnN0IG11dGFibGVTdGFydFByb21pc2UgPSB0aGlzLnN0YXJ0SW50ZXJuYWwob3B0aW9ucykudGhlbigoKSA9PiB7XG4gICAgICBjb21wbGV0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5tdXRhYmxlU3RhcnRQcm9taXNlID0gdW5kZWZpbmVkO1xuICAgIH0pO1xuICAgIGlmICghY29tcGxldGVkKSB7XG4gICAgICB0aGlzLm11dGFibGVTdGFydFByb21pc2UgPSBtdXRhYmxlU3RhcnRQcm9taXNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc3RhcnRJbnRlcm5hbChvcHRpb25zOiBJbnRlcm5hbE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2dnZXIuaW5mbyh7IG5hbWU6ICduZW9fY29uc2Vuc3VzX3N0YXJ0JyB9LCAnQ29uc2Vuc3VzIHN0YXJ0ZWQuJyk7XG5cbiAgICBjb25zdCBpbml0aWFsUmVzdWx0ID0gYXdhaXQgaW5pdGlhbGl6ZU5ld0NvbnNlbnN1cyh7XG4gICAgICBibG9ja2NoYWluOiB0aGlzLm5vZGUuYmxvY2tjaGFpbixcbiAgICAgIHB1YmxpY0tleTogb3B0aW9ucy5wdWJsaWNLZXksXG4gICAgICBjb25zZW5zdXNDb250ZXh0OiB0aGlzLm11dGFibGVDb25zZW5zdXNDb250ZXh0LFxuICAgIH0pO1xuXG4gICAgYXdhaXQgQXN5bmNJdGVyYWJsZVguZnJvbSh0aGlzLm11dGFibGVRdWV1ZSlcbiAgICAgIC5waXBlKFxuICAgICAgICBzY2FuKGFzeW5jIChjb250ZXh0OiBDb250ZXh0LCBldmVudDogRXZlbnQpID0+IHtcbiAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnaGFuZGxlUGVyc2lzdEJsb2NrJzpcbiAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgaGFuZGxlUGVyc2lzdEJsb2NrKHtcbiAgICAgICAgICAgICAgICBibG9ja2NoYWluOiB0aGlzLm5vZGUuYmxvY2tjaGFpbixcbiAgICAgICAgICAgICAgICBwdWJsaWNLZXk6IG9wdGlvbnMucHVibGljS2V5LFxuICAgICAgICAgICAgICAgIGNvbnNlbnN1c0NvbnRleHQ6IHRoaXMubXV0YWJsZUNvbnNlbnN1c0NvbnRleHQsXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaGFuZGxlQ29uc2Vuc3VzUGF5bG9hZCc6XG4gICAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IGhhbmRsZUNvbnNlbnN1c1BheWxvYWQoe1xuICAgICAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICAgICAgbm9kZTogdGhpcy5ub2RlLFxuICAgICAgICAgICAgICAgIHByaXZhdGVLZXk6IG9wdGlvbnMucHJpdmF0ZUtleSxcbiAgICAgICAgICAgICAgICBwYXlsb2FkOiBldmVudC5wYXlsb2FkLFxuICAgICAgICAgICAgICAgIGNvbnNlbnN1c0NvbnRleHQ6IHRoaXMubXV0YWJsZUNvbnNlbnN1c0NvbnRleHQsXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaGFuZGxlVHJhbnNhY3Rpb25SZWNlaXZlZCc6XG4gICAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IGhhbmRsZVRyYW5zYWN0aW9uUmVjZWl2ZWQoe1xuICAgICAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICAgICAgbm9kZTogdGhpcy5ub2RlLFxuICAgICAgICAgICAgICAgIHByaXZhdGVLZXk6IG9wdGlvbnMucHJpdmF0ZUtleSxcbiAgICAgICAgICAgICAgICB0cmFuc2FjdGlvbjogZXZlbnQudHJhbnNhY3Rpb24sXG4gICAgICAgICAgICAgICAgY29uc2Vuc3VzQ29udGV4dDogdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dCxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICd0aW1lcic6XG4gICAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IHJ1bkNvbnNlbnN1cyh7XG4gICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICBub2RlOiB0aGlzLm5vZGUsXG4gICAgICAgICAgICAgICAgb3B0aW9ucyxcbiAgICAgICAgICAgICAgICBjb25zZW5zdXNDb250ZXh0OiB0aGlzLm11dGFibGVDb25zZW5zdXNDb250ZXh0LFxuICAgICAgICAgICAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50LnByb21pc2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgZXZlbnQucHJvbWlzZS5yZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgaWYgKGV2ZW50LnByb21pc2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGV2ZW50LnByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgY29tbW9uVXRpbHMuYXNzZXJ0TmV2ZXIoZXZlbnQpO1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvciBUUycpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB0aGlzLmhhbmRsZVJlc3VsdChyZXN1bHQpO1xuICAgICAgICB9LCB0aGlzLmhhbmRsZVJlc3VsdChpbml0aWFsUmVzdWx0KSksXG4gICAgICApXG4gICAgICAuZm9yRWFjaCgoKSA9PiB7XG4gICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgIH0pO1xuXG4gICAgbG9nZ2VyLmluZm8oeyBuYW1lOiAnbmVvX2NvbnNlbnN1c19zdG9wJyB9LCAnQ29uc2Vuc3VzIHN0b3BwZWQuJyk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVJlc3VsdChyZXN1bHQ6IFJlc3VsdDxDb250ZXh0Pik6IENvbnRleHQge1xuICAgIGlmIChyZXN1bHQudGltZXJTZWNvbmRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuaGFuZGxlVGltZXIocmVzdWx0LnRpbWVyU2Vjb25kcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdC5jb250ZXh0O1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVUaW1lcihtdXRhYmxlVGltZXJTZWNvbmRzOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmNsZWFyVGltZXIoKTtcbiAgICB0aGlzLm11dGFibGVUaW1lciA9IHNldFRpbWVvdXQoXG4gICAgICAoKSA9PiB0aGlzLm11dGFibGVRdWV1ZS53cml0ZSh7IHR5cGU6ICd0aW1lcicgfSksXG4gICAgICBtdXRhYmxlVGltZXJTZWNvbmRzICogTVNfSU5fU0VDT05ELFxuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFueVxuICAgICkgYXMgYW55O1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhclRpbWVyKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLm11dGFibGVUaW1lciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5tdXRhYmxlVGltZXIpO1xuICAgICAgdGhpcy5tdXRhYmxlVGltZXIgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG59XG4iXX0=