UNPKG

36.5 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const client_common_1 = require("@neo-one/client-common");
5const node_core_1 = require("@neo-one/node-core");
6const utils_1 = require("@neo-one/utils");
7const lodash_1 = tslib_1.__importDefault(require("lodash"));
8const context_1 = require("./context");
9exports.signAndRelay = ({ node, privateKey, context, consensusMessage, }) => {
10 const payload = node_core_1.ConsensusPayload.sign(new node_core_1.UnsignedConsensusPayload({
11 version: context.version,
12 previousHash: context.previousHash,
13 blockIndex: context.blockIndex,
14 validatorIndex: context.myIndex,
15 consensusMessage,
16 }), privateKey);
17 node.relayConsensusPayload(payload);
18};
19exports.getInitialContextAdd = ({ blockchain, publicKey, validators, blockReceivedTimeSeconds, }) => {
20 const blockIndex = blockchain.currentBlock.index + 1;
21 const primaryIndex = blockIndex % validators.length;
22 const myIndex = lodash_1.default.findIndex(validators, (validator) => client_common_1.common.ecPointEqual(validator, publicKey));
23 return {
24 type: primaryIndex === myIndex ? 'primary' : 'backup',
25 previousHash: blockchain.currentBlock.hash,
26 blockIndex,
27 viewNumber: 0,
28 myIndex,
29 primaryIndex,
30 expectedView: lodash_1.default.range(0, validators.length).map(() => 0),
31 validators,
32 blockReceivedTimeSeconds,
33 };
34};
35function initializeConsensusCommon({ context, blockchain, consensusContext, }) {
36 if (context.myIndex < 0) {
37 return { context };
38 }
39 if (context.type === 'primary') {
40 return {
41 context,
42 timerSeconds: Math.max(0, blockchain.settings.secondsPerBlock - (consensusContext.nowSeconds() - context.blockReceivedTimeSeconds)),
43 };
44 }
45 const { secondsPerBlock } = blockchain.settings;
46 return {
47 context,
48 // tslint:disable-next-line no-bitwise
49 timerSeconds: secondsPerBlock << (context.viewNumber + 1),
50 };
51}
52exports.initializeNewConsensus = async ({ blockchain, publicKey, consensusContext, }) => {
53 const validators = await blockchain.getValidators([]);
54 const blockReceivedTimeSeconds = blockchain.currentBlock.timestamp;
55 const blockIndex = blockchain.currentBlock.index + 1;
56 const primaryIndex = blockIndex % validators.length;
57 const myIndex = lodash_1.default.findIndex(validators, (validator) => client_common_1.common.ecPointEqual(validator, publicKey));
58 const context = new context_1.InitialContext({
59 type: primaryIndex === myIndex ? 'primary' : 'backup',
60 previousHash: blockchain.currentBlock.hash,
61 blockIndex,
62 viewNumber: 0,
63 myIndex,
64 primaryIndex,
65 expectedView: lodash_1.default.range(0, validators.length).map(() => 0),
66 validators,
67 blockReceivedTimeSeconds,
68 });
69 return initializeConsensusCommon({ context, blockchain, consensusContext });
70};
71const getPrimaryIndexType = ({ context, viewNumber, }) => {
72 let primaryIndex = (context.blockIndex - viewNumber) % context.validators.length;
73 if (primaryIndex < 0) {
74 primaryIndex += context.validators.length;
75 }
76 return {
77 type: primaryIndex === context.myIndex ? 'primary' : 'backup',
78 primaryIndex,
79 };
80};
81exports.initializeConsensus = ({ node, context: contextIn, viewNumber, consensusContext, }) => {
82 if (viewNumber <= 0) {
83 throw new Error('Programming error');
84 }
85 const { blockchain } = node;
86 let context = contextIn;
87 let primaryIndex = (context.blockIndex - viewNumber) % context.validators.length;
88 if (primaryIndex < 0) {
89 primaryIndex += context.validators.length;
90 }
91 const type = primaryIndex === context.myIndex ? 'primary' : 'backup';
92 context =
93 type === 'primary' && context instanceof context_1.SignatureSentContext
94 ? context.clone({ type, primaryIndex, viewNumber })
95 : context_1.cloneInitial(context, { type, primaryIndex, viewNumber });
96 return initializeConsensusCommon({ blockchain, context, consensusContext });
97};
98async function checkSignatures({ node, context, }) {
99 const signaturesLength = context.signatures.filter((p) => p !== undefined).length;
100 if (signaturesLength >= context.M &&
101 context.transactionHashes.every((hash) => context.transactions[hash] !== undefined)) {
102 const mutablePublicKeyToSignature = {};
103 // tslint:disable-next-line no-loop-statement
104 for (let i = 0, j = 0; i < context.validators.length && j < context.M; i += 1) {
105 const validator = context.validators[i];
106 const signature = context.signatures[i];
107 if (signature !== undefined) {
108 mutablePublicKeyToSignature[client_common_1.common.ecPointToHex(validator)] = signature;
109 j += 1;
110 }
111 }
112 const script = client_common_1.crypto.createMultiSignatureWitness(context.M, context.validators, mutablePublicKeyToSignature, node_core_1.Witness);
113 const block = context.header.clone({
114 transactions: context.transactionHashes.map((hash) => context.transactions[hash]).filter(utils_1.utils.notNull),
115 script,
116 });
117 await node.relayBlock(block);
118 return { context: context_1.cloneBlockSent(context) };
119 }
120 return { context };
121}
122exports.checkSignatures = checkSignatures;
123exports.signAndRelayChangeView = ({ node, privateKey, context, }) => {
124 exports.signAndRelay({
125 node,
126 privateKey,
127 context,
128 consensusMessage: new node_core_1.ChangeViewConsensusMessage({
129 viewNumber: context.viewNumber,
130 newViewNumber: context.expectedView[context.myIndex],
131 }),
132 });
133};
134exports.checkExpectedView = ({ context, viewNumber, }) => context.viewNumber !== viewNumber && context.expectedView.filter((p) => p === viewNumber).length >= context.M;
135exports.initializeConsensusInitial = ({ blockchain, context, viewNumber, consensusContext, }) => {
136 const { primaryIndex, type } = getPrimaryIndexType({ context, viewNumber });
137 return initializeConsensusCommon({
138 blockchain,
139 context: context_1.cloneInitial(context, { type, primaryIndex, viewNumber }),
140 consensusContext,
141 });
142};
143exports.incrementExpectedView = (context) => {
144 const mutableExpectedView = [...context.expectedView];
145 mutableExpectedView[context.myIndex] += 1;
146 return mutableExpectedView;
147};
148const requestChangeViewBackup = ({ context: contextIn, node, privateKey, consensusContext, }) => {
149 const context = contextIn.cloneViewChanging({
150 expectedView: exports.incrementExpectedView(contextIn),
151 });
152 exports.signAndRelayChangeView({ context, node, privateKey });
153 const viewNumber = context.expectedView[context.myIndex];
154 if (exports.checkExpectedView({ context, viewNumber })) {
155 return exports.initializeConsensusInitial({
156 blockchain: node.blockchain,
157 context,
158 viewNumber,
159 consensusContext,
160 });
161 }
162 return { context };
163};
164exports.addTransaction = async ({ context: contextIn, node, privateKey, transaction, verify, consensusContext, }) => {
165 let context = contextIn;
166 const { blockchain } = node;
167 const tx = await blockchain.transaction.tryGet({ hash: transaction.hash });
168 if (tx !== undefined) {
169 return { context };
170 }
171 if (verify) {
172 let verified = true;
173 try {
174 const { verifications } = await blockchain.verifyTransaction({
175 transaction,
176 memPool: Object.values(context.transactions).filter(utils_1.utils.notNull),
177 });
178 verified = verifications.every(({ failureMessage }) => failureMessage === undefined);
179 }
180 catch (_a) {
181 verified = false;
182 }
183 if (!verified) {
184 return { context };
185 }
186 }
187 context = context.clone({
188 transactions: Object.assign({}, context.transactions, { [transaction.hashHex]: transaction }),
189 });
190 const transactionsLength = Object.values(context.transactions).length;
191 if (context.transactionHashes.length === transactionsLength) {
192 const validators = await blockchain.getValidators(Object.values(context.transactions).filter(utils_1.utils.notNull));
193 const consensusAddress = client_common_1.crypto.getConsensusAddress(validators);
194 if (client_common_1.common.uInt160Equal(consensusAddress, context.header.nextConsensus)) {
195 const mutableSignatures = [...context.signatures];
196 mutableSignatures[context.myIndex] = client_common_1.crypto.sign({
197 message: context.header.message,
198 privateKey,
199 });
200 const newContext = context.cloneSignatureSent({ signatures: mutableSignatures });
201 exports.signAndRelay({
202 node,
203 context: newContext,
204 privateKey,
205 consensusMessage: new node_core_1.PrepareResponseConsensusMessage({
206 viewNumber: newContext.viewNumber,
207 signature: utils_1.utils.nullthrows(mutableSignatures[newContext.myIndex]),
208 }),
209 });
210 return checkSignatures({ node, context: newContext });
211 }
212 return requestChangeViewBackup({
213 context,
214 node,
215 privateKey,
216 consensusContext,
217 });
218 }
219 return { context };
220};
221
222//# sourceMappingURL=data:application/json;charset=utf8;base64,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RSxDQUFDLENBQUM7WUFDakYsb0JBQVksQ0FBQztnQkFDWCxJQUFJO2dCQUNKLE9BQU8sRUFBRSxVQUFVO2dCQUNuQixVQUFVO2dCQUNWLGdCQUFnQixFQUFFLElBQUksMkNBQStCLENBQUM7b0JBQ3BELFVBQVUsRUFBRSxVQUFVLENBQUMsVUFBVTtvQkFDakMsU0FBUyxFQUFFLGFBQVcsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUN6RSxDQUFDO2FBQ0gsQ0FBQyxDQUFDO1lBRUgsT0FBTyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7U0FDdkQ7UUFFRCxPQUFPLHVCQUF1QixDQUFDO1lBQzdCLE9BQU87WUFDUCxJQUFJO1lBQ0osVUFBVTtZQUNWLGdCQUFnQjtTQUNqQixDQUFDLENBQUM7S0FDSjtJQUVELE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUNyQixDQUFDLENBQUMiLCJmaWxlIjoibmVvLW9uZS1ub2RlLWNvbnNlbnN1cy9zcmMvY29tbW9uLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29tbW9uLCBjcnlwdG8sIEVDUG9pbnQsIFByaXZhdGVLZXkgfSBmcm9tICdAbmVvLW9uZS9jbGllbnQtY29tbW9uJztcbmltcG9ydCB7XG4gIEJsb2NrY2hhaW4sXG4gIENoYW5nZVZpZXdDb25zZW5zdXNNZXNzYWdlLFxuICBDb25zZW5zdXNNZXNzYWdlLFxuICBDb25zZW5zdXNQYXlsb2FkLFxuICBOb2RlLFxuICBQcmVwYXJlUmVzcG9uc2VDb25zZW5zdXNNZXNzYWdlLFxuICBUcmFuc2FjdGlvbixcbiAgVW5zaWduZWRDb25zZW5zdXNQYXlsb2FkLFxuICBXaXRuZXNzLFxufSBmcm9tICdAbmVvLW9uZS9ub2RlLWNvcmUnO1xuaW1wb3J0IHsgdXRpbHMgYXMgY29tbW9uVXRpbHMgfSBmcm9tICdAbmVvLW9uZS91dGlscyc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgQ29uc2Vuc3VzQ29udGV4dCB9IGZyb20gJy4vQ29uc2Vuc3VzQ29udGV4dCc7XG5pbXBvcnQge1xuICBCbG9ja1NlbnRDb250ZXh0LFxuICBjbG9uZUJsb2NrU2VudCxcbiAgY2xvbmVJbml0aWFsLFxuICBDb250ZXh0LFxuICBIZWFkZXJDb250ZXh0LFxuICBJbml0aWFsQ29udGV4dCxcbiAgUmVxdWVzdFJlY2VpdmVkQ29udGV4dCxcbiAgU2lnbmF0dXJlU2VudENvbnRleHQsXG4gIFR5cGUsXG4gIFZpZXdDaGFuZ2luZ0NvbnRleHQsXG59IGZyb20gJy4vY29udGV4dCc7XG5pbXBvcnQgeyBSZXN1bHQgfSBmcm9tICcuL3R5cGVzJztcblxuZXhwb3J0IGNvbnN0IHNpZ25BbmRSZWxheSA9ICh7XG4gIG5vZGUsXG4gIHByaXZhdGVLZXksXG4gIGNvbnRleHQsXG4gIGNvbnNlbnN1c01lc3NhZ2UsXG59OiB7XG4gIHJlYWRvbmx5IG5vZGU6IE5vZGU7XG4gIHJlYWRvbmx5IHByaXZhdGVLZXk6IFByaXZhdGVLZXk7XG4gIHJlYWRvbmx5IGNvbnRleHQ6IENvbnRleHQ7XG4gIHJlYWRvbmx5IGNvbnNlbnN1c01lc3NhZ2U6IENvbnNlbnN1c01lc3NhZ2U7XG59KSA9PiB7XG4gIGNvbnN0IHBheWxvYWQgPSBDb25zZW5zdXNQYXlsb2FkLnNpZ24oXG4gICAgbmV3IFVuc2lnbmVkQ29uc2Vuc3VzUGF5bG9hZCh7XG4gICAgICB2ZXJzaW9uOiBjb250ZXh0LnZlcnNpb24sXG4gICAgICBwcmV2aW91c0hhc2g6IGNvbnRleHQucHJldmlvdXNIYXNoLFxuICAgICAgYmxvY2tJbmRleDogY29udGV4dC5ibG9ja0luZGV4LFxuICAgICAgdmFsaWRhdG9ySW5kZXg6IGNvbnRleHQubXlJbmRleCxcbiAgICAgIGNvbnNlbnN1c01lc3NhZ2UsXG4gICAgfSksXG5cbiAgICBwcml2YXRlS2V5LFxuICApO1xuXG4gIG5vZGUucmVsYXlDb25zZW5zdXNQYXlsb2FkKHBheWxvYWQpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEluaXRpYWxDb250ZXh0QWRkID0gKHtcbiAgYmxvY2tjaGFpbixcbiAgcHVibGljS2V5LFxuICB2YWxpZGF0b3JzLFxuICBibG9ja1JlY2VpdmVkVGltZVNlY29uZHMsXG59OiB7XG4gIHJlYWRvbmx5IGJsb2NrY2hhaW46IEJsb2NrY2hhaW47XG4gIHJlYWRvbmx5IHB1YmxpY0tleTogRUNQb2ludDtcbiAgcmVhZG9ubHkgdmFsaWRhdG9yczogUmVhZG9ubHlBcnJheTxFQ1BvaW50PjtcbiAgcmVhZG9ubHkgYmxvY2tSZWNlaXZlZFRpbWVTZWNvbmRzPzogbnVtYmVyO1xufSkgPT4ge1xuICBjb25zdCBibG9ja0luZGV4ID0gYmxvY2tjaGFpbi5jdXJyZW50QmxvY2suaW5kZXggKyAxO1xuICBjb25zdCBwcmltYXJ5SW5kZXggPSBibG9ja0luZGV4ICUgdmFsaWRhdG9ycy5sZW5ndGg7XG4gIGNvbnN0IG15SW5kZXggPSBfLmZpbmRJbmRleCh2YWxpZGF0b3JzLCAodmFsaWRhdG9yKSA9PiBjb21tb24uZWNQb2ludEVxdWFsKHZhbGlkYXRvciwgcHVibGljS2V5KSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBwcmltYXJ5SW5kZXggPT09IG15SW5kZXggPyAncHJpbWFyeScgOiAnYmFja3VwJyxcbiAgICBwcmV2aW91c0hhc2g6IGJsb2NrY2hhaW4uY3VycmVudEJsb2NrLmhhc2gsXG4gICAgYmxvY2tJbmRleCxcbiAgICB2aWV3TnVtYmVyOiAwLFxuICAgIG15SW5kZXgsXG4gICAgcHJpbWFyeUluZGV4LFxuICAgIGV4cGVjdGVkVmlldzogXy5yYW5nZSgwLCB2YWxpZGF0b3JzLmxlbmd0aCkubWFwKCgpID0+IDApLFxuICAgIHZhbGlkYXRvcnMsXG4gICAgYmxvY2tSZWNlaXZlZFRpbWVTZWNvbmRzLFxuICB9O1xufTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUNvbnNlbnN1c0NvbW1vbjxUQ29udGV4dCBleHRlbmRzIEluaXRpYWxDb250ZXh0IHwgU2lnbmF0dXJlU2VudENvbnRleHQ+KHtcbiAgY29udGV4dCxcbiAgYmxvY2tjaGFpbixcbiAgY29uc2Vuc3VzQ29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgY29udGV4dDogVENvbnRleHQ7XG4gIHJlYWRvbmx5IGJsb2NrY2hhaW46IEJsb2NrY2hhaW47XG4gIHJlYWRvbmx5IGNvbnNlbnN1c0NvbnRleHQ6IENvbnNlbnN1c0NvbnRleHQ7XG59KTogUmVzdWx0PFRDb250ZXh0PiB7XG4gIGlmIChjb250ZXh0Lm15SW5kZXggPCAwKSB7XG4gICAgcmV0dXJuIHsgY29udGV4dCB9O1xuICB9XG5cbiAgaWYgKGNvbnRleHQudHlwZSA9PT0gJ3ByaW1hcnknKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRleHQsXG4gICAgICB0aW1lclNlY29uZHM6IE1hdGgubWF4KFxuICAgICAgICAwLFxuICAgICAgICBibG9ja2NoYWluLnNldHRpbmdzLnNlY29uZHNQZXJCbG9jayAtIChjb25zZW5zdXNDb250ZXh0Lm5vd1NlY29uZHMoKSAtIGNvbnRleHQuYmxvY2tSZWNlaXZlZFRpbWVTZWNvbmRzKSxcbiAgICAgICksXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0IHsgc2Vjb25kc1BlckJsb2NrIH0gPSBibG9ja2NoYWluLnNldHRpbmdzO1xuXG4gIHJldHVybiB7XG4gICAgY29udGV4dCxcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgIHRpbWVyU2Vjb25kczogc2Vjb25kc1BlckJsb2NrIDw8IChjb250ZXh0LnZpZXdOdW1iZXIgKyAxKSxcbiAgfTtcbn1cblxuZXhwb3J0IGNvbnN0IGluaXRpYWxpemVOZXdDb25zZW5zdXMgPSBhc3luYyAoe1xuICBibG9ja2NoYWluLFxuICBwdWJsaWNLZXksXG4gIGNvbnNlbnN1c0NvbnRleHQsXG59OiB7XG4gIHJlYWRvbmx5IGJsb2NrY2hhaW46IEJsb2NrY2hhaW47XG4gIHJlYWRvbmx5IHB1YmxpY0tleTogRUNQb2ludDtcbiAgcmVhZG9ubHkgY29uc2Vuc3VzQ29udGV4dDogQ29uc2Vuc3VzQ29udGV4dDtcbn0pOiBQcm9taXNlPFJlc3VsdDxJbml0aWFsQ29udGV4dD4+ID0+IHtcbiAgY29uc3QgdmFsaWRhdG9ycyA9IGF3YWl0IGJsb2NrY2hhaW4uZ2V0VmFsaWRhdG9ycyhbXSk7XG4gIGNvbnN0IGJsb2NrUmVjZWl2ZWRUaW1lU2Vjb25kcyA9IGJsb2NrY2hhaW4uY3VycmVudEJsb2NrLnRpbWVzdGFtcDtcbiAgY29uc3QgYmxvY2tJbmRleCA9IGJsb2NrY2hhaW4uY3VycmVudEJsb2NrLmluZGV4ICsgMTtcbiAgY29uc3QgcHJpbWFyeUluZGV4ID0gYmxvY2tJbmRleCAlIHZhbGlkYXRvcnMubGVuZ3RoO1xuICBjb25zdCBteUluZGV4ID0gXy5maW5kSW5kZXgodmFsaWRhdG9ycywgKHZhbGlkYXRvcikgPT4gY29tbW9uLmVjUG9pbnRFcXVhbCh2YWxpZGF0b3IsIHB1YmxpY0tleSkpO1xuXG4gIGNvbnN0IGNvbnRleHQgPSBuZXcgSW5pdGlhbENvbnRleHQoe1xuICAgIHR5cGU6IHByaW1hcnlJbmRleCA9PT0gbXlJbmRleCA/ICdwcmltYXJ5JyA6ICdiYWNrdXAnLFxuICAgIHByZXZpb3VzSGFzaDogYmxvY2tjaGFpbi5jdXJyZW50QmxvY2suaGFzaCxcbiAgICBibG9ja0luZGV4LFxuICAgIHZpZXdOdW1iZXI6IDAsXG4gICAgbXlJbmRleCxcbiAgICBwcmltYXJ5SW5kZXgsXG4gICAgZXhwZWN0ZWRWaWV3OiBfLnJhbmdlKDAsIHZhbGlkYXRvcnMubGVuZ3RoKS5tYXAoKCkgPT4gMCksXG4gICAgdmFsaWRhdG9ycyxcbiAgICBibG9ja1JlY2VpdmVkVGltZVNlY29uZHMsXG4gIH0pO1xuXG4gIHJldHVybiBpbml0aWFsaXplQ29uc2Vuc3VzQ29tbW9uKHsgY29udGV4dCwgYmxvY2tjaGFpbiwgY29uc2Vuc3VzQ29udGV4dCB9KTtcbn07XG5cbmNvbnN0IGdldFByaW1hcnlJbmRleFR5cGUgPSAoe1xuICBjb250ZXh0LFxuICB2aWV3TnVtYmVyLFxufToge1xuICByZWFkb25seSBjb250ZXh0OiBDb250ZXh0O1xuICByZWFkb25seSB2aWV3TnVtYmVyOiBudW1iZXI7XG59KToge1xuICByZWFkb25seSB0eXBlOiBUeXBlO1xuICByZWFkb25seSBwcmltYXJ5SW5kZXg6IG51bWJlcjtcbn0gPT4ge1xuICBsZXQgcHJpbWFyeUluZGV4ID0gKGNvbnRleHQuYmxvY2tJbmRleCAtIHZpZXdOdW1iZXIpICUgY29udGV4dC52YWxpZGF0b3JzLmxlbmd0aDtcbiAgaWYgKHByaW1hcnlJbmRleCA8IDApIHtcbiAgICBwcmltYXJ5SW5kZXggKz0gY29udGV4dC52YWxpZGF0b3JzLmxlbmd0aDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdHlwZTogcHJpbWFyeUluZGV4ID09PSBjb250ZXh0Lm15SW5kZXggPyAncHJpbWFyeScgOiAnYmFja3VwJyxcbiAgICBwcmltYXJ5SW5kZXgsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZUNvbnNlbnN1cyA9ICh7XG4gIG5vZGUsXG4gIGNvbnRleHQ6IGNvbnRleHRJbixcbiAgdmlld051bWJlcixcbiAgY29uc2Vuc3VzQ29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgY29udGV4dDogQ29udGV4dDtcbiAgcmVhZG9ubHkgdmlld051bWJlcjogbnVtYmVyO1xuICByZWFkb25seSBjb25zZW5zdXNDb250ZXh0OiBDb25zZW5zdXNDb250ZXh0O1xufSk6IFJlc3VsdDxJbml0aWFsQ29udGV4dCB8IFNpZ25hdHVyZVNlbnRDb250ZXh0PiA9PiB7XG4gIGlmICh2aWV3TnVtYmVyIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Byb2dyYW1taW5nIGVycm9yJyk7XG4gIH1cbiAgY29uc3QgeyBibG9ja2NoYWluIH0gPSBub2RlO1xuICBsZXQgY29udGV4dCA9IGNvbnRleHRJbjtcbiAgbGV0IHByaW1hcnlJbmRleCA9IChjb250ZXh0LmJsb2NrSW5kZXggLSB2aWV3TnVtYmVyKSAlIGNvbnRleHQudmFsaWRhdG9ycy5sZW5ndGg7XG4gIGlmIChwcmltYXJ5SW5kZXggPCAwKSB7XG4gICAgcHJpbWFyeUluZGV4ICs9IGNvbnRleHQudmFsaWRhdG9ycy5sZW5ndGg7XG4gIH1cbiAgY29uc3QgdHlwZSA9IHByaW1hcnlJbmRleCA9PT0gY29udGV4dC5teUluZGV4ID8gJ3ByaW1hcnknIDogJ2JhY2t1cCc7XG4gIGNvbnRleHQgPVxuICAgIHR5cGUgPT09ICdwcmltYXJ5JyAmJiBjb250ZXh0IGluc3RhbmNlb2YgU2lnbmF0dXJlU2VudENvbnRleHRcbiAgICAgID8gY29udGV4dC5jbG9uZSh7IHR5cGUsIHByaW1hcnlJbmRleCwgdmlld051bWJlciB9KVxuICAgICAgOiBjbG9uZUluaXRpYWwoY29udGV4dCwgeyB0eXBlLCBwcmltYXJ5SW5kZXgsIHZpZXdOdW1iZXIgfSk7XG5cbiAgcmV0dXJuIGluaXRpYWxpemVDb25zZW5zdXNDb21tb24oeyBibG9ja2NoYWluLCBjb250ZXh0LCBjb25zZW5zdXNDb250ZXh0IH0pO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNoZWNrU2lnbmF0dXJlczxUQ29udGV4dCBleHRlbmRzIEhlYWRlckNvbnRleHQ+KHtcbiAgbm9kZSxcbiAgY29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgY29udGV4dDogVENvbnRleHQ7XG59KTogUHJvbWlzZTxSZXN1bHQ8VENvbnRleHQgfCBCbG9ja1NlbnRDb250ZXh0Pj4ge1xuICBjb25zdCBzaWduYXR1cmVzTGVuZ3RoID0gY29udGV4dC5zaWduYXR1cmVzLmZpbHRlcigocCkgPT4gcCAhPT0gdW5kZWZpbmVkKS5sZW5ndGg7XG5cbiAgaWYgKFxuICAgIHNpZ25hdHVyZXNMZW5ndGggPj0gY29udGV4dC5NICYmXG4gICAgY29udGV4dC50cmFuc2FjdGlvbkhhc2hlcy5ldmVyeSgoaGFzaCkgPT4gY29udGV4dC50cmFuc2FjdGlvbnNbaGFzaF0gIT09IHVuZGVmaW5lZClcbiAgKSB7XG4gICAgY29uc3QgbXV0YWJsZVB1YmxpY0tleVRvU2lnbmF0dXJlOiB7IFtrZXk6IHN0cmluZ106IEJ1ZmZlciB9ID0ge307XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gICAgZm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgY29udGV4dC52YWxpZGF0b3JzLmxlbmd0aCAmJiBqIDwgY29udGV4dC5NOyBpICs9IDEpIHtcbiAgICAgIGNvbnN0IHZhbGlkYXRvciA9IGNvbnRleHQudmFsaWRhdG9yc1tpXTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGNvbnRleHQuc2lnbmF0dXJlc1tpXTtcbiAgICAgIGlmIChzaWduYXR1cmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBtdXRhYmxlUHVibGljS2V5VG9TaWduYXR1cmVbY29tbW9uLmVjUG9pbnRUb0hleCh2YWxpZGF0b3IpXSA9IHNpZ25hdHVyZTtcbiAgICAgICAgaiArPSAxO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBzY3JpcHQgPSBjcnlwdG8uY3JlYXRlTXVsdGlTaWduYXR1cmVXaXRuZXNzKFxuICAgICAgY29udGV4dC5NLFxuICAgICAgY29udGV4dC52YWxpZGF0b3JzLFxuICAgICAgbXV0YWJsZVB1YmxpY0tleVRvU2lnbmF0dXJlLFxuICAgICAgV2l0bmVzcyxcbiAgICApO1xuXG4gICAgY29uc3QgYmxvY2sgPSBjb250ZXh0LmhlYWRlci5jbG9uZSh7XG4gICAgICB0cmFuc2FjdGlvbnM6IGNvbnRleHQudHJhbnNhY3Rpb25IYXNoZXMubWFwKChoYXNoKSA9PiBjb250ZXh0LnRyYW5zYWN0aW9uc1toYXNoXSkuZmlsdGVyKGNvbW1vblV0aWxzLm5vdE51bGwpLFxuICAgICAgc2NyaXB0LFxuICAgIH0pO1xuXG4gICAgYXdhaXQgbm9kZS5yZWxheUJsb2NrKGJsb2NrKTtcblxuICAgIHJldHVybiB7IGNvbnRleHQ6IGNsb25lQmxvY2tTZW50KGNvbnRleHQpIH07XG4gIH1cblxuICByZXR1cm4geyBjb250ZXh0IH07XG59XG5cbmV4cG9ydCBjb25zdCBzaWduQW5kUmVsYXlDaGFuZ2VWaWV3ID0gKHtcbiAgbm9kZSxcbiAgcHJpdmF0ZUtleSxcbiAgY29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgcHJpdmF0ZUtleTogUHJpdmF0ZUtleTtcbiAgcmVhZG9ubHkgY29udGV4dDogQ29udGV4dDtcbn0pID0+IHtcbiAgc2lnbkFuZFJlbGF5KHtcbiAgICBub2RlLFxuICAgIHByaXZhdGVLZXksXG4gICAgY29udGV4dCxcbiAgICBjb25zZW5zdXNNZXNzYWdlOiBuZXcgQ2hhbmdlVmlld0NvbnNlbnN1c01lc3NhZ2Uoe1xuICAgICAgdmlld051bWJlcjogY29udGV4dC52aWV3TnVtYmVyLFxuICAgICAgbmV3Vmlld051bWJlcjogY29udGV4dC5leHBlY3RlZFZpZXdbY29udGV4dC5teUluZGV4XSxcbiAgICB9KSxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgY2hlY2tFeHBlY3RlZFZpZXcgPSAoe1xuICBjb250ZXh0LFxuICB2aWV3TnVtYmVyLFxufToge1xuICByZWFkb25seSBjb250ZXh0OiBDb250ZXh0O1xuICByZWFkb25seSB2aWV3TnVtYmVyOiBudW1iZXI7XG59KSA9PiBjb250ZXh0LnZpZXdOdW1iZXIgIT09IHZpZXdOdW1iZXIgJiYgY29udGV4dC5leHBlY3RlZFZpZXcuZmlsdGVyKChwKSA9PiBwID09PSB2aWV3TnVtYmVyKS5sZW5ndGggPj0gY29udGV4dC5NO1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZUNvbnNlbnN1c0luaXRpYWwgPSAoe1xuICBibG9ja2NoYWluLFxuICBjb250ZXh0LFxuICB2aWV3TnVtYmVyLFxuICBjb25zZW5zdXNDb250ZXh0LFxufToge1xuICByZWFkb25seSBibG9ja2NoYWluOiBCbG9ja2NoYWluO1xuICByZWFkb25seSBjb250ZXh0OiBDb250ZXh0O1xuICByZWFkb25seSB2aWV3TnVtYmVyOiBudW1iZXI7XG4gIHJlYWRvbmx5IGNvbnNlbnN1c0NvbnRleHQ6IENvbnNlbnN1c0NvbnRleHQ7XG59KTogUmVzdWx0PEluaXRpYWxDb250ZXh0PiA9PiB7XG4gIGNvbnN0IHsgcHJpbWFyeUluZGV4LCB0eXBlIH0gPSBnZXRQcmltYXJ5SW5kZXhUeXBlKHsgY29udGV4dCwgdmlld051bWJlciB9KTtcblxuICByZXR1cm4gaW5pdGlhbGl6ZUNvbnNlbnN1c0NvbW1vbih7XG4gICAgYmxvY2tjaGFpbixcbiAgICBjb250ZXh0OiBjbG9uZUluaXRpYWwoY29udGV4dCwgeyB0eXBlLCBwcmltYXJ5SW5kZXgsIHZpZXdOdW1iZXIgfSksXG4gICAgY29uc2Vuc3VzQ29udGV4dCxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgaW5jcmVtZW50RXhwZWN0ZWRWaWV3ID0gKGNvbnRleHQ6IENvbnRleHQpOiBSZWFkb25seUFycmF5PG51bWJlcj4gPT4ge1xuICBjb25zdCBtdXRhYmxlRXhwZWN0ZWRWaWV3ID0gWy4uLmNvbnRleHQuZXhwZWN0ZWRWaWV3XTtcbiAgbXV0YWJsZUV4cGVjdGVkVmlld1tjb250ZXh0Lm15SW5kZXhdICs9IDE7XG5cbiAgcmV0dXJuIG11dGFibGVFeHBlY3RlZFZpZXc7XG59O1xuXG5jb25zdCByZXF1ZXN0Q2hhbmdlVmlld0JhY2t1cCA9ICh7XG4gIGNvbnRleHQ6IGNvbnRleHRJbixcbiAgbm9kZSxcbiAgcHJpdmF0ZUtleSxcbiAgY29uc2Vuc3VzQ29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgY29udGV4dDogUmVxdWVzdFJlY2VpdmVkQ29udGV4dDtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgcHJpdmF0ZUtleTogUHJpdmF0ZUtleTtcbiAgcmVhZG9ubHkgY29uc2Vuc3VzQ29udGV4dDogQ29uc2Vuc3VzQ29udGV4dDtcbn0pOiBSZXN1bHQ8SW5pdGlhbENvbnRleHQgfCBWaWV3Q2hhbmdpbmdDb250ZXh0PiA9PiB7XG4gIGNvbnN0IGNvbnRleHQgPSBjb250ZXh0SW4uY2xvbmVWaWV3Q2hhbmdpbmcoe1xuICAgIGV4cGVjdGVkVmlldzogaW5jcmVtZW50RXhwZWN0ZWRWaWV3KGNvbnRleHRJbiksXG4gIH0pO1xuXG4gIHNpZ25BbmRSZWxheUNoYW5nZVZpZXcoeyBjb250ZXh0LCBub2RlLCBwcml2YXRlS2V5IH0pO1xuXG4gIGNvbnN0IHZpZXdOdW1iZXIgPSBjb250ZXh0LmV4cGVjdGVkVmlld1tjb250ZXh0Lm15SW5kZXhdO1xuICBpZiAoY2hlY2tFeHBlY3RlZFZpZXcoeyBjb250ZXh0LCB2aWV3TnVtYmVyIH0pKSB7XG4gICAgcmV0dXJuIGluaXRpYWxpemVDb25zZW5zdXNJbml0aWFsKHtcbiAgICAgIGJsb2NrY2hhaW46IG5vZGUuYmxvY2tjaGFpbixcbiAgICAgIGNvbnRleHQsXG4gICAgICB2aWV3TnVtYmVyLFxuICAgICAgY29uc2Vuc3VzQ29udGV4dCxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB7IGNvbnRleHQgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBhZGRUcmFuc2FjdGlvbiA9IGFzeW5jICh7XG4gIGNvbnRleHQ6IGNvbnRleHRJbixcbiAgbm9kZSxcbiAgcHJpdmF0ZUtleSxcbiAgdHJhbnNhY3Rpb24sXG4gIHZlcmlmeSxcbiAgY29uc2Vuc3VzQ29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgY29udGV4dDogUmVxdWVzdFJlY2VpdmVkQ29udGV4dDtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgcHJpdmF0ZUtleTogUHJpdmF0ZUtleTtcbiAgcmVhZG9ubHkgdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uO1xuICByZWFkb25seSB2ZXJpZnk6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNvbnNlbnN1c0NvbnRleHQ6IENvbnNlbnN1c0NvbnRleHQ7XG59KTogUHJvbWlzZTxcbiAgUmVzdWx0PFJlcXVlc3RSZWNlaXZlZENvbnRleHQgfCBJbml0aWFsQ29udGV4dCB8IFZpZXdDaGFuZ2luZ0NvbnRleHQgfCBTaWduYXR1cmVTZW50Q29udGV4dCB8IEJsb2NrU2VudENvbnRleHQ+XG4+ID0+IHtcbiAgbGV0IGNvbnRleHQgPSBjb250ZXh0SW47XG4gIGNvbnN0IHsgYmxvY2tjaGFpbiB9ID0gbm9kZTtcbiAgY29uc3QgdHggPSBhd2FpdCBibG9ja2NoYWluLnRyYW5zYWN0aW9uLnRyeUdldCh7IGhhc2g6IHRyYW5zYWN0aW9uLmhhc2ggfSk7XG4gIGlmICh0eCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHsgY29udGV4dCB9O1xuICB9XG4gIGlmICh2ZXJpZnkpIHtcbiAgICBsZXQgdmVyaWZpZWQgPSB0cnVlO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IHZlcmlmaWNhdGlvbnMgfSA9IGF3YWl0IGJsb2NrY2hhaW4udmVyaWZ5VHJhbnNhY3Rpb24oe1xuICAgICAgICB0cmFuc2FjdGlvbixcbiAgICAgICAgbWVtUG9vbDogT2JqZWN0LnZhbHVlcyhjb250ZXh0LnRyYW5zYWN0aW9ucykuZmlsdGVyKGNvbW1vblV0aWxzLm5vdE51bGwpLFxuICAgICAgfSk7XG4gICAgICB2ZXJpZmllZCA9IHZlcmlmaWNhdGlvbnMuZXZlcnkoKHsgZmFpbHVyZU1lc3NhZ2UgfSkgPT4gZmFpbHVyZU1lc3NhZ2UgPT09IHVuZGVmaW5lZCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICB2ZXJpZmllZCA9IGZhbHNlO1xuICAgIH1cbiAgICBpZiAoIXZlcmlmaWVkKSB7XG4gICAgICByZXR1cm4geyBjb250ZXh0IH07XG4gICAgfVxuICB9XG5cbiAgY29udGV4dCA9IGNvbnRleHQuY2xvbmUoe1xuICAgIHRyYW5zYWN0aW9uczoge1xuICAgICAgLi4uY29udGV4dC50cmFuc2FjdGlvbnMsXG4gICAgICBbdHJhbnNhY3Rpb24uaGFzaEhleF06IHRyYW5zYWN0aW9uLFxuICAgIH0sXG4gIH0pO1xuXG4gIGNvbnN0IHRyYW5zYWN0aW9uc0xlbmd0aCA9IE9iamVjdC52YWx1ZXMoY29udGV4dC50cmFuc2FjdGlvbnMpLmxlbmd0aDtcbiAgaWYgKGNvbnRleHQudHJhbnNhY3Rpb25IYXNoZXMubGVuZ3RoID09PSB0cmFuc2FjdGlvbnNMZW5ndGgpIHtcbiAgICBjb25zdCB2YWxpZGF0b3JzID0gYXdhaXQgYmxvY2tjaGFpbi5nZXRWYWxpZGF0b3JzKE9iamVjdC52YWx1ZXMoY29udGV4dC50cmFuc2FjdGlvbnMpLmZpbHRlcihjb21tb25VdGlscy5ub3ROdWxsKSk7XG5cbiAgICBjb25zdCBjb25zZW5zdXNBZGRyZXNzID0gY3J5cHRvLmdldENvbnNlbnN1c0FkZHJlc3ModmFsaWRhdG9ycyk7XG4gICAgaWYgKGNvbW1vbi51SW50MTYwRXF1YWwoY29uc2Vuc3VzQWRkcmVzcywgY29udGV4dC5oZWFkZXIubmV4dENvbnNlbnN1cykpIHtcbiAgICAgIGNvbnN0IG11dGFibGVTaWduYXR1cmVzID0gWy4uLmNvbnRleHQuc2lnbmF0dXJlc107XG4gICAgICBtdXRhYmxlU2lnbmF0dXJlc1tjb250ZXh0Lm15SW5kZXhdID0gY3J5cHRvLnNpZ24oe1xuICAgICAgICBtZXNzYWdlOiBjb250ZXh0LmhlYWRlci5tZXNzYWdlLFxuICAgICAgICBwcml2YXRlS2V5LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IG5ld0NvbnRleHQgPSBjb250ZXh0LmNsb25lU2lnbmF0dXJlU2VudCh7IHNpZ25hdHVyZXM6IG11dGFibGVTaWduYXR1cmVzIH0pO1xuICAgICAgc2lnbkFuZFJlbGF5KHtcbiAgICAgICAgbm9kZSxcbiAgICAgICAgY29udGV4dDogbmV3Q29udGV4dCxcbiAgICAgICAgcHJpdmF0ZUtleSxcbiAgICAgICAgY29uc2Vuc3VzTWVzc2FnZTogbmV3IFByZXBhcmVSZXNwb25zZUNvbnNlbnN1c01lc3NhZ2Uoe1xuICAgICAgICAgIHZpZXdOdW1iZXI6IG5ld0NvbnRleHQudmlld051bWJlcixcbiAgICAgICAgICBzaWduYXR1cmU6IGNvbW1vblV0aWxzLm51bGx0aHJvd3MobXV0YWJsZVNpZ25hdHVyZXNbbmV3Q29udGV4dC5teUluZGV4XSksXG4gICAgICAgIH0pLFxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBjaGVja1NpZ25hdHVyZXMoeyBub2RlLCBjb250ZXh0OiBuZXdDb250ZXh0IH0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXF1ZXN0Q2hhbmdlVmlld0JhY2t1cCh7XG4gICAgICBjb250ZXh0LFxuICAgICAgbm9kZSxcbiAgICAgIHByaXZhdGVLZXksXG4gICAgICBjb25zZW5zdXNDb250ZXh0LFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHsgY29udGV4dCB9O1xufTtcbiJdfQ==