UNPKG

36.3 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 timerSeconds: secondsPerBlock << (context.viewNumber + 1),
49 };
50}
51exports.initializeNewConsensus = async ({ blockchain, publicKey, consensusContext, }) => {
52 const validators = await blockchain.getValidators([]);
53 const blockReceivedTimeSeconds = blockchain.currentBlock.timestamp;
54 const blockIndex = blockchain.currentBlock.index + 1;
55 const primaryIndex = blockIndex % validators.length;
56 const myIndex = lodash_1.default.findIndex(validators, (validator) => client_common_1.common.ecPointEqual(validator, publicKey));
57 const context = new context_1.InitialContext({
58 type: primaryIndex === myIndex ? 'primary' : 'backup',
59 previousHash: blockchain.currentBlock.hash,
60 blockIndex,
61 viewNumber: 0,
62 myIndex,
63 primaryIndex,
64 expectedView: lodash_1.default.range(0, validators.length).map(() => 0),
65 validators,
66 blockReceivedTimeSeconds,
67 });
68 return initializeConsensusCommon({ context, blockchain, consensusContext });
69};
70const getPrimaryIndexType = ({ context, viewNumber, }) => {
71 let primaryIndex = (context.blockIndex - viewNumber) % context.validators.length;
72 if (primaryIndex < 0) {
73 primaryIndex += context.validators.length;
74 }
75 return {
76 type: primaryIndex === context.myIndex ? 'primary' : 'backup',
77 primaryIndex,
78 };
79};
80exports.initializeConsensus = ({ node, context: contextIn, viewNumber, consensusContext, }) => {
81 if (viewNumber <= 0) {
82 throw new Error('Programming error');
83 }
84 const { blockchain } = node;
85 let context = contextIn;
86 let primaryIndex = (context.blockIndex - viewNumber) % context.validators.length;
87 if (primaryIndex < 0) {
88 primaryIndex += context.validators.length;
89 }
90 const type = primaryIndex === context.myIndex ? 'primary' : 'backup';
91 context =
92 type === 'primary' && context instanceof context_1.SignatureSentContext
93 ? context.clone({ type, primaryIndex, viewNumber })
94 : context_1.cloneInitial(context, { type, primaryIndex, viewNumber });
95 return initializeConsensusCommon({ blockchain, context, consensusContext });
96};
97async function checkSignatures({ node, context, }) {
98 const signaturesLength = context.signatures.filter((p) => p !== undefined).length;
99 if (signaturesLength >= context.M &&
100 context.transactionHashes.every((hash) => context.transactions[hash] !== undefined)) {
101 const mutablePublicKeyToSignature = {};
102 for (let i = 0, j = 0; i < context.validators.length && j < context.M; i += 1) {
103 const validator = context.validators[i];
104 const signature = context.signatures[i];
105 if (signature !== undefined) {
106 mutablePublicKeyToSignature[client_common_1.common.ecPointToHex(validator)] = signature;
107 j += 1;
108 }
109 }
110 const script = client_common_1.crypto.createMultiSignatureWitness(context.M, context.validators, mutablePublicKeyToSignature, node_core_1.Witness);
111 const block = context.header.clone({
112 transactions: context.transactionHashes.map((hash) => context.transactions[hash]).filter(utils_1.utils.notNull),
113 script,
114 });
115 await node.relayBlock(block);
116 return { context: context_1.cloneBlockSent(context) };
117 }
118 return { context };
119}
120exports.checkSignatures = checkSignatures;
121exports.signAndRelayChangeView = ({ node, privateKey, context, }) => {
122 exports.signAndRelay({
123 node,
124 privateKey,
125 context,
126 consensusMessage: new node_core_1.ChangeViewConsensusMessage({
127 viewNumber: context.viewNumber,
128 newViewNumber: context.expectedView[context.myIndex],
129 }),
130 });
131};
132exports.checkExpectedView = ({ context, viewNumber, }) => context.viewNumber !== viewNumber && context.expectedView.filter((p) => p === viewNumber).length >= context.M;
133exports.initializeConsensusInitial = ({ blockchain, context, viewNumber, consensusContext, }) => {
134 const { primaryIndex, type } = getPrimaryIndexType({ context, viewNumber });
135 return initializeConsensusCommon({
136 blockchain,
137 context: context_1.cloneInitial(context, { type, primaryIndex, viewNumber }),
138 consensusContext,
139 });
140};
141exports.incrementExpectedView = (context) => {
142 const mutableExpectedView = [...context.expectedView];
143 mutableExpectedView[context.myIndex] += 1;
144 return mutableExpectedView;
145};
146const requestChangeViewBackup = ({ context: contextIn, node, privateKey, consensusContext, }) => {
147 const context = contextIn.cloneViewChanging({
148 expectedView: exports.incrementExpectedView(contextIn),
149 });
150 exports.signAndRelayChangeView({ context, node, privateKey });
151 const viewNumber = context.expectedView[context.myIndex];
152 if (exports.checkExpectedView({ context, viewNumber })) {
153 return exports.initializeConsensusInitial({
154 blockchain: node.blockchain,
155 context,
156 viewNumber,
157 consensusContext,
158 });
159 }
160 return { context };
161};
162exports.addTransaction = async ({ context: contextIn, node, privateKey, transaction, verify, consensusContext, }) => {
163 let context = contextIn;
164 const { blockchain } = node;
165 const tx = await blockchain.transaction.tryGet({ hash: transaction.hash });
166 if (tx !== undefined) {
167 return { context };
168 }
169 if (verify) {
170 let verified = true;
171 try {
172 const { verifications } = await blockchain.verifyTransaction({
173 transaction,
174 memPool: Object.values(context.transactions).filter(utils_1.utils.notNull),
175 });
176 verified = verifications.every(({ failureMessage }) => failureMessage === undefined);
177 }
178 catch (_a) {
179 verified = false;
180 }
181 if (!verified) {
182 return { context };
183 }
184 }
185 context = context.clone({
186 transactions: Object.assign(Object.assign({}, context.transactions), { [transaction.hashHex]: transaction }),
187 });
188 const transactionsLength = Object.values(context.transactions).length;
189 if (context.transactionHashes.length === transactionsLength) {
190 const validators = await blockchain.getValidators(Object.values(context.transactions).filter(utils_1.utils.notNull));
191 const consensusAddress = client_common_1.crypto.getConsensusAddress(validators);
192 if (client_common_1.common.uInt160Equal(consensusAddress, context.header.nextConsensus)) {
193 const mutableSignatures = [...context.signatures];
194 mutableSignatures[context.myIndex] = client_common_1.crypto.sign({
195 message: context.header.message,
196 privateKey,
197 });
198 const newContext = context.cloneSignatureSent({ signatures: mutableSignatures });
199 exports.signAndRelay({
200 node,
201 context: newContext,
202 privateKey,
203 consensusMessage: new node_core_1.PrepareResponseConsensusMessage({
204 viewNumber: newContext.viewNumber,
205 signature: utils_1.utils.nullthrows(mutableSignatures[newContext.myIndex]),
206 }),
207 });
208 return checkSignatures({ node, context: newContext });
209 }
210 return requestChangeViewBackup({
211 context,
212 node,
213 privateKey,
214 consensusContext,
215 });
216 }
217 return { context };
218};
219
220//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUM7Z0JBQ1gsSUFBSTtnQkFDSixPQUFPLEVBQUUsVUFBVTtnQkFDbkIsVUFBVTtnQkFDVixnQkFBZ0IsRUFBRSxJQUFJLDJDQUErQixDQUFDO29CQUNwRCxVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVU7b0JBQ2pDLFNBQVMsRUFBRSxhQUFXLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztpQkFDekUsQ0FBQzthQUNILENBQUMsQ0FBQztZQUVILE9BQU8sZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1NBQ3ZEO1FBRUQsT0FBTyx1QkFBdUIsQ0FBQztZQUM3QixPQUFPO1lBQ1AsSUFBSTtZQUNKLFVBQVU7WUFDVixnQkFBZ0I7U0FDakIsQ0FBQyxDQUFDO0tBQ0o7SUFFRCxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFDckIsQ0FBQyxDQUFDIiwiZmlsZSI6Im5lby1vbmUtbm9kZS1jb25zZW5zdXMvc3JjL2NvbW1vbi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvbW1vbiwgY3J5cHRvLCBFQ1BvaW50LCBQcml2YXRlS2V5IH0gZnJvbSAnQG5lby1vbmUvY2xpZW50LWNvbW1vbic7XG5pbXBvcnQge1xuICBCbG9ja2NoYWluLFxuICBDaGFuZ2VWaWV3Q29uc2Vuc3VzTWVzc2FnZSxcbiAgQ29uc2Vuc3VzTWVzc2FnZSxcbiAgQ29uc2Vuc3VzUGF5bG9hZCxcbiAgTm9kZSxcbiAgUHJlcGFyZVJlc3BvbnNlQ29uc2Vuc3VzTWVzc2FnZSxcbiAgVHJhbnNhY3Rpb24sXG4gIFVuc2lnbmVkQ29uc2Vuc3VzUGF5bG9hZCxcbiAgV2l0bmVzcyxcbn0gZnJvbSAnQG5lby1vbmUvbm9kZS1jb3JlJztcbmltcG9ydCB7IHV0aWxzIGFzIGNvbW1vblV0aWxzIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IENvbnNlbnN1c0NvbnRleHQgfSBmcm9tICcuL0NvbnNlbnN1c0NvbnRleHQnO1xuaW1wb3J0IHtcbiAgQmxvY2tTZW50Q29udGV4dCxcbiAgY2xvbmVCbG9ja1NlbnQsXG4gIGNsb25lSW5pdGlhbCxcbiAgQ29udGV4dCxcbiAgSGVhZGVyQ29udGV4dCxcbiAgSW5pdGlhbENvbnRleHQsXG4gIFJlcXVlc3RSZWNlaXZlZENvbnRleHQsXG4gIFNpZ25hdHVyZVNlbnRDb250ZXh0LFxuICBUeXBlLFxuICBWaWV3Q2hhbmdpbmdDb250ZXh0LFxufSBmcm9tICcuL2NvbnRleHQnO1xuaW1wb3J0IHsgUmVzdWx0IH0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCBjb25zdCBzaWduQW5kUmVsYXkgPSAoe1xuICBub2RlLFxuICBwcml2YXRlS2V5LFxuICBjb250ZXh0LFxuICBjb25zZW5zdXNNZXNzYWdlLFxufToge1xuICByZWFkb25seSBub2RlOiBOb2RlO1xuICByZWFkb25seSBwcml2YXRlS2V5OiBQcml2YXRlS2V5O1xuICByZWFkb25seSBjb250ZXh0OiBDb250ZXh0O1xuICByZWFkb25seSBjb25zZW5zdXNNZXNzYWdlOiBDb25zZW5zdXNNZXNzYWdlO1xufSkgPT4ge1xuICBjb25zdCBwYXlsb2FkID0gQ29uc2Vuc3VzUGF5bG9hZC5zaWduKFxuICAgIG5ldyBVbnNpZ25lZENvbnNlbnN1c1BheWxvYWQoe1xuICAgICAgdmVyc2lvbjogY29udGV4dC52ZXJzaW9uLFxuICAgICAgcHJldmlvdXNIYXNoOiBjb250ZXh0LnByZXZpb3VzSGFzaCxcbiAgICAgIGJsb2NrSW5kZXg6IGNvbnRleHQuYmxvY2tJbmRleCxcbiAgICAgIHZhbGlkYXRvckluZGV4OiBjb250ZXh0Lm15SW5kZXgsXG4gICAgICBjb25zZW5zdXNNZXNzYWdlLFxuICAgIH0pLFxuXG4gICAgcHJpdmF0ZUtleSxcbiAgKTtcblxuICBub2RlLnJlbGF5Q29uc2Vuc3VzUGF5bG9hZChwYXlsb2FkKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRJbml0aWFsQ29udGV4dEFkZCA9ICh7XG4gIGJsb2NrY2hhaW4sXG4gIHB1YmxpY0tleSxcbiAgdmFsaWRhdG9ycyxcbiAgYmxvY2tSZWNlaXZlZFRpbWVTZWNvbmRzLFxufToge1xuICByZWFkb25seSBibG9ja2NoYWluOiBCbG9ja2NoYWluO1xuICByZWFkb25seSBwdWJsaWNLZXk6IEVDUG9pbnQ7XG4gIHJlYWRvbmx5IHZhbGlkYXRvcnM6IHJlYWRvbmx5IEVDUG9pbnRbXTtcbiAgcmVhZG9ubHkgYmxvY2tSZWNlaXZlZFRpbWVTZWNvbmRzPzogbnVtYmVyO1xufSkgPT4ge1xuICBjb25zdCBibG9ja0luZGV4ID0gYmxvY2tjaGFpbi5jdXJyZW50QmxvY2suaW5kZXggKyAxO1xuICBjb25zdCBwcmltYXJ5SW5kZXggPSBibG9ja0luZGV4ICUgdmFsaWRhdG9ycy5sZW5ndGg7XG4gIGNvbnN0IG15SW5kZXggPSBfLmZpbmRJbmRleCh2YWxpZGF0b3JzLCAodmFsaWRhdG9yKSA9PiBjb21tb24uZWNQb2ludEVxdWFsKHZhbGlkYXRvciwgcHVibGljS2V5KSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBwcmltYXJ5SW5kZXggPT09IG15SW5kZXggPyAncHJpbWFyeScgOiAnYmFja3VwJyxcbiAgICBwcmV2aW91c0hhc2g6IGJsb2NrY2hhaW4uY3VycmVudEJsb2NrLmhhc2gsXG4gICAgYmxvY2tJbmRleCxcbiAgICB2aWV3TnVtYmVyOiAwLFxuICAgIG15SW5kZXgsXG4gICAgcHJpbWFyeUluZGV4LFxuICAgIGV4cGVjdGVkVmlldzogXy5yYW5nZSgwLCB2YWxpZGF0b3JzLmxlbmd0aCkubWFwKCgpID0+IDApLFxuICAgIHZhbGlkYXRvcnMsXG4gICAgYmxvY2tSZWNlaXZlZFRpbWVTZWNvbmRzLFxuICB9O1xufTtcblxuZnVuY3Rpb24gaW5pdGlhbGl6ZUNvbnNlbnN1c0NvbW1vbjxUQ29udGV4dCBleHRlbmRzIEluaXRpYWxDb250ZXh0IHwgU2lnbmF0dXJlU2VudENvbnRleHQ+KHtcbiAgY29udGV4dCxcbiAgYmxvY2tjaGFpbixcbiAgY29uc2Vuc3VzQ29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgY29udGV4dDogVENvbnRleHQ7XG4gIHJlYWRvbmx5IGJsb2NrY2hhaW46IEJsb2NrY2hhaW47XG4gIHJlYWRvbmx5IGNvbnNlbnN1c0NvbnRleHQ6IENvbnNlbnN1c0NvbnRleHQ7XG59KTogUmVzdWx0PFRDb250ZXh0PiB7XG4gIGlmIChjb250ZXh0Lm15SW5kZXggPCAwKSB7XG4gICAgcmV0dXJuIHsgY29udGV4dCB9O1xuICB9XG5cbiAgaWYgKGNvbnRleHQudHlwZSA9PT0gJ3ByaW1hcnknKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRleHQsXG4gICAgICB0aW1lclNlY29uZHM6IE1hdGgubWF4KFxuICAgICAgICAwLFxuICAgICAgICBibG9ja2NoYWluLnNldHRpbmdzLnNlY29uZHNQZXJCbG9jayAtIChjb25zZW5zdXNDb250ZXh0Lm5vd1NlY29uZHMoKSAtIGNvbnRleHQuYmxvY2tSZWNlaXZlZFRpbWVTZWNvbmRzKSxcbiAgICAgICksXG4gICAgfTtcbiAgfVxuXG4gIGNvbnN0IHsgc2Vjb25kc1BlckJsb2NrIH0gPSBibG9ja2NoYWluLnNldHRpbmdzO1xuXG4gIHJldHVybiB7XG4gICAgY29udGV4dCxcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgIHRpbWVyU2Vjb25kczogc2Vjb25kc1BlckJsb2NrIDw8IChjb250ZXh0LnZpZXdOdW1iZXIgKyAxKSxcbiAgfTtcbn1cblxuZXhwb3J0IGNvbnN0IGluaXRpYWxpemVOZXdDb25zZW5zdXMgPSBhc3luYyAoe1xuICBibG9ja2NoYWluLFxuICBwdWJsaWNLZXksXG4gIGNvbnNlbnN1c0NvbnRleHQsXG59OiB7XG4gIHJlYWRvbmx5IGJsb2NrY2hhaW46IEJsb2NrY2hhaW47XG4gIHJlYWRvbmx5IHB1YmxpY0tleTogRUNQb2ludDtcbiAgcmVhZG9ubHkgY29uc2Vuc3VzQ29udGV4dDogQ29uc2Vuc3VzQ29udGV4dDtcbn0pOiBQcm9taXNlPFJlc3VsdDxJbml0aWFsQ29udGV4dD4+ID0+IHtcbiAgY29uc3QgdmFsaWRhdG9ycyA9IGF3YWl0IGJsb2NrY2hhaW4uZ2V0VmFsaWRhdG9ycyhbXSk7XG4gIGNvbnN0IGJsb2NrUmVjZWl2ZWRUaW1lU2Vjb25kcyA9IGJsb2NrY2hhaW4uY3VycmVudEJsb2NrLnRpbWVzdGFtcDtcbiAgY29uc3QgYmxvY2tJbmRleCA9IGJsb2NrY2hhaW4uY3VycmVudEJsb2NrLmluZGV4ICsgMTtcbiAgY29uc3QgcHJpbWFyeUluZGV4ID0gYmxvY2tJbmRleCAlIHZhbGlkYXRvcnMubGVuZ3RoO1xuICBjb25zdCBteUluZGV4ID0gXy5maW5kSW5kZXgodmFsaWRhdG9ycywgKHZhbGlkYXRvcikgPT4gY29tbW9uLmVjUG9pbnRFcXVhbCh2YWxpZGF0b3IsIHB1YmxpY0tleSkpO1xuXG4gIGNvbnN0IGNvbnRleHQgPSBuZXcgSW5pdGlhbENvbnRleHQoe1xuICAgIHR5cGU6IHByaW1hcnlJbmRleCA9PT0gbXlJbmRleCA/ICdwcmltYXJ5JyA6ICdiYWNrdXAnLFxuICAgIHByZXZpb3VzSGFzaDogYmxvY2tjaGFpbi5jdXJyZW50QmxvY2suaGFzaCxcbiAgICBibG9ja0luZGV4LFxuICAgIHZpZXdOdW1iZXI6IDAsXG4gICAgbXlJbmRleCxcbiAgICBwcmltYXJ5SW5kZXgsXG4gICAgZXhwZWN0ZWRWaWV3OiBfLnJhbmdlKDAsIHZhbGlkYXRvcnMubGVuZ3RoKS5tYXAoKCkgPT4gMCksXG4gICAgdmFsaWRhdG9ycyxcbiAgICBibG9ja1JlY2VpdmVkVGltZVNlY29uZHMsXG4gIH0pO1xuXG4gIHJldHVybiBpbml0aWFsaXplQ29uc2Vuc3VzQ29tbW9uKHsgY29udGV4dCwgYmxvY2tjaGFpbiwgY29uc2Vuc3VzQ29udGV4dCB9KTtcbn07XG5cbmNvbnN0IGdldFByaW1hcnlJbmRleFR5cGUgPSAoe1xuICBjb250ZXh0LFxuICB2aWV3TnVtYmVyLFxufToge1xuICByZWFkb25seSBjb250ZXh0OiBDb250ZXh0O1xuICByZWFkb25seSB2aWV3TnVtYmVyOiBudW1iZXI7XG59KToge1xuICByZWFkb25seSB0eXBlOiBUeXBlO1xuICByZWFkb25seSBwcmltYXJ5SW5kZXg6IG51bWJlcjtcbn0gPT4ge1xuICBsZXQgcHJpbWFyeUluZGV4ID0gKGNvbnRleHQuYmxvY2tJbmRleCAtIHZpZXdOdW1iZXIpICUgY29udGV4dC52YWxpZGF0b3JzLmxlbmd0aDtcbiAgaWYgKHByaW1hcnlJbmRleCA8IDApIHtcbiAgICBwcmltYXJ5SW5kZXggKz0gY29udGV4dC52YWxpZGF0b3JzLmxlbmd0aDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdHlwZTogcHJpbWFyeUluZGV4ID09PSBjb250ZXh0Lm15SW5kZXggPyAncHJpbWFyeScgOiAnYmFja3VwJyxcbiAgICBwcmltYXJ5SW5kZXgsXG4gIH07XG59O1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZUNvbnNlbnN1cyA9ICh7XG4gIG5vZGUsXG4gIGNvbnRleHQ6IGNvbnRleHRJbixcbiAgdmlld051bWJlcixcbiAgY29uc2Vuc3VzQ29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgY29udGV4dDogQ29udGV4dDtcbiAgcmVhZG9ubHkgdmlld051bWJlcjogbnVtYmVyO1xuICByZWFkb25seSBjb25zZW5zdXNDb250ZXh0OiBDb25zZW5zdXNDb250ZXh0O1xufSk6IFJlc3VsdDxJbml0aWFsQ29udGV4dCB8IFNpZ25hdHVyZVNlbnRDb250ZXh0PiA9PiB7XG4gIGlmICh2aWV3TnVtYmVyIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Byb2dyYW1taW5nIGVycm9yJyk7XG4gIH1cbiAgY29uc3QgeyBibG9ja2NoYWluIH0gPSBub2RlO1xuICBsZXQgY29udGV4dCA9IGNvbnRleHRJbjtcbiAgbGV0IHByaW1hcnlJbmRleCA9IChjb250ZXh0LmJsb2NrSW5kZXggLSB2aWV3TnVtYmVyKSAlIGNvbnRleHQudmFsaWRhdG9ycy5sZW5ndGg7XG4gIGlmIChwcmltYXJ5SW5kZXggPCAwKSB7XG4gICAgcHJpbWFyeUluZGV4ICs9IGNvbnRleHQudmFsaWRhdG9ycy5sZW5ndGg7XG4gIH1cbiAgY29uc3QgdHlwZSA9IHByaW1hcnlJbmRleCA9PT0gY29udGV4dC5teUluZGV4ID8gJ3ByaW1hcnknIDogJ2JhY2t1cCc7XG4gIGNvbnRleHQgPVxuICAgIHR5cGUgPT09ICdwcmltYXJ5JyAmJiBjb250ZXh0IGluc3RhbmNlb2YgU2lnbmF0dXJlU2VudENvbnRleHRcbiAgICAgID8gY29udGV4dC5jbG9uZSh7IHR5cGUsIHByaW1hcnlJbmRleCwgdmlld051bWJlciB9KVxuICAgICAgOiBjbG9uZUluaXRpYWwoY29udGV4dCwgeyB0eXBlLCBwcmltYXJ5SW5kZXgsIHZpZXdOdW1iZXIgfSk7XG5cbiAgcmV0dXJuIGluaXRpYWxpemVDb25zZW5zdXNDb21tb24oeyBibG9ja2NoYWluLCBjb250ZXh0LCBjb25zZW5zdXNDb250ZXh0IH0pO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNoZWNrU2lnbmF0dXJlczxUQ29udGV4dCBleHRlbmRzIEhlYWRlckNvbnRleHQ+KHtcbiAgbm9kZSxcbiAgY29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgY29udGV4dDogVENvbnRleHQ7XG59KTogUHJvbWlzZTxSZXN1bHQ8VENvbnRleHQgfCBCbG9ja1NlbnRDb250ZXh0Pj4ge1xuICBjb25zdCBzaWduYXR1cmVzTGVuZ3RoID0gY29udGV4dC5zaWduYXR1cmVzLmZpbHRlcigocCkgPT4gcCAhPT0gdW5kZWZpbmVkKS5sZW5ndGg7XG5cbiAgaWYgKFxuICAgIHNpZ25hdHVyZXNMZW5ndGggPj0gY29udGV4dC5NICYmXG4gICAgY29udGV4dC50cmFuc2FjdGlvbkhhc2hlcy5ldmVyeSgoaGFzaCkgPT4gY29udGV4dC50cmFuc2FjdGlvbnNbaGFzaF0gIT09IHVuZGVmaW5lZClcbiAgKSB7XG4gICAgY29uc3QgbXV0YWJsZVB1YmxpY0tleVRvU2lnbmF0dXJlOiB7IFtrZXk6IHN0cmluZ106IEJ1ZmZlciB9ID0ge307XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gICAgZm9yIChsZXQgaSA9IDAsIGogPSAwOyBpIDwgY29udGV4dC52YWxpZGF0b3JzLmxlbmd0aCAmJiBqIDwgY29udGV4dC5NOyBpICs9IDEpIHtcbiAgICAgIGNvbnN0IHZhbGlkYXRvciA9IGNvbnRleHQudmFsaWRhdG9yc1tpXTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZSA9IGNvbnRleHQuc2lnbmF0dXJlc1tpXTtcbiAgICAgIGlmIChzaWduYXR1cmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBtdXRhYmxlUHVibGljS2V5VG9TaWduYXR1cmVbY29tbW9uLmVjUG9pbnRUb0hleCh2YWxpZGF0b3IpXSA9IHNpZ25hdHVyZTtcbiAgICAgICAgaiArPSAxO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBzY3JpcHQgPSBjcnlwdG8uY3JlYXRlTXVsdGlTaWduYXR1cmVXaXRuZXNzKFxuICAgICAgY29udGV4dC5NLFxuICAgICAgY29udGV4dC52YWxpZGF0b3JzLFxuICAgICAgbXV0YWJsZVB1YmxpY0tleVRvU2lnbmF0dXJlLFxuICAgICAgV2l0bmVzcyxcbiAgICApO1xuXG4gICAgY29uc3QgYmxvY2sgPSBjb250ZXh0LmhlYWRlci5jbG9uZSh7XG4gICAgICB0cmFuc2FjdGlvbnM6IGNvbnRleHQudHJhbnNhY3Rpb25IYXNoZXMubWFwKChoYXNoKSA9PiBjb250ZXh0LnRyYW5zYWN0aW9uc1toYXNoXSkuZmlsdGVyKGNvbW1vblV0aWxzLm5vdE51bGwpLFxuICAgICAgc2NyaXB0LFxuICAgIH0pO1xuXG4gICAgYXdhaXQgbm9kZS5yZWxheUJsb2NrKGJsb2NrKTtcblxuICAgIHJldHVybiB7IGNvbnRleHQ6IGNsb25lQmxvY2tTZW50KGNvbnRleHQpIH07XG4gIH1cblxuICByZXR1cm4geyBjb250ZXh0IH07XG59XG5cbmV4cG9ydCBjb25zdCBzaWduQW5kUmVsYXlDaGFuZ2VWaWV3ID0gKHtcbiAgbm9kZSxcbiAgcHJpdmF0ZUtleSxcbiAgY29udGV4dCxcbn06IHtcbiAgcmVhZG9ubHkgbm9kZTogTm9kZTtcbiAgcmVhZG9ubHkgcHJpdmF0ZUtleTogUHJpdmF0ZUtleTtcbiAgcmVhZG9ubHkgY29udGV4dDogQ29udGV4dDtcbn0pID0+IHtcbiAgc2lnbkFuZFJlbGF5KHtcbiAgICBub2RlLFxuICAgIHByaXZhdGVLZXksXG4gICAgY29udGV4dCxcbiAgICBjb25zZW5zdXNNZXNzYWdlOiBuZXcgQ2hhbmdlVmlld0NvbnNlbnN1c01lc3NhZ2Uoe1xuICAgICAgdmlld051bWJlcjogY29udGV4dC52aWV3TnVtYmVyLFxuICAgICAgbmV3Vmlld051bWJlcjogY29udGV4dC5leHBlY3RlZFZpZXdbY29udGV4dC5teUluZGV4XSxcbiAgICB9KSxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgY2hlY2tFeHBlY3RlZFZpZXcgPSAoe1xuICBjb250ZXh0LFxuICB2aWV3TnVtYmVyLFxufToge1xuICByZWFkb25seSBjb250ZXh0OiBDb250ZXh0O1xuICByZWFkb25seSB2aWV3TnVtYmVyOiBudW1iZXI7XG59KSA9PiBjb250ZXh0LnZpZXdOdW1iZXIgIT09IHZpZXdOdW1iZXIgJiYgY29udGV4dC5leHBlY3RlZFZpZXcuZmlsdGVyKChwKSA9PiBwID09PSB2aWV3TnVtYmVyKS5sZW5ndGggPj0gY29udGV4dC5NO1xuXG5leHBvcnQgY29uc3QgaW5pdGlhbGl6ZUNvbnNlbnN1c0luaXRpYWwgPSAoe1xuICBibG9ja2NoYWluLFxuICBjb250ZXh0LFxuICB2aWV3TnVtYmVyLFxuICBjb25zZW5zdXNDb250ZXh0LFxufToge1xuICByZWFkb25seSBibG9ja2NoYWluOiBCbG9ja2NoYWluO1xuICByZWFkb25seSBjb250ZXh0OiBDb250ZXh0O1xuICByZWFkb25seSB2aWV3TnVtYmVyOiBudW1iZXI7XG4gIHJlYWRvbmx5IGNvbnNlbnN1c0NvbnRleHQ6IENvbnNlbnN1c0NvbnRleHQ7XG59KTogUmVzdWx0PEluaXRpYWxDb250ZXh0PiA9PiB7XG4gIGNvbnN0IHsgcHJpbWFyeUluZGV4LCB0eXBlIH0gPSBnZXRQcmltYXJ5SW5kZXhUeXBlKHsgY29udGV4dCwgdmlld051bWJlciB9KTtcblxuICByZXR1cm4gaW5pdGlhbGl6ZUNvbnNlbnN1c0NvbW1vbih7XG4gICAgYmxvY2tjaGFpbixcbiAgICBjb250ZXh0OiBjbG9uZUluaXRpYWwoY29udGV4dCwgeyB0eXBlLCBwcmltYXJ5SW5kZXgsIHZpZXdOdW1iZXIgfSksXG4gICAgY29uc2Vuc3VzQ29udGV4dCxcbiAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgaW5jcmVtZW50RXhwZWN0ZWRWaWV3ID0gKGNvbnRleHQ6IENvbnRleHQpOiByZWFkb25seSBudW1iZXJbXSA9PiB7XG4gIGNvbnN0IG11dGFibGVFeHBlY3RlZFZpZXcgPSBbLi4uY29udGV4dC5leHBlY3RlZFZpZXddO1xuICBtdXRhYmxlRXhwZWN0ZWRWaWV3W2NvbnRleHQubXlJbmRleF0gKz0gMTtcblxuICByZXR1cm4gbXV0YWJsZUV4cGVjdGVkVmlldztcbn07XG5cbmNvbnN0IHJlcXVlc3RDaGFuZ2VWaWV3QmFja3VwID0gKHtcbiAgY29udGV4dDogY29udGV4dEluLFxuICBub2RlLFxuICBwcml2YXRlS2V5LFxuICBjb25zZW5zdXNDb250ZXh0LFxufToge1xuICByZWFkb25seSBjb250ZXh0OiBSZXF1ZXN0UmVjZWl2ZWRDb250ZXh0O1xuICByZWFkb25seSBub2RlOiBOb2RlO1xuICByZWFkb25seSBwcml2YXRlS2V5OiBQcml2YXRlS2V5O1xuICByZWFkb25seSBjb25zZW5zdXNDb250ZXh0OiBDb25zZW5zdXNDb250ZXh0O1xufSk6IFJlc3VsdDxJbml0aWFsQ29udGV4dCB8IFZpZXdDaGFuZ2luZ0NvbnRleHQ+ID0+IHtcbiAgY29uc3QgY29udGV4dCA9IGNvbnRleHRJbi5jbG9uZVZpZXdDaGFuZ2luZyh7XG4gICAgZXhwZWN0ZWRWaWV3OiBpbmNyZW1lbnRFeHBlY3RlZFZpZXcoY29udGV4dEluKSxcbiAgfSk7XG5cbiAgc2lnbkFuZFJlbGF5Q2hhbmdlVmlldyh7IGNvbnRleHQsIG5vZGUsIHByaXZhdGVLZXkgfSk7XG5cbiAgY29uc3Qgdmlld051bWJlciA9IGNvbnRleHQuZXhwZWN0ZWRWaWV3W2NvbnRleHQubXlJbmRleF07XG4gIGlmIChjaGVja0V4cGVjdGVkVmlldyh7IGNvbnRleHQsIHZpZXdOdW1iZXIgfSkpIHtcbiAgICByZXR1cm4gaW5pdGlhbGl6ZUNvbnNlbnN1c0luaXRpYWwoe1xuICAgICAgYmxvY2tjaGFpbjogbm9kZS5ibG9ja2NoYWluLFxuICAgICAgY29udGV4dCxcbiAgICAgIHZpZXdOdW1iZXIsXG4gICAgICBjb25zZW5zdXNDb250ZXh0LFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHsgY29udGV4dCB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGFkZFRyYW5zYWN0aW9uID0gYXN5bmMgKHtcbiAgY29udGV4dDogY29udGV4dEluLFxuICBub2RlLFxuICBwcml2YXRlS2V5LFxuICB0cmFuc2FjdGlvbixcbiAgdmVyaWZ5LFxuICBjb25zZW5zdXNDb250ZXh0LFxufToge1xuICByZWFkb25seSBjb250ZXh0OiBSZXF1ZXN0UmVjZWl2ZWRDb250ZXh0O1xuICByZWFkb25seSBub2RlOiBOb2RlO1xuICByZWFkb25seSBwcml2YXRlS2V5OiBQcml2YXRlS2V5O1xuICByZWFkb25seSB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb247XG4gIHJlYWRvbmx5IHZlcmlmeTogYm9vbGVhbjtcbiAgcmVhZG9ubHkgY29uc2Vuc3VzQ29udGV4dDogQ29uc2Vuc3VzQ29udGV4dDtcbn0pOiBQcm9taXNlPFxuICBSZXN1bHQ8UmVxdWVzdFJlY2VpdmVkQ29udGV4dCB8IEluaXRpYWxDb250ZXh0IHwgVmlld0NoYW5naW5nQ29udGV4dCB8IFNpZ25hdHVyZVNlbnRDb250ZXh0IHwgQmxvY2tTZW50Q29udGV4dD5cbj4gPT4ge1xuICBsZXQgY29udGV4dCA9IGNvbnRleHRJbjtcbiAgY29uc3QgeyBibG9ja2NoYWluIH0gPSBub2RlO1xuICBjb25zdCB0eCA9IGF3YWl0IGJsb2NrY2hhaW4udHJhbnNhY3Rpb24udHJ5R2V0KHsgaGFzaDogdHJhbnNhY3Rpb24uaGFzaCB9KTtcbiAgaWYgKHR4ICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4geyBjb250ZXh0IH07XG4gIH1cbiAgaWYgKHZlcmlmeSkge1xuICAgIGxldCB2ZXJpZmllZCA9IHRydWU7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgdmVyaWZpY2F0aW9ucyB9ID0gYXdhaXQgYmxvY2tjaGFpbi52ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgICAgIHRyYW5zYWN0aW9uLFxuICAgICAgICBtZW1Qb29sOiBPYmplY3QudmFsdWVzKGNvbnRleHQudHJhbnNhY3Rpb25zKS5maWx0ZXIoY29tbW9uVXRpbHMubm90TnVsbCksXG4gICAgICB9KTtcbiAgICAgIHZlcmlmaWVkID0gdmVyaWZpY2F0aW9ucy5ldmVyeSgoeyBmYWlsdXJlTWVzc2FnZSB9KSA9PiBmYWlsdXJlTWVzc2FnZSA9PT0gdW5kZWZpbmVkKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHZlcmlmaWVkID0gZmFsc2U7XG4gICAgfVxuICAgIGlmICghdmVyaWZpZWQpIHtcbiAgICAgIHJldHVybiB7IGNvbnRleHQgfTtcbiAgICB9XG4gIH1cblxuICBjb250ZXh0ID0gY29udGV4dC5jbG9uZSh7XG4gICAgdHJhbnNhY3Rpb25zOiB7XG4gICAgICAuLi5jb250ZXh0LnRyYW5zYWN0aW9ucyxcbiAgICAgIFt0cmFuc2FjdGlvbi5oYXNoSGV4XTogdHJhbnNhY3Rpb24sXG4gICAgfSxcbiAgfSk7XG5cbiAgY29uc3QgdHJhbnNhY3Rpb25zTGVuZ3RoID0gT2JqZWN0LnZhbHVlcyhjb250ZXh0LnRyYW5zYWN0aW9ucykubGVuZ3RoO1xuICBpZiAoY29udGV4dC50cmFuc2FjdGlvbkhhc2hlcy5sZW5ndGggPT09IHRyYW5zYWN0aW9uc0xlbmd0aCkge1xuICAgIGNvbnN0IHZhbGlkYXRvcnMgPSBhd2FpdCBibG9ja2NoYWluLmdldFZhbGlkYXRvcnMoT2JqZWN0LnZhbHVlcyhjb250ZXh0LnRyYW5zYWN0aW9ucykuZmlsdGVyKGNvbW1vblV0aWxzLm5vdE51bGwpKTtcblxuICAgIGNvbnN0IGNvbnNlbnN1c0FkZHJlc3MgPSBjcnlwdG8uZ2V0Q29uc2Vuc3VzQWRkcmVzcyh2YWxpZGF0b3JzKTtcbiAgICBpZiAoY29tbW9uLnVJbnQxNjBFcXVhbChjb25zZW5zdXNBZGRyZXNzLCBjb250ZXh0LmhlYWRlci5uZXh0Q29uc2Vuc3VzKSkge1xuICAgICAgY29uc3QgbXV0YWJsZVNpZ25hdHVyZXMgPSBbLi4uY29udGV4dC5zaWduYXR1cmVzXTtcbiAgICAgIG11dGFibGVTaWduYXR1cmVzW2NvbnRleHQubXlJbmRleF0gPSBjcnlwdG8uc2lnbih7XG4gICAgICAgIG1lc3NhZ2U6IGNvbnRleHQuaGVhZGVyLm1lc3NhZ2UsXG4gICAgICAgIHByaXZhdGVLZXksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgbmV3Q29udGV4dCA9IGNvbnRleHQuY2xvbmVTaWduYXR1cmVTZW50KHsgc2lnbmF0dXJlczogbXV0YWJsZVNpZ25hdHVyZXMgfSk7XG4gICAgICBzaWduQW5kUmVsYXkoe1xuICAgICAgICBub2RlLFxuICAgICAgICBjb250ZXh0OiBuZXdDb250ZXh0LFxuICAgICAgICBwcml2YXRlS2V5LFxuICAgICAgICBjb25zZW5zdXNNZXNzYWdlOiBuZXcgUHJlcGFyZVJlc3BvbnNlQ29uc2Vuc3VzTWVzc2FnZSh7XG4gICAgICAgICAgdmlld051bWJlcjogbmV3Q29udGV4dC52aWV3TnVtYmVyLFxuICAgICAgICAgIHNpZ25hdHVyZTogY29tbW9uVXRpbHMubnVsbHRocm93cyhtdXRhYmxlU2lnbmF0dXJlc1tuZXdDb250ZXh0Lm15SW5kZXhdKSxcbiAgICAgICAgfSksXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGNoZWNrU2lnbmF0dXJlcyh7IG5vZGUsIGNvbnRleHQ6IG5ld0NvbnRleHQgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcXVlc3RDaGFuZ2VWaWV3QmFja3VwKHtcbiAgICAgIGNvbnRleHQsXG4gICAgICBub2RlLFxuICAgICAgcHJpdmF0ZUtleSxcbiAgICAgIGNvbnNlbnN1c0NvbnRleHQsXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4geyBjb250ZXh0IH07XG59O1xuIl19