UNPKG

25.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3/// <reference types="@reactivex/ix-es2015-cjs" />
4const client_common_1 = require("@neo-one/client-common");
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 operators_1 = require("rxjs/operators");
9const common_1 = require("./common");
10const ConsensusContext_1 = require("./ConsensusContext");
11const ConsensusQueue_1 = require("./ConsensusQueue");
12const handleConsensusPayload_1 = require("./handleConsensusPayload");
13const handlePersistBlock_1 = require("./handlePersistBlock");
14const handleTransactionReceived_1 = require("./handleTransactionReceived");
15const runConsensus_1 = require("./runConsensus");
16const MS_IN_SECOND = 1000;
17class Consensus {
18 constructor({ options$, node, monitor, }) {
19 this.mutableQueue = new ConsensusQueue_1.ConsensusQueue();
20 this.options$ = options$.pipe(operators_1.map((options) => {
21 const privateKey = client_common_1.common.stringToPrivateKey(options.privateKey);
22 const publicKey = client_common_1.crypto.privateKeyToPublicKey(privateKey);
23 const feeAddress = client_common_1.crypto.publicKeyToScriptHash(publicKey);
24 return {
25 privateKey,
26 publicKey,
27 feeAddress,
28 privateNet: options.privateNet,
29 };
30 }));
31 this.node = node;
32 this.mutableConsensusContext = new ConsensusContext_1.ConsensusContext();
33 this.monitor = monitor.at('node_consensus');
34 }
35 start$() {
36 return this.options$.pipe(utils_1.mergeScanLatest(async (_, options) => {
37 await this.pause();
38 this.doStart(options);
39 }), utils_1.finalize(async () => {
40 await this.pause();
41 }));
42 }
43 onPersistBlock() {
44 this.mutableQueue.write({ type: 'handlePersistBlock' });
45 }
46 onConsensusPayloadReceived(payload) {
47 this.mutableQueue.write({
48 type: 'handleConsensusPayload',
49 payload,
50 });
51 }
52 onTransactionReceived(transaction) {
53 this.mutableQueue.write({
54 type: 'handleTransactionReceived',
55 transaction,
56 });
57 }
58 async runConsensusNow() {
59 const options = await this.options$.pipe(operators_1.take(1)).toPromise();
60 if (options.privateNet) {
61 this.mutableQueue.write({ type: 'timer' });
62 }
63 else {
64 throw new Error('Can only force consensus on a private network.');
65 }
66 }
67 nowSeconds() {
68 return this.mutableConsensusContext.nowSeconds();
69 }
70 async fastForwardOffset(seconds) {
71 const options = await this.options$.pipe(operators_1.take(1)).toPromise();
72 if (options.privateNet) {
73 this.mutableConsensusContext.fastForwardOffset(seconds);
74 }
75 else {
76 throw new Error('Can only fast forward on a private network.');
77 }
78 }
79 async fastForwardToTime(seconds) {
80 const options = await this.options$.pipe(operators_1.take(1)).toPromise();
81 if (options.privateNet) {
82 this.mutableConsensusContext.fastForwardToTime(seconds);
83 }
84 else {
85 throw new Error('Can only fast forward on a private network.');
86 }
87 }
88 async pause() {
89 this.clearTimer();
90 this.mutableQueue.done();
91 this.mutableQueue = new ConsensusQueue_1.ConsensusQueue();
92 if (this.mutableStartPromise !== undefined) {
93 await this.mutableStartPromise;
94 }
95 }
96 async reset() {
97 this.mutableConsensusContext = new ConsensusContext_1.ConsensusContext();
98 }
99 async resume() {
100 const options = await this.options$.pipe(operators_1.take(1)).toPromise();
101 // tslint:disable-next-line no-floating-promises
102 this.doStart(options);
103 }
104 doStart(options) {
105 let completed = false;
106 const mutableStartPromise = this.start(options).then(() => {
107 completed = true;
108 this.mutableStartPromise = undefined;
109 });
110 if (!completed) {
111 this.mutableStartPromise = mutableStartPromise;
112 }
113 }
114 async start(options) {
115 this.monitor.log({
116 name: 'neo_consensus_start',
117 message: 'Consensus started.',
118 level: 'verbose',
119 });
120 const initialResult = await common_1.initializeNewConsensus({
121 blockchain: this.node.blockchain,
122 publicKey: options.publicKey,
123 consensusContext: this.mutableConsensusContext,
124 });
125 await asynciterablex_1.AsyncIterableX.from(this.mutableQueue)
126 .pipe(scan_1.scan(async (context, event) => {
127 let result;
128 switch (event.type) {
129 case 'handlePersistBlock':
130 result = await handlePersistBlock_1.handlePersistBlock({
131 blockchain: this.node.blockchain,
132 publicKey: options.publicKey,
133 consensusContext: this.mutableConsensusContext,
134 });
135 break;
136 case 'handleConsensusPayload':
137 result = await handleConsensusPayload_1.handleConsensusPayload({
138 context,
139 node: this.node,
140 privateKey: options.privateKey,
141 payload: event.payload,
142 consensusContext: this.mutableConsensusContext,
143 });
144 break;
145 case 'handleTransactionReceived':
146 result = await handleTransactionReceived_1.handleTransactionReceived({
147 context,
148 node: this.node,
149 privateKey: options.privateKey,
150 transaction: event.transaction,
151 consensusContext: this.mutableConsensusContext,
152 });
153 break;
154 case 'timer':
155 result = await runConsensus_1.runConsensus({
156 context,
157 node: this.node,
158 options,
159 consensusContext: this.mutableConsensusContext,
160 });
161 break;
162 default:
163 utils_1.utils.assertNever(event);
164 throw new Error('For TS');
165 }
166 return this.handleResult(result);
167 }, this.handleResult(initialResult)))
168 .forEach(() => {
169 // do nothing
170 });
171 this.monitor.log({
172 name: 'neo_consensus_stop',
173 message: 'Consensus stopped.',
174 level: 'verbose',
175 });
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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QUcsU0FBUyxDQUFDO1NBQy9CO0lBQ0gsQ0FBQztDQUNGO0FBbk9ELDhCQW1PQyIsImZpbGUiOiJuZW8tb25lLW5vZGUtY29uc2Vuc3VzL3NyYy9Db25zZW5zdXMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLy8gPHJlZmVyZW5jZSB0eXBlcz1cIkByZWFjdGl2ZXgvaXgtZXMyMDE1LWNqc1wiIC8+XG5pbXBvcnQgeyBjb21tb24sIGNyeXB0bywgRUNQb2ludCwgUHJpdmF0ZUtleSwgVUludDE2MCB9IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb21tb24nO1xuaW1wb3J0IHsgTW9uaXRvciB9IGZyb20gJ0BuZW8tb25lL21vbml0b3InO1xuaW1wb3J0IHsgQ29uc2Vuc3VzUGF5bG9hZCwgTm9kZSwgVHJhbnNhY3Rpb24gfSBmcm9tICdAbmVvLW9uZS9ub2RlLWNvcmUnO1xuaW1wb3J0IHsgZmluYWxpemUsIG1lcmdlU2NhbkxhdGVzdCwgdXRpbHMgYXMgY29tbW9uVXRpbHMgfSBmcm9tICdAbmVvLW9uZS91dGlscyc7XG5pbXBvcnQgeyBBc3luY0l0ZXJhYmxlWCB9IGZyb20gJ0ByZWFjdGl2ZXgvaXgtZXMyMDE1LWNqcy9hc3luY2l0ZXJhYmxlL2FzeW5jaXRlcmFibGV4JztcbmltcG9ydCB7IHNjYW4gfSBmcm9tICdAcmVhY3RpdmV4L2l4LWVzMjAxNS1janMvYXN5bmNpdGVyYWJsZS9waXBlL3NjYW4nO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCB0YWtlIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgaW5pdGlhbGl6ZU5ld0NvbnNlbnN1cyB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IENvbnNlbnN1c0NvbnRleHQgfSBmcm9tICcuL0NvbnNlbnN1c0NvbnRleHQnO1xuaW1wb3J0IHsgQ29uc2Vuc3VzUXVldWUgfSBmcm9tICcuL0NvbnNlbnN1c1F1ZXVlJztcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tICcuL2NvbnRleHQnO1xuaW1wb3J0IHsgaGFuZGxlQ29uc2Vuc3VzUGF5bG9hZCB9IGZyb20gJy4vaGFuZGxlQ29uc2Vuc3VzUGF5bG9hZCc7XG5pbXBvcnQgeyBoYW5kbGVQZXJzaXN0QmxvY2sgfSBmcm9tICcuL2hhbmRsZVBlcnNpc3RCbG9jayc7XG5pbXBvcnQgeyBoYW5kbGVUcmFuc2FjdGlvblJlY2VpdmVkIH0gZnJvbSAnLi9oYW5kbGVUcmFuc2FjdGlvblJlY2VpdmVkJztcbmltcG9ydCB7IHJ1bkNvbnNlbnN1cyB9IGZyb20gJy4vcnVuQ29uc2Vuc3VzJztcbmltcG9ydCB7IEV2ZW50LCBSZXN1bHQgfSBmcm9tICcuL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBPcHRpb25zIHtcbiAgcmVhZG9ubHkgcHJpdmF0ZUtleTogc3RyaW5nO1xuICByZWFkb25seSBwcml2YXRlTmV0OiBib29sZWFuO1xufVxuZXhwb3J0IGludGVyZmFjZSBJbnRlcm5hbE9wdGlvbnMge1xuICByZWFkb25seSBwcml2YXRlS2V5OiBQcml2YXRlS2V5O1xuICByZWFkb25seSBwdWJsaWNLZXk6IEVDUG9pbnQ7XG4gIHJlYWRvbmx5IGZlZUFkZHJlc3M6IFVJbnQxNjA7XG4gIHJlYWRvbmx5IHByaXZhdGVOZXQ6IGJvb2xlYW47XG59XG5cbmNvbnN0IE1TX0lOX1NFQ09ORCA9IDEwMDA7XG5cbmV4cG9ydCBjbGFzcyBDb25zZW5zdXMge1xuICBwcml2YXRlIG11dGFibGVRdWV1ZTogQ29uc2Vuc3VzUXVldWU7XG4gIHByaXZhdGUgbXV0YWJsZVRpbWVyOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9ucyQ6IE9ic2VydmFibGU8SW50ZXJuYWxPcHRpb25zPjtcbiAgcHJpdmF0ZSByZWFkb25seSBub2RlOiBOb2RlO1xuICBwcml2YXRlIG11dGFibGVDb25zZW5zdXNDb250ZXh0OiBDb25zZW5zdXNDb250ZXh0O1xuICBwcml2YXRlIHJlYWRvbmx5IG1vbml0b3I6IE1vbml0b3I7XG4gIHByaXZhdGUgbXV0YWJsZVN0YXJ0UHJvbWlzZTogUHJvbWlzZTx2b2lkPiB8IHVuZGVmaW5lZDtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioe1xuICAgIG9wdGlvbnMkLFxuICAgIG5vZGUsXG4gICAgbW9uaXRvcixcbiAgfToge1xuICAgIHJlYWRvbmx5IG9wdGlvbnMkOiBPYnNlcnZhYmxlPE9wdGlvbnM+O1xuICAgIHJlYWRvbmx5IG5vZGU6IE5vZGU7XG4gICAgcmVhZG9ubHkgbW9uaXRvcjogTW9uaXRvcjtcbiAgfSkge1xuICAgIHRoaXMubXV0YWJsZVF1ZXVlID0gbmV3IENvbnNlbnN1c1F1ZXVlKCk7XG4gICAgdGhpcy5vcHRpb25zJCA9IG9wdGlvbnMkLnBpcGUoXG4gICAgICBtYXAoKG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgcHJpdmF0ZUtleSA9IGNvbW1vbi5zdHJpbmdUb1ByaXZhdGVLZXkob3B0aW9ucy5wcml2YXRlS2V5KTtcbiAgICAgICAgY29uc3QgcHVibGljS2V5ID0gY3J5cHRvLnByaXZhdGVLZXlUb1B1YmxpY0tleShwcml2YXRlS2V5KTtcbiAgICAgICAgY29uc3QgZmVlQWRkcmVzcyA9IGNyeXB0by5wdWJsaWNLZXlUb1NjcmlwdEhhc2gocHVibGljS2V5KTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHByaXZhdGVLZXksXG4gICAgICAgICAgcHVibGljS2V5LFxuICAgICAgICAgIGZlZUFkZHJlc3MsXG4gICAgICAgICAgcHJpdmF0ZU5ldDogb3B0aW9ucy5wcml2YXRlTmV0LFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIHRoaXMubm9kZSA9IG5vZGU7XG4gICAgdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dCA9IG5ldyBDb25zZW5zdXNDb250ZXh0KCk7XG4gICAgdGhpcy5tb25pdG9yID0gbW9uaXRvci5hdCgnbm9kZV9jb25zZW5zdXMnKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGFydCQoKTogT2JzZXJ2YWJsZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucyQucGlwZShcbiAgICAgIG1lcmdlU2NhbkxhdGVzdDxJbnRlcm5hbE9wdGlvbnMsIHZvaWQ+KGFzeW5jIChfLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMucGF1c2UoKTtcbiAgICAgICAgdGhpcy5kb1N0YXJ0KG9wdGlvbnMpO1xuICAgICAgfSksXG4gICAgICBmaW5hbGl6ZShhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMucGF1c2UoKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgb25QZXJzaXN0QmxvY2soKTogdm9pZCB7XG4gICAgdGhpcy5tdXRhYmxlUXVldWUud3JpdGUoeyB0eXBlOiAnaGFuZGxlUGVyc2lzdEJsb2NrJyB9KTtcbiAgfVxuXG4gIHB1YmxpYyBvbkNvbnNlbnN1c1BheWxvYWRSZWNlaXZlZChwYXlsb2FkOiBDb25zZW5zdXNQYXlsb2FkKTogdm9pZCB7XG4gICAgdGhpcy5tdXRhYmxlUXVldWUud3JpdGUoe1xuICAgICAgdHlwZTogJ2hhbmRsZUNvbnNlbnN1c1BheWxvYWQnLFxuICAgICAgcGF5bG9hZCxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBvblRyYW5zYWN0aW9uUmVjZWl2ZWQodHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy5tdXRhYmxlUXVldWUud3JpdGUoe1xuICAgICAgdHlwZTogJ2hhbmRsZVRyYW5zYWN0aW9uUmVjZWl2ZWQnLFxuICAgICAgdHJhbnNhY3Rpb24sXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcnVuQ29uc2Vuc3VzTm93KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBhd2FpdCB0aGlzLm9wdGlvbnMkLnBpcGUodGFrZSgxKSkudG9Qcm9taXNlKCk7XG4gICAgaWYgKG9wdGlvbnMucHJpdmF0ZU5ldCkge1xuICAgICAgdGhpcy5tdXRhYmxlUXVldWUud3JpdGUoeyB0eXBlOiAndGltZXInIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGZvcmNlIGNvbnNlbnN1cyBvbiBhIHByaXZhdGUgbmV0d29yay4nKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgbm93U2Vjb25kcygpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLm11dGFibGVDb25zZW5zdXNDb250ZXh0Lm5vd1NlY29uZHMoKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBmYXN0Rm9yd2FyZE9mZnNldChzZWNvbmRzOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBvcHRpb25zID0gYXdhaXQgdGhpcy5vcHRpb25zJC5waXBlKHRha2UoMSkpLnRvUHJvbWlzZSgpO1xuICAgIGlmIChvcHRpb25zLnByaXZhdGVOZXQpIHtcbiAgICAgIHRoaXMubXV0YWJsZUNvbnNlbnN1c0NvbnRleHQuZmFzdEZvcndhcmRPZmZzZXQoc2Vjb25kcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG9ubHkgZmFzdCBmb3J3YXJkIG9uIGEgcHJpdmF0ZSBuZXR3b3JrLicpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBmYXN0Rm9yd2FyZFRvVGltZShzZWNvbmRzOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBvcHRpb25zID0gYXdhaXQgdGhpcy5vcHRpb25zJC5waXBlKHRha2UoMSkpLnRvUHJvbWlzZSgpO1xuICAgIGlmIChvcHRpb25zLnByaXZhdGVOZXQpIHtcbiAgICAgIHRoaXMubXV0YWJsZUNvbnNlbnN1c0NvbnRleHQuZmFzdEZvcndhcmRUb1RpbWUoc2Vjb25kcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG9ubHkgZmFzdCBmb3J3YXJkIG9uIGEgcHJpdmF0ZSBuZXR3b3JrLicpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBwYXVzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmNsZWFyVGltZXIoKTtcbiAgICB0aGlzLm11dGFibGVRdWV1ZS5kb25lKCk7XG4gICAgdGhpcy5tdXRhYmxlUXVldWUgPSBuZXcgQ29uc2Vuc3VzUXVldWUoKTtcbiAgICBpZiAodGhpcy5tdXRhYmxlU3RhcnRQcm9taXNlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMubXV0YWJsZVN0YXJ0UHJvbWlzZTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcmVzZXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dCA9IG5ldyBDb25zZW5zdXNDb250ZXh0KCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcmVzdW1lKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBhd2FpdCB0aGlzLm9wdGlvbnMkLnBpcGUodGFrZSgxKSkudG9Qcm9taXNlKCk7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgdGhpcy5kb1N0YXJ0KG9wdGlvbnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBkb1N0YXJ0KG9wdGlvbnM6IEludGVybmFsT3B0aW9ucyk6IHZvaWQge1xuICAgIGxldCBjb21wbGV0ZWQgPSBmYWxzZTtcbiAgICBjb25zdCBtdXRhYmxlU3RhcnRQcm9taXNlID0gdGhpcy5zdGFydChvcHRpb25zKS50aGVuKCgpID0+IHtcbiAgICAgIGNvbXBsZXRlZCA9IHRydWU7XG4gICAgICB0aGlzLm11dGFibGVTdGFydFByb21pc2UgPSB1bmRlZmluZWQ7XG4gICAgfSk7XG4gICAgaWYgKCFjb21wbGV0ZWQpIHtcbiAgICAgIHRoaXMubXV0YWJsZVN0YXJ0UHJvbWlzZSA9IG11dGFibGVTdGFydFByb21pc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzdGFydChvcHRpb25zOiBJbnRlcm5hbE9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLm1vbml0b3IubG9nKHtcbiAgICAgIG5hbWU6ICduZW9fY29uc2Vuc3VzX3N0YXJ0JyxcbiAgICAgIG1lc3NhZ2U6ICdDb25zZW5zdXMgc3RhcnRlZC4nLFxuICAgICAgbGV2ZWw6ICd2ZXJib3NlJyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGluaXRpYWxSZXN1bHQgPSBhd2FpdCBpbml0aWFsaXplTmV3Q29uc2Vuc3VzKHtcbiAgICAgIGJsb2NrY2hhaW46IHRoaXMubm9kZS5ibG9ja2NoYWluLFxuICAgICAgcHVibGljS2V5OiBvcHRpb25zLnB1YmxpY0tleSxcbiAgICAgIGNvbnNlbnN1c0NvbnRleHQ6IHRoaXMubXV0YWJsZUNvbnNlbnN1c0NvbnRleHQsXG4gICAgfSk7XG5cbiAgICBhd2FpdCBBc3luY0l0ZXJhYmxlWC5mcm9tKHRoaXMubXV0YWJsZVF1ZXVlKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHNjYW4oYXN5bmMgKGNvbnRleHQ6IENvbnRleHQsIGV2ZW50OiBFdmVudCkgPT4ge1xuICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgc3dpdGNoIChldmVudC50eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdoYW5kbGVQZXJzaXN0QmxvY2snOlxuICAgICAgICAgICAgICByZXN1bHQgPSBhd2FpdCBoYW5kbGVQZXJzaXN0QmxvY2soe1xuICAgICAgICAgICAgICAgIGJsb2NrY2hhaW46IHRoaXMubm9kZS5ibG9ja2NoYWluLFxuICAgICAgICAgICAgICAgIHB1YmxpY0tleTogb3B0aW9ucy5wdWJsaWNLZXksXG4gICAgICAgICAgICAgICAgY29uc2Vuc3VzQ29udGV4dDogdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dCxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoYW5kbGVDb25zZW5zdXNQYXlsb2FkJzpcbiAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgaGFuZGxlQ29uc2Vuc3VzUGF5bG9hZCh7XG4gICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICBub2RlOiB0aGlzLm5vZGUsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZUtleTogb3B0aW9ucy5wcml2YXRlS2V5LFxuICAgICAgICAgICAgICAgIHBheWxvYWQ6IGV2ZW50LnBheWxvYWQsXG4gICAgICAgICAgICAgICAgY29uc2Vuc3VzQ29udGV4dDogdGhpcy5tdXRhYmxlQ29uc2Vuc3VzQ29udGV4dCxcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdoYW5kbGVUcmFuc2FjdGlvblJlY2VpdmVkJzpcbiAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgaGFuZGxlVHJhbnNhY3Rpb25SZWNlaXZlZCh7XG4gICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICBub2RlOiB0aGlzLm5vZGUsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZUtleTogb3B0aW9ucy5wcml2YXRlS2V5LFxuICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uOiBldmVudC50cmFuc2FjdGlvbixcbiAgICAgICAgICAgICAgICBjb25zZW5zdXNDb250ZXh0OiB0aGlzLm11dGFibGVDb25zZW5zdXNDb250ZXh0LFxuICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3RpbWVyJzpcbiAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgcnVuQ29uc2Vuc3VzKHtcbiAgICAgICAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgICAgICAgIG5vZGU6IHRoaXMubm9kZSxcbiAgICAgICAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgICAgICAgIGNvbnNlbnN1c0NvbnRleHQ6IHRoaXMubXV0YWJsZUNvbnNlbnN1c0NvbnRleHQsXG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgY29tbW9uVXRpbHMuYXNzZXJ0TmV2ZXIoZXZlbnQpO1xuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvciBUUycpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB0aGlzLmhhbmRsZVJlc3VsdChyZXN1bHQpO1xuICAgICAgICB9LCB0aGlzLmhhbmRsZVJlc3VsdChpbml0aWFsUmVzdWx0KSksXG4gICAgICApXG4gICAgICAuZm9yRWFjaCgoKSA9PiB7XG4gICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5tb25pdG9yLmxvZyh7XG4gICAgICBuYW1lOiAnbmVvX2NvbnNlbnN1c19zdG9wJyxcbiAgICAgIG1lc3NhZ2U6ICdDb25zZW5zdXMgc3RvcHBlZC4nLFxuICAgICAgbGV2ZWw6ICd2ZXJib3NlJyxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlUmVzdWx0KHJlc3VsdDogUmVzdWx0PENvbnRleHQ+KTogQ29udGV4dCB7XG4gICAgaWYgKHJlc3VsdC50aW1lclNlY29uZHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5oYW5kbGVUaW1lcihyZXN1bHQudGltZXJTZWNvbmRzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0LmNvbnRleHQ7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVRpbWVyKG11dGFibGVUaW1lclNlY29uZHM6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuY2xlYXJUaW1lcigpO1xuICAgIHRoaXMubXV0YWJsZVRpbWVyID0gc2V0VGltZW91dChcbiAgICAgICgpID0+IHRoaXMubXV0YWJsZVF1ZXVlLndyaXRlKHsgdHlwZTogJ3RpbWVyJyB9KSxcbiAgICAgIG11dGFibGVUaW1lclNlY29uZHMgKiBNU19JTl9TRUNPTkQsXG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYW55XG4gICAgKSBhcyBhbnk7XG4gIH1cblxuICBwcml2YXRlIGNsZWFyVGltZXIoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubXV0YWJsZVRpbWVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLm11dGFibGVUaW1lcik7XG4gICAgICB0aGlzLm11dGFibGVUaW1lciA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cbn1cbiJdfQ==