UNPKG

54.9 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 utils_1 = require("@neo-one/utils");
6const lodash_1 = tslib_1.__importDefault(require("lodash"));
7const AssetType_1 = require("../AssetType");
8const constants_1 = require("../constants");
9const errors_1 = require("../errors");
10const ScriptContainer_1 = require("../ScriptContainer");
11const utils_2 = require("../utils");
12const Witness_1 = require("../Witness");
13const attribute_1 = require("./attribute");
14const common_1 = require("./common");
15const Input_1 = require("./Input");
16const Output_1 = require("./Output");
17const TransactionType_1 = require("./TransactionType");
18const getUtilityValue = ({ outputs, utilityToken, }) => outputs
19 .filter((output) => client_common_1.common.uInt256Equal(output.asset, utilityToken.hash))
20 .reduce((acc, output) => acc.add(output.value), utils_2.utils.ZERO);
21function TransactionBase(Base) {
22 class TransactionBaseClass extends Base {
23 constructor() {
24 super(...arguments);
25 this.equals = utils_2.utils.equals(this.constructor, this, (other) => client_common_1.common.uInt256Equal(this.hash, other.hash));
26 this.toKeyString = utils_2.utils.toKeyString(TransactionBase, () => this.hashHex);
27 this.getSortedScriptHashesForVerifying = utils_2.utils.lazyAsync(async (options) => {
28 const hashes = await this.getScriptHashesForVerifying(options);
29 return [...hashes].sort();
30 });
31 this.sizeInternal = utils_2.utils.lazy(() => client_common_1.IOHelper.sizeOfUInt8 +
32 client_common_1.IOHelper.sizeOfArray(this.attributes, (attribute) => attribute.size) +
33 client_common_1.IOHelper.sizeOfArray(this.inputs, (input) => input.size) +
34 client_common_1.IOHelper.sizeOfArray(this.outputs, (output) => output.size) +
35 client_common_1.IOHelper.sizeOfArray(this.scripts, (script) => script.size) +
36 this.sizeExclusive());
37 this.networkFee = utils_2.utils.lazyAsync(async (context) => {
38 const { getOutput, utilityToken } = context;
39 const outputsForInputs = await Promise.all(this.inputs.map(getOutput));
40 const inputValue = getUtilityValue({
41 outputs: outputsForInputs,
42 utilityToken,
43 });
44 const outputValue = getUtilityValue({
45 outputs: this.outputs,
46 utilityToken,
47 });
48 const result = inputValue.sub(outputValue).sub(this.getSystemFee(context));
49 return result.lt(utils_2.utils.ZERO) ? utils_2.utils.ZERO : result;
50 });
51 this.getReferencesInternal = utils_2.utils.lazyAsync(async ({ getOutput }) => Promise.all(this.inputs.map(async (input) => getOutput(input))));
52 this.getTransactionResultsInternal = utils_2.utils.lazyAsync(async ({ getOutput }) => {
53 const inputOutputs = await this.getReferences({ getOutput });
54 const mutableResults = {};
55 const addOutputs = (outputs, negative) => {
56 outputs.forEach((output) => {
57 const key = client_common_1.common.uInt256ToHex(output.asset);
58 let result = mutableResults[key];
59 if (result === undefined) {
60 mutableResults[key] = result = utils_2.utils.ZERO;
61 }
62 mutableResults[key] = result.add(negative === true ? output.value.neg() : output.value);
63 });
64 };
65 addOutputs(inputOutputs);
66 addOutputs(this.outputs, true);
67 return lodash_1.default.pickBy(mutableResults, (value) => value !== undefined && !value.eq(utils_2.utils.ZERO));
68 });
69 this.baseGetScriptHashesForVerifyingInternal = utils_2.utils.lazyAsync(async ({ getOutput, getAsset }) => {
70 const [inputHashes, outputHashes] = await Promise.all([
71 Promise.all(this.inputs.map(async (input) => {
72 const output = await getOutput(input);
73 return client_common_1.common.uInt160ToHex(output.address);
74 })),
75 Promise.all(this.outputs.map(async (output) => {
76 const asset = await getAsset({ hash: output.asset });
77 if (client_common_1.hasFlag(asset.type, AssetType_1.AssetType.DutyFlag)) {
78 return client_common_1.common.uInt160ToHex(output.address);
79 }
80 return undefined;
81 })).then((hashes) => hashes.filter(utils_1.utils.notNull)),
82 ]);
83 const attributeHashes = this.attributes
84 .map((attribute) => attribute instanceof attribute_1.UInt160Attribute && attribute.usage === attribute_1.AttributeUsage.Script
85 ? client_common_1.common.uInt160ToHex(attribute.value)
86 : undefined)
87 .filter(utils_1.utils.notNull);
88 return new Set([...inputHashes, ...outputHashes, ...attributeHashes]);
89 });
90 this.sizeExclusive = () => 0;
91 }
92 static deserializeTransactionBaseStartWireBase({ reader, }) {
93 const type = client_common_1.assertTransactionType(reader.readUInt8());
94 const version = reader.readUInt8();
95 return { type, version };
96 }
97 static deserializeTransactionBaseEndWireBase(options) {
98 const { reader } = options;
99 const attributes = reader.readArray(() => attribute_1.deserializeAttributeWireBase(options), client_common_1.MAX_TRANSACTION_ATTRIBUTES);
100 const inputs = reader.readArray(() => Input_1.Input.deserializeWireBase(options));
101 const outputs = reader.readArray(() => Output_1.Output.deserializeWireBase(options), utils_2.utils.USHORT_MAX_NUMBER + 1);
102 const scripts = reader.readArray(() => Witness_1.Witness.deserializeWireBase(options));
103 return { attributes, inputs, outputs, scripts };
104 }
105 static deserializeWireBase(_options) {
106 throw new Error('Not Implemented');
107 }
108 static deserializeWire(options) {
109 return this.deserializeWireBase({
110 context: options.context,
111 reader: new utils_2.BinaryReader(options.buffer),
112 });
113 }
114 get size() {
115 return this.sizeInternal();
116 }
117 async serializeTransactionBaseJSON(context) {
118 const [networkFee, transactionData] = await Promise.all([
119 this.getNetworkFee(context.feeContext),
120 context.tryGetTransactionData(this),
121 ]);
122 return {
123 txid: client_common_1.common.uInt256ToString(this.hashHex),
124 size: this.size,
125 version: this.version,
126 attributes: this.attributes.map((attribute) => attribute.serializeJSON(context)),
127 vin: this.inputs.map((input) => input.serializeJSON(context)),
128 vout: this.outputs.map((output, index) => output.serializeJSON(context, index)),
129 scripts: this.scripts.map((script) => script.serializeJSON(context)),
130 sys_fee: client_common_1.JSONHelper.writeFixed8(this.getSystemFee(context.feeContext)),
131 net_fee: client_common_1.JSONHelper.writeFixed8(networkFee),
132 data: transactionData === undefined
133 ? undefined
134 : {
135 blockHash: client_common_1.common.uInt256ToString(transactionData.blockHash),
136 blockIndex: transactionData.startHeight,
137 transactionIndex: transactionData.index,
138 globalIndex: client_common_1.JSONHelper.writeUInt64(transactionData.globalIndex),
139 },
140 };
141 }
142 async serializeJSON(_context) {
143 throw new Error('Not Implemented');
144 }
145 async getNetworkFee(context) {
146 return this.networkFee(context);
147 }
148 getSystemFee({ fees }) {
149 const fee = fees[this.type];
150 return fee === undefined ? utils_2.utils.ZERO : fee;
151 }
152 async getReferences(options) {
153 return this.getReferencesInternal(options);
154 }
155 async getTransactionResults(options) {
156 return this.getTransactionResultsInternal(options);
157 }
158 async getScriptHashesForVerifying(options) {
159 return this.baseGetScriptHashesForVerifyingInternal(options);
160 }
161 async verify(options) {
162 if (this.size > constants_1.MAX_TRANSACTION_SIZE) {
163 throw new errors_1.VerifyError('Transaction too large.');
164 }
165 const { memPool = [] } = options;
166 if (common_1.hasDuplicateInputs(this.inputs)) {
167 throw new errors_1.VerifyError('Duplicate inputs');
168 }
169 if (memPool.some((tx) => !tx.equals(this) && common_1.hasIntersectingInputs(tx.inputs, this.inputs))) {
170 throw new errors_1.VerifyError('Input already exists in mempool');
171 }
172 if (this.attributes.filter((attribute) => attribute.usage === attribute_1.AttributeUsage.ECDH02 || attribute.usage === attribute_1.AttributeUsage.ECDH03).length > 1) {
173 throw new errors_1.VerifyError('Too many ECDH attributes.');
174 }
175 const [results] = await Promise.all([
176 this.verifyScripts(options),
177 this.verifyDoubleSpend(options),
178 this.verifyOutputs(options),
179 this.verifyTransactionResults(options),
180 ]);
181 return results;
182 }
183 async verifyDoubleSpend({ isSpent }) {
184 const isDoubleSpend = await Promise.all(this.inputs.map(isSpent));
185 if (isDoubleSpend.some((value) => value)) {
186 throw new errors_1.VerifyError('Transaction is a double spend');
187 }
188 }
189 async verifyOutputs({ getAsset, currentHeight }) {
190 const outputsGrouped = Object.entries(lodash_1.default.groupBy(this.outputs, (output) => client_common_1.common.uInt256ToHex(output.asset)));
191 const hasInvalidOutputs = await Promise.all(outputsGrouped.map(async ([assetHex, outputs]) => {
192 const asset = await getAsset({ hash: client_common_1.common.hexToUInt256(assetHex) });
193 if (asset.expiration <= currentHeight + 1 &&
194 asset.type !== AssetType_1.AssetType.GoverningToken &&
195 asset.type !== AssetType_1.AssetType.UtilityToken) {
196 return true;
197 }
198 return outputs.some((output) => !output.value.mod(utils_2.utils.TEN.pow(utils_2.utils.EIGHT.subn(asset.precision))).eq(utils_2.utils.ZERO));
199 }));
200 if (hasInvalidOutputs.some((value) => value)) {
201 throw new errors_1.VerifyError('Transaction has invalid output');
202 }
203 }
204 async verifyTransactionResults({ getOutput, utilityToken, governingToken, fees, registerValidatorFee, }) {
205 const results = await this.getTransactionResults({ getOutput });
206 const resultsDestroy = Object.entries(results).filter(([_key, value]) => value.gt(utils_2.utils.ZERO));
207 if (resultsDestroy.length > 1 ||
208 (resultsDestroy.length === 1 &&
209 !client_common_1.common.uInt256Equal(client_common_1.common.hexToUInt256(resultsDestroy[0][0]), utilityToken.hash))) {
210 throw new errors_1.VerifyError('Invalid destroyed output.');
211 }
212 const feeContext = {
213 getOutput,
214 governingToken,
215 utilityToken,
216 fees,
217 registerValidatorFee,
218 };
219 const systemFee = this.getSystemFee(feeContext);
220 if (systemFee.gt(utils_2.utils.ZERO) && (resultsDestroy.length === 0 || resultsDestroy[0][1].lt(systemFee))) {
221 throw new errors_1.VerifyError('Not enough output value for system fee.');
222 }
223 const resultsIssue = Object.entries(results).filter(([__, value]) => value.lt(utils_2.utils.ZERO));
224 switch (this.type) {
225 case TransactionType_1.TransactionType.Miner:
226 case TransactionType_1.TransactionType.Claim:
227 if (resultsIssue.some(([assetHex]) => !client_common_1.common.uInt256Equal(client_common_1.common.hexToUInt256(assetHex), utilityToken.hash))) {
228 throw new errors_1.VerifyError('Invalid miner/claim result');
229 }
230 break;
231 case TransactionType_1.TransactionType.Issue:
232 if (resultsIssue.some(([assetHex, __]) => client_common_1.common.uInt256Equal(client_common_1.common.hexToUInt256(assetHex), utilityToken.hash))) {
233 throw new errors_1.VerifyError('Invalid issue result');
234 }
235 break;
236 default:
237 if (resultsIssue.length > 0) {
238 throw new errors_1.VerifyError('Invalid results.');
239 }
240 }
241 }
242 async verifyScripts({ getAsset, getOutput, verifyScript, }) {
243 const hashesArr = await this.getSortedScriptHashesForVerifying({
244 getAsset,
245 getOutput,
246 });
247 if (hashesArr.length !== this.scripts.length) {
248 throw new errors_1.VerifyError(`Invalid witnesses. Found ${hashesArr.length} hashes and ${this.scripts.length} scripts.`);
249 }
250 const hashes = hashesArr.map((value) => client_common_1.common.hexToUInt160(value));
251 return Promise.all(lodash_1.default.zip(hashes, this.scripts).map(async ([hash, witness]) => verifyScript({
252 scriptContainer: {
253 type: ScriptContainer_1.ScriptContainerType.Transaction,
254 value: this,
255 },
256 hash: hash,
257 witness: witness,
258 })));
259 }
260 }
261 TransactionBaseClass.WitnessConstructor = Witness_1.Witness;
262 return TransactionBaseClass;
263}
264exports.TransactionBase = TransactionBase;
265
266//# sourceMappingURL=data:application/json;charset=utf8;base64,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LElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxXQUFXLENBQzFGLENBQUM7YUFDSDtZQUVELE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLHNCQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFcEUsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUNoQixnQkFBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUN4RCxZQUFZLENBQUM7Z0JBQ1gsZUFBZSxFQUFFO29CQUNmLElBQUksRUFBRSxxQ0FBbUIsQ0FBQyxXQUFXO29CQUVyQyxLQUFLLEVBQUUsSUFBVztpQkFDbkI7Z0JBQ0QsSUFBSSxFQUFFLElBQWU7Z0JBQ3JCLE9BQU8sRUFBRSxPQUFrQjthQUM1QixDQUFDLENBQ0gsQ0FDRixDQUFDO1FBQ0osQ0FBQzs7SUF4VXlCLHVDQUFrQixHQUF5QixpQkFBTyxDQUFDO0lBMlUvRSxPQUFPLG9CQUFvQixDQUFDO0FBQzlCLENBQUM7QUEzWEQsMENBMlhDIiwiZmlsZSI6Im5lby1vbmUtbm9kZS1jb3JlL3NyYy90cmFuc2FjdGlvbi9UcmFuc2FjdGlvbkJhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBhc3NlcnRUcmFuc2FjdGlvblR5cGUsXG4gIGNvbW1vbixcbiAgRUNQb2ludCxcbiAgaGFzRmxhZyxcbiAgSU9IZWxwZXIsXG4gIEpTT05IZWxwZXIsXG4gIE1BWF9UUkFOU0FDVElPTl9BVFRSSUJVVEVTLFxuICBUcmFuc2FjdGlvbkJhc2VKU09OLFxuICBUcmFuc2FjdGlvbkJhc2VNb2RlbCxcbiAgVHJhbnNhY3Rpb25CYXNlTW9kZWxBZGQsXG4gIFRyYW5zYWN0aW9uQmFzZU1vZGVsQWRkV2l0aFR5cGUsXG4gIFVJbnQxNjAsXG4gIFVJbnQxNjBIZXgsXG59IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb21tb24nO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIHV0aWxzIGFzIGNvbW1vblV0aWxzIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuaW1wb3J0IHsgQk4gfSBmcm9tICdibi5qcyc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgQWNjb3VudCwgQWNjb3VudEtleSB9IGZyb20gJy4uL0FjY291bnQnO1xuaW1wb3J0IHsgQXNzZXQsIEFzc2V0S2V5IH0gZnJvbSAnLi4vQXNzZXQnO1xuaW1wb3J0IHsgQXNzZXRUeXBlIH0gZnJvbSAnLi4vQXNzZXRUeXBlJztcbmltcG9ydCB7IE1BWF9UUkFOU0FDVElPTl9TSVpFIH0gZnJvbSAnLi4vY29uc3RhbnRzJztcbmltcG9ydCB7IEVxdWFscywgRXF1YXRhYmxlS2V5IH0gZnJvbSAnLi4vRXF1YXRhYmxlJztcbmltcG9ydCB7IFZlcmlmeUVycm9yIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IFNjcmlwdENvbnRhaW5lclR5cGUgfSBmcm9tICcuLi9TY3JpcHRDb250YWluZXInO1xuaW1wb3J0IHtcbiAgRGVzZXJpYWxpemVXaXJlQmFzZU9wdGlvbnMsXG4gIERlc2VyaWFsaXplV2lyZU9wdGlvbnMsXG4gIFNlcmlhbGl6YWJsZUpTT04sXG4gIFNlcmlhbGl6ZUpTT05Db250ZXh0LFxufSBmcm9tICcuLi9TZXJpYWxpemFibGUnO1xuaW1wb3J0IHsgQmluYXJ5UmVhZGVyLCB1dGlscyB9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gJy4uL1ZhbGlkYXRvcic7XG5pbXBvcnQgeyBWZXJpZnlTY3JpcHQsIFZlcmlmeVNjcmlwdFJlc3VsdCB9IGZyb20gJy4uL3ZtJztcbmltcG9ydCB7IFdpdG5lc3MgfSBmcm9tICcuLi9XaXRuZXNzJztcbmltcG9ydCB7IEF0dHJpYnV0ZSwgQXR0cmlidXRlVXNhZ2UsIGRlc2VyaWFsaXplQXR0cmlidXRlV2lyZUJhc2UsIFVJbnQxNjBBdHRyaWJ1dGUgfSBmcm9tICcuL2F0dHJpYnV0ZSc7XG5pbXBvcnQgeyBoYXNEdXBsaWNhdGVJbnB1dHMsIGhhc0ludGVyc2VjdGluZ0lucHV0cyB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IElucHV0IH0gZnJvbSAnLi9JbnB1dCc7XG5pbXBvcnQgeyBPdXRwdXQsIE91dHB1dEtleSB9IGZyb20gJy4vT3V0cHV0JztcbmltcG9ydCB7IFJlZ2lzdGVyVHJhbnNhY3Rpb24gfSBmcm9tICcuL1JlZ2lzdGVyVHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb24gfSBmcm9tICcuL1RyYW5zYWN0aW9uJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uVHlwZSB9IGZyb20gJy4vVHJhbnNhY3Rpb25UeXBlJztcblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2FjdGlvbkJhc2VBZGQgZXh0ZW5kcyBUcmFuc2FjdGlvbkJhc2VNb2RlbEFkZDxBdHRyaWJ1dGUsIElucHV0LCBPdXRwdXQsIFdpdG5lc3M+IHt9XG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zYWN0aW9uQmFzZUFkZFdpdGhUeXBlPFR5cGUgZXh0ZW5kcyBUcmFuc2FjdGlvblR5cGU+XG4gIGV4dGVuZHMgVHJhbnNhY3Rpb25CYXNlTW9kZWxBZGRXaXRoVHlwZTxUeXBlLCBBdHRyaWJ1dGUsIElucHV0LCBPdXRwdXQsIFdpdG5lc3M+IHt9XG5cbmNvbnN0IGdldFV0aWxpdHlWYWx1ZSA9ICh7XG4gIG91dHB1dHMsXG4gIHV0aWxpdHlUb2tlbixcbn06IHtcbiAgcmVhZG9ubHkgb3V0cHV0czogcmVhZG9ubHkgT3V0cHV0W107XG4gIHJlYWRvbmx5IHV0aWxpdHlUb2tlbjogUmVnaXN0ZXJUcmFuc2FjdGlvbjtcbn0pID0+XG4gIG91dHB1dHNcbiAgICAuZmlsdGVyKChvdXRwdXQpID0+IGNvbW1vbi51SW50MjU2RXF1YWwob3V0cHV0LmFzc2V0LCB1dGlsaXR5VG9rZW4uaGFzaCkpXG4gICAgLnJlZHVjZSgoYWNjLCBvdXRwdXQpID0+IGFjYy5hZGQob3V0cHV0LnZhbHVlKSwgdXRpbHMuWkVSTyk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmVlQ29udGV4dCB7XG4gIHJlYWRvbmx5IGdldE91dHB1dDogKGlucHV0OiBJbnB1dCkgPT4gUHJvbWlzZTxPdXRwdXQ+O1xuICByZWFkb25seSBnb3Zlcm5pbmdUb2tlbjogUmVnaXN0ZXJUcmFuc2FjdGlvbjtcbiAgcmVhZG9ubHkgdXRpbGl0eVRva2VuOiBSZWdpc3RlclRyYW5zYWN0aW9uO1xuICByZWFkb25seSBmZWVzOiB7IFtLIGluIFRyYW5zYWN0aW9uVHlwZV0/OiBCTiB9O1xuICByZWFkb25seSByZWdpc3RlclZhbGlkYXRvckZlZTogQk47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNhY3Rpb25HZXRTY3JpcHRIYXNoZXNGb3JWZXJpZnlpbmdPcHRpb25zIHtcbiAgcmVhZG9ubHkgZ2V0T3V0cHV0OiAoa2V5OiBPdXRwdXRLZXkpID0+IFByb21pc2U8T3V0cHV0PjtcbiAgcmVhZG9ubHkgZ2V0QXNzZXQ6IChrZXk6IEFzc2V0S2V5KSA9PiBQcm9taXNlPEFzc2V0Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHZXRSZWZlcmVuY2VzT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGdldE91dHB1dDogKGtleTogT3V0cHV0S2V5KSA9PiBQcm9taXNlPE91dHB1dD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0VHJhbnNhY3Rpb25SZXN1bHRzT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGdldE91dHB1dDogKGtleTogT3V0cHV0S2V5KSA9PiBQcm9taXNlPE91dHB1dD47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNhY3Rpb25WZXJpZnlPcHRpb25zIHtcbiAgcmVhZG9ubHkgY2FsY3VsYXRlQ2xhaW1BbW91bnQ6IChpbnB1dHM6IHJlYWRvbmx5IElucHV0W10pID0+IFByb21pc2U8Qk4+O1xuICByZWFkb25seSBpc1NwZW50OiAoa2V5OiBPdXRwdXRLZXkpID0+IFByb21pc2U8Ym9vbGVhbj47XG4gIHJlYWRvbmx5IGdldEFzc2V0OiAoa2V5OiBBc3NldEtleSkgPT4gUHJvbWlzZTxBc3NldD47XG4gIHJlYWRvbmx5IGdldE91dHB1dDogKGtleTogT3V0cHV0S2V5KSA9PiBQcm9taXNlPE91dHB1dD47XG4gIHJlYWRvbmx5IHRyeUdldEFjY291bnQ6IChrZXk6IEFjY291bnRLZXkpID0+IFByb21pc2U8QWNjb3VudCB8IHVuZGVmaW5lZD47XG4gIHJlYWRvbmx5IHN0YW5kYnlWYWxpZGF0b3JzOiByZWFkb25seSBFQ1BvaW50W107XG4gIHJlYWRvbmx5IGdldEFsbFZhbGlkYXRvcnM6ICgpID0+IFByb21pc2U8cmVhZG9ubHkgVmFsaWRhdG9yW10+O1xuICByZWFkb25seSB2ZXJpZnlTY3JpcHQ6IFZlcmlmeVNjcmlwdDtcbiAgcmVhZG9ubHkgY3VycmVudEhlaWdodDogbnVtYmVyO1xuICByZWFkb25seSBnb3Zlcm5pbmdUb2tlbjogUmVnaXN0ZXJUcmFuc2FjdGlvbjtcbiAgcmVhZG9ubHkgdXRpbGl0eVRva2VuOiBSZWdpc3RlclRyYW5zYWN0aW9uO1xuICByZWFkb25seSBmZWVzOiB7IFtLIGluIFRyYW5zYWN0aW9uVHlwZV0/OiBCTiB9O1xuICByZWFkb25seSByZWdpc3RlclZhbGlkYXRvckZlZTogQk47XG4gIHJlYWRvbmx5IG1lbVBvb2w/OiByZWFkb25seSBUcmFuc2FjdGlvbltdO1xufVxuXG4vKiogQGludGVybmFsICovXG5leHBvcnQgZnVuY3Rpb24gVHJhbnNhY3Rpb25CYXNlPFxuICBUeXBlIGV4dGVuZHMgVHJhbnNhY3Rpb25UeXBlLFxuICBUcmFuc2FjdGlvbkpTT04sXG4gIFRCYXNlIGV4dGVuZHMgQ29uc3RydWN0b3I8VHJhbnNhY3Rpb25CYXNlTW9kZWw8VHlwZSwgQXR0cmlidXRlLCBJbnB1dCwgT3V0cHV0LCBXaXRuZXNzPj5cbj4oQmFzZTogVEJhc2UpIHtcbiAgYWJzdHJhY3QgY2xhc3MgVHJhbnNhY3Rpb25CYXNlQ2xhc3MgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgRXF1YXRhYmxlS2V5LCBTZXJpYWxpemFibGVKU09OPFRyYW5zYWN0aW9uSlNPTj4ge1xuICAgIHB1YmxpYyBzdGF0aWMgZGVzZXJpYWxpemVUcmFuc2FjdGlvbkJhc2VTdGFydFdpcmVCYXNlKHtcbiAgICAgIHJlYWRlcixcbiAgICB9OiBEZXNlcmlhbGl6ZVdpcmVCYXNlT3B0aW9ucyk6IHsgcmVhZG9ubHkgdHlwZTogVHJhbnNhY3Rpb25UeXBlOyByZWFkb25seSB2ZXJzaW9uOiBudW1iZXIgfSB7XG4gICAgICBjb25zdCB0eXBlID0gYXNzZXJ0VHJhbnNhY3Rpb25UeXBlKHJlYWRlci5yZWFkVUludDgoKSk7XG4gICAgICBjb25zdCB2ZXJzaW9uID0gcmVhZGVyLnJlYWRVSW50OCgpO1xuXG4gICAgICByZXR1cm4geyB0eXBlLCB2ZXJzaW9uIH07XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXRpYyBkZXNlcmlhbGl6ZVRyYW5zYWN0aW9uQmFzZUVuZFdpcmVCYXNlKFxuICAgICAgb3B0aW9uczogRGVzZXJpYWxpemVXaXJlQmFzZU9wdGlvbnMsXG4gICAgKToge1xuICAgICAgcmVhZG9ubHkgYXR0cmlidXRlczogcmVhZG9ubHkgQXR0cmlidXRlW107XG4gICAgICByZWFkb25seSBpbnB1dHM6IHJlYWRvbmx5IElucHV0W107XG4gICAgICByZWFkb25seSBvdXRwdXRzOiByZWFkb25seSBPdXRwdXRbXTtcbiAgICAgIHJlYWRvbmx5IHNjcmlwdHM6IHJlYWRvbmx5IFdpdG5lc3NbXTtcbiAgICB9IHtcbiAgICAgIGNvbnN0IHsgcmVhZGVyIH0gPSBvcHRpb25zO1xuICAgICAgY29uc3QgYXR0cmlidXRlcyA9IHJlYWRlci5yZWFkQXJyYXkoKCkgPT4gZGVzZXJpYWxpemVBdHRyaWJ1dGVXaXJlQmFzZShvcHRpb25zKSwgTUFYX1RSQU5TQUNUSU9OX0FUVFJJQlVURVMpO1xuXG4gICAgICBjb25zdCBpbnB1dHMgPSByZWFkZXIucmVhZEFycmF5KCgpID0+IElucHV0LmRlc2VyaWFsaXplV2lyZUJhc2Uob3B0aW9ucykpO1xuICAgICAgY29uc3Qgb3V0cHV0cyA9IHJlYWRlci5yZWFkQXJyYXkoKCkgPT4gT3V0cHV0LmRlc2VyaWFsaXplV2lyZUJhc2Uob3B0aW9ucyksIHV0aWxzLlVTSE9SVF9NQVhfTlVNQkVSICsgMSk7XG5cbiAgICAgIGNvbnN0IHNjcmlwdHMgPSByZWFkZXIucmVhZEFycmF5KCgpID0+IFdpdG5lc3MuZGVzZXJpYWxpemVXaXJlQmFzZShvcHRpb25zKSk7XG5cbiAgICAgIHJldHVybiB7IGF0dHJpYnV0ZXMsIGlucHV0cywgb3V0cHV0cywgc2NyaXB0cyB9O1xuICAgIH1cblxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hbnlcbiAgICBwdWJsaWMgc3RhdGljIGRlc2VyaWFsaXplV2lyZUJhc2UoX29wdGlvbnM6IERlc2VyaWFsaXplV2lyZUJhc2VPcHRpb25zKTogYW55IHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm90IEltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFueVxuICAgIHB1YmxpYyBzdGF0aWMgZGVzZXJpYWxpemVXaXJlKG9wdGlvbnM6IERlc2VyaWFsaXplV2lyZU9wdGlvbnMpOiBhbnkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVzZXJpYWxpemVXaXJlQmFzZSh7XG4gICAgICAgIGNvbnRleHQ6IG9wdGlvbnMuY29udGV4dCxcbiAgICAgICAgcmVhZGVyOiBuZXcgQmluYXJ5UmVhZGVyKG9wdGlvbnMuYnVmZmVyKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzdGF0aWMgcmVhZG9ubHkgV2l0bmVzc0NvbnN0cnVjdG9yOiBDb25zdHJ1Y3RvcjxXaXRuZXNzPiA9IFdpdG5lc3M7XG5cbiAgICBwdWJsaWMgcmVhZG9ubHkgZXF1YWxzOiBFcXVhbHMgPSB1dGlscy5lcXVhbHMoXG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYW55XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yIGFzIGFueSxcbiAgICAgIHRoaXMsXG4gICAgICAob3RoZXI6IFRyYW5zYWN0aW9uQmFzZUNsYXNzKSA9PiBjb21tb24udUludDI1NkVxdWFsKHRoaXMuaGFzaCwgb3RoZXIuaGFzaCksXG4gICAgKTtcbiAgICBwdWJsaWMgcmVhZG9ubHkgdG9LZXlTdHJpbmcgPSB1dGlscy50b0tleVN0cmluZyhUcmFuc2FjdGlvbkJhc2UsICgpID0+IHRoaXMuaGFzaEhleCk7XG4gICAgcHVibGljIHJlYWRvbmx5IGdldFNvcnRlZFNjcmlwdEhhc2hlc0ZvclZlcmlmeWluZyA9IHV0aWxzLmxhenlBc3luYyhcbiAgICAgIGFzeW5jIChvcHRpb25zOiBUcmFuc2FjdGlvbkdldFNjcmlwdEhhc2hlc0ZvclZlcmlmeWluZ09wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgaGFzaGVzID0gYXdhaXQgdGhpcy5nZXRTY3JpcHRIYXNoZXNGb3JWZXJpZnlpbmcob3B0aW9ucyk7XG5cbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFycmF5LW11dGF0aW9uXG4gICAgICAgIHJldHVybiBbLi4uaGFzaGVzXS5zb3J0KCk7XG4gICAgICB9LFxuICAgICk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBzaXplSW50ZXJuYWwgPSB1dGlscy5sYXp5KFxuICAgICAgKCkgPT5cbiAgICAgICAgSU9IZWxwZXIuc2l6ZU9mVUludDggK1xuICAgICAgICBJT0hlbHBlci5zaXplT2ZBcnJheSh0aGlzLmF0dHJpYnV0ZXMsIChhdHRyaWJ1dGUpID0+IGF0dHJpYnV0ZS5zaXplKSArXG4gICAgICAgIElPSGVscGVyLnNpemVPZkFycmF5KHRoaXMuaW5wdXRzLCAoaW5wdXQpID0+IGlucHV0LnNpemUpICtcbiAgICAgICAgSU9IZWxwZXIuc2l6ZU9mQXJyYXkodGhpcy5vdXRwdXRzLCAob3V0cHV0KSA9PiBvdXRwdXQuc2l6ZSkgK1xuICAgICAgICBJT0hlbHBlci5zaXplT2ZBcnJheSh0aGlzLnNjcmlwdHMsIChzY3JpcHQpID0+IHNjcmlwdC5zaXplKSArXG4gICAgICAgIHRoaXMuc2l6ZUV4Y2x1c2l2ZSgpLFxuICAgICk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBuZXR3b3JrRmVlID0gdXRpbHMubGF6eUFzeW5jKFxuICAgICAgYXN5bmMgKGNvbnRleHQ6IEZlZUNvbnRleHQpOiBQcm9taXNlPEJOPiA9PiB7XG4gICAgICAgIGNvbnN0IHsgZ2V0T3V0cHV0LCB1dGlsaXR5VG9rZW4gfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgY29uc3Qgb3V0cHV0c0ZvcklucHV0cyA9IGF3YWl0IFByb21pc2UuYWxsKHRoaXMuaW5wdXRzLm1hcChnZXRPdXRwdXQpKTtcblxuICAgICAgICBjb25zdCBpbnB1dFZhbHVlID0gZ2V0VXRpbGl0eVZhbHVlKHtcbiAgICAgICAgICBvdXRwdXRzOiBvdXRwdXRzRm9ySW5wdXRzLFxuICAgICAgICAgIHV0aWxpdHlUb2tlbixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3Qgb3V0cHV0VmFsdWUgPSBnZXRVdGlsaXR5VmFsdWUoe1xuICAgICAgICAgIG91dHB1dHM6IHRoaXMub3V0cHV0cyxcbiAgICAgICAgICB1dGlsaXR5VG9rZW4sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGlucHV0VmFsdWUuc3ViKG91dHB1dFZhbHVlKS5zdWIodGhpcy5nZXRTeXN0ZW1GZWUoY29udGV4dCkpO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQubHQodXRpbHMuWkVSTykgPyB1dGlscy5aRVJPIDogcmVzdWx0O1xuICAgICAgfSxcbiAgICApO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZ2V0UmVmZXJlbmNlc0ludGVybmFsID0gdXRpbHMubGF6eUFzeW5jKGFzeW5jICh7IGdldE91dHB1dCB9OiBHZXRSZWZlcmVuY2VzT3B0aW9ucykgPT5cbiAgICAgIFByb21pc2UuYWxsKHRoaXMuaW5wdXRzLm1hcChhc3luYyAoaW5wdXQpID0+IGdldE91dHB1dChpbnB1dCkpKSxcbiAgICApO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZ2V0VHJhbnNhY3Rpb25SZXN1bHRzSW50ZXJuYWwgPSB1dGlscy5sYXp5QXN5bmMoXG4gICAgICBhc3luYyAoeyBnZXRPdXRwdXQgfTogR2V0VHJhbnNhY3Rpb25SZXN1bHRzT3B0aW9ucyk6IFByb21pc2U8eyByZWFkb25seSBbSyBpbiBzdHJpbmddPzogQk4gfT4gPT4ge1xuICAgICAgICBjb25zdCBpbnB1dE91dHB1dHMgPSBhd2FpdCB0aGlzLmdldFJlZmVyZW5jZXMoeyBnZXRPdXRwdXQgfSk7XG4gICAgICAgIGNvbnN0IG11dGFibGVSZXN1bHRzOiB7IFtLIGluIHN0cmluZ10/OiBCTiB9ID0ge307XG4gICAgICAgIGNvbnN0IGFkZE91dHB1dHMgPSAob3V0cHV0czogcmVhZG9ubHkgT3V0cHV0W10sIG5lZ2F0aXZlPzogYm9vbGVhbikgPT4ge1xuICAgICAgICAgIG91dHB1dHMuZm9yRWFjaCgob3V0cHV0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBrZXkgPSBjb21tb24udUludDI1NlRvSGV4KG91dHB1dC5hc3NldCk7XG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gbXV0YWJsZVJlc3VsdHNba2V5XTtcbiAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBtdXRhYmxlUmVzdWx0c1trZXldID0gcmVzdWx0ID0gdXRpbHMuWkVSTztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbXV0YWJsZVJlc3VsdHNba2V5XSA9IHJlc3VsdC5hZGQobmVnYXRpdmUgPT09IHRydWUgPyBvdXRwdXQudmFsdWUubmVnKCkgOiBvdXRwdXQudmFsdWUpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBhZGRPdXRwdXRzKGlucHV0T3V0cHV0cyk7XG4gICAgICAgIGFkZE91dHB1dHModGhpcy5vdXRwdXRzLCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gXy5waWNrQnkobXV0YWJsZVJlc3VsdHMsICh2YWx1ZSkgPT4gdmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhdmFsdWUuZXEodXRpbHMuWkVSTykpO1xuICAgICAgfSxcbiAgICApO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgYmFzZUdldFNjcmlwdEhhc2hlc0ZvclZlcmlmeWluZ0ludGVybmFsID0gdXRpbHMubGF6eUFzeW5jKFxuICAgICAgYXN5bmMgKHsgZ2V0T3V0cHV0LCBnZXRBc3NldCB9OiBUcmFuc2FjdGlvbkdldFNjcmlwdEhhc2hlc0ZvclZlcmlmeWluZ09wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgW2lucHV0SGFzaGVzLCBvdXRwdXRIYXNoZXNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgIFByb21pc2UuYWxsKFxuICAgICAgICAgICAgdGhpcy5pbnB1dHMubWFwKGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBvdXRwdXQgPSBhd2FpdCBnZXRPdXRwdXQoaW5wdXQpO1xuXG4gICAgICAgICAgICAgIHJldHVybiBjb21tb24udUludDE2MFRvSGV4KG91dHB1dC5hZGRyZXNzKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICksXG5cbiAgICAgICAgICBQcm9taXNlLmFsbChcbiAgICAgICAgICAgIHRoaXMub3V0cHV0cy5tYXAoYXN5bmMgKG91dHB1dCkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBhc3NldCA9IGF3YWl0IGdldEFzc2V0KHsgaGFzaDogb3V0cHV0LmFzc2V0IH0pO1xuICAgICAgICAgICAgICBpZiAoaGFzRmxhZyhhc3NldC50eXBlLCBBc3NldFR5cGUuRHV0eUZsYWcpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbW1vbi51SW50MTYwVG9IZXgob3V0cHV0LmFkZHJlc3MpO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICkudGhlbigoaGFzaGVzKSA9PiBoYXNoZXMuZmlsdGVyKGNvbW1vblV0aWxzLm5vdE51bGwpKSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgY29uc3QgYXR0cmlidXRlSGFzaGVzID0gdGhpcy5hdHRyaWJ1dGVzXG4gICAgICAgICAgLm1hcCgoYXR0cmlidXRlKSA9PlxuICAgICAgICAgICAgYXR0cmlidXRlIGluc3RhbmNlb2YgVUludDE2MEF0dHJpYnV0ZSAmJiBhdHRyaWJ1dGUudXNhZ2UgPT09IEF0dHJpYnV0ZVVzYWdlLlNjcmlwdFxuICAgICAgICAgICAgICA/IGNvbW1vbi51SW50MTYwVG9IZXgoYXR0cmlidXRlLnZhbHVlKVxuICAgICAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgICApXG4gICAgICAgICAgLmZpbHRlcihjb21tb25VdGlscy5ub3ROdWxsKTtcblxuICAgICAgICByZXR1cm4gbmV3IFNldChbLi4uaW5wdXRIYXNoZXMsIC4uLm91dHB1dEhhc2hlcywgLi4uYXR0cmlidXRlSGFzaGVzXSk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICBwdWJsaWMgZ2V0IHNpemUoKTogbnVtYmVyIHtcbiAgICAgIHJldHVybiB0aGlzLnNpemVJbnRlcm5hbCgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzZXJpYWxpemVUcmFuc2FjdGlvbkJhc2VKU09OKGNvbnRleHQ6IFNlcmlhbGl6ZUpTT05Db250ZXh0KTogUHJvbWlzZTxUcmFuc2FjdGlvbkJhc2VKU09OPiB7XG4gICAgICBjb25zdCBbbmV0d29ya0ZlZSwgdHJhbnNhY3Rpb25EYXRhXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgdGhpcy5nZXROZXR3b3JrRmVlKGNvbnRleHQuZmVlQ29udGV4dCksXG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hbnlcbiAgICAgICAgY29udGV4dC50cnlHZXRUcmFuc2FjdGlvbkRhdGEodGhpcyBhcyBhbnkpLFxuICAgICAgXSk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR4aWQ6IGNvbW1vbi51SW50MjU2VG9TdHJpbmcodGhpcy5oYXNoSGV4KSxcbiAgICAgICAgc2l6ZTogdGhpcy5zaXplLFxuICAgICAgICB2ZXJzaW9uOiB0aGlzLnZlcnNpb24sXG4gICAgICAgIGF0dHJpYnV0ZXM6IHRoaXMuYXR0cmlidXRlcy5tYXAoKGF0dHJpYnV0ZSkgPT4gYXR0cmlidXRlLnNlcmlhbGl6ZUpTT04oY29udGV4dCkpLFxuXG4gICAgICAgIHZpbjogdGhpcy5pbnB1dHMubWFwKChpbnB1dCkgPT4gaW5wdXQuc2VyaWFsaXplSlNPTihjb250ZXh0KSksXG4gICAgICAgIHZvdXQ6IHRoaXMub3V0cHV0cy5tYXAoKG91dHB1dCwgaW5kZXgpID0+IG91dHB1dC5zZXJpYWxpemVKU09OKGNvbnRleHQsIGluZGV4KSksXG5cbiAgICAgICAgc2NyaXB0czogdGhpcy5zY3JpcHRzLm1hcCgoc2NyaXB0KSA9PiBzY3JpcHQuc2VyaWFsaXplSlNPTihjb250ZXh0KSksXG4gICAgICAgIHN5c19mZWU6IEpTT05IZWxwZXIud3JpdGVGaXhlZDgodGhpcy5nZXRTeXN0ZW1GZWUoY29udGV4dC5mZWVDb250ZXh0KSksXG4gICAgICAgIG5ldF9mZWU6IEpTT05IZWxwZXIud3JpdGVGaXhlZDgobmV0d29ya0ZlZSksXG4gICAgICAgIGRhdGE6XG4gICAgICAgICAgdHJhbnNhY3Rpb25EYXRhID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgID8gdW5kZWZpbmVkXG4gICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBibG9ja0hhc2g6IGNvbW1vbi51SW50MjU2VG9TdHJpbmcodHJhbnNhY3Rpb25EYXRhLmJsb2NrSGFzaCksXG4gICAgICAgICAgICAgICAgYmxvY2tJbmRleDogdHJhbnNhY3Rpb25EYXRhLnN0YXJ0SGVpZ2h0LFxuICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uSW5kZXg6IHRyYW5zYWN0aW9uRGF0YS5pbmRleCxcbiAgICAgICAgICAgICAgICBnbG9iYWxJbmRleDogSlNPTkhlbHBlci53cml0ZVVJbnQ2NCh0cmFuc2FjdGlvbkRhdGEuZ2xvYmFsSW5kZXgpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2VyaWFsaXplSlNPTihfY29udGV4dDogU2VyaWFsaXplSlNPTkNvbnRleHQpOiBQcm9taXNlPFRyYW5zYWN0aW9uSlNPTj4ge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgSW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0TmV0d29ya0ZlZShjb250ZXh0OiBGZWVDb250ZXh0KTogUHJvbWlzZTxCTj4ge1xuICAgICAgcmV0dXJuIHRoaXMubmV0d29ya0ZlZShjb250ZXh0KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U3lzdGVtRmVlKHsgZmVlcyB9OiBGZWVDb250ZXh0KTogQk4ge1xuICAgICAgY29uc3QgZmVlOiBCTiB8IHVuZGVmaW5lZCA9IGZlZXNbdGhpcy50eXBlXTtcblxuICAgICAgcmV0dXJuIGZlZSA9PT0gdW5kZWZpbmVkID8gdXRpbHMuWkVSTyA6IGZlZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0UmVmZXJlbmNlcyhvcHRpb25zOiBHZXRSZWZlcmVuY2VzT3B0aW9ucyk6IFByb21pc2U8cmVhZG9ubHkgT3V0cHV0W10+IHtcbiAgICAgIHJldHVybiB0aGlzLmdldFJlZmVyZW5jZXNJbnRlcm5hbChvcHRpb25zKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0VHJhbnNhY3Rpb25SZXN1bHRzKG9wdGlvbnM6IEdldFRyYW5zYWN0aW9uUmVzdWx0c09wdGlvbnMpOiBQcm9taXNlPHsgcmVhZG9ubHkgW2tleTogc3RyaW5nXTogQk4gfT4ge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VHJhbnNhY3Rpb25SZXN1bHRzSW50ZXJuYWwob3B0aW9ucykgYXMgUHJvbWlzZTx7IHJlYWRvbmx5IFtrZXk6IHN0cmluZ106IEJOIH0+O1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBnZXRTY3JpcHRIYXNoZXNGb3JWZXJpZnlpbmcoXG4gICAgICBvcHRpb25zOiBUcmFuc2FjdGlvbkdldFNjcmlwdEhhc2hlc0ZvclZlcmlmeWluZ09wdGlvbnMsXG4gICAgKTogUHJvbWlzZTxTZXQ8VUludDE2MEhleD4+IHtcbiAgICAgIHJldHVybiB0aGlzLmJhc2VHZXRTY3JpcHRIYXNoZXNGb3JWZXJpZnlpbmdJbnRlcm5hbChvcHRpb25zKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgdmVyaWZ5KG9wdGlvbnM6IFRyYW5zYWN0aW9uVmVyaWZ5T3B0aW9ucyk6IFByb21pc2U8cmVhZG9ubHkgVmVyaWZ5U2NyaXB0UmVzdWx0W10+IHtcbiAgICAgIGlmICh0aGlzLnNpemUgPiBNQVhfVFJBTlNBQ1RJT05fU0laRSkge1xuICAgICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ1RyYW5zYWN0aW9uIHRvbyBsYXJnZS4nKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBtZW1Qb29sID0gW10gfSA9IG9wdGlvbnM7XG4gICAgICBpZiAoaGFzRHVwbGljYXRlSW5wdXRzKHRoaXMuaW5wdXRzKSkge1xuICAgICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ0R1cGxpY2F0ZSBpbnB1dHMnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lbVBvb2wuc29tZSgodHgpID0+ICF0eC5lcXVhbHModGhpcykgJiYgaGFzSW50ZXJzZWN0aW5nSW5wdXRzKHR4LmlucHV0cywgdGhpcy5pbnB1dHMpKSkge1xuICAgICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ0lucHV0IGFscmVhZHkgZXhpc3RzIGluIG1lbXBvb2wnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICB0aGlzLmF0dHJpYnV0ZXMuZmlsdGVyKFxuICAgICAgICAgIChhdHRyaWJ1dGUpID0+IGF0dHJpYnV0ZS51c2FnZSA9PT0gQXR0cmlidXRlVXNhZ2UuRUNESDAyIHx8IGF0dHJpYnV0ZS51c2FnZSA9PT0gQXR0cmlidXRlVXNhZ2UuRUNESDAzLFxuICAgICAgICApLmxlbmd0aCA+IDFcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ1RvbyBtYW55IEVDREggYXR0cmlidXRlcy4nKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgW3Jlc3VsdHNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICB0aGlzLnZlcmlmeVNjcmlwdHMob3B0aW9ucyksXG4gICAgICAgIHRoaXMudmVyaWZ5RG91YmxlU3BlbmQob3B0aW9ucyksXG4gICAgICAgIHRoaXMudmVyaWZ5T3V0cHV0cyhvcHRpb25zKSxcbiAgICAgICAgdGhpcy52ZXJpZnlUcmFuc2FjdGlvblJlc3VsdHMob3B0aW9ucyksXG4gICAgICBdKTtcblxuICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHNpemVFeGNsdXNpdmU6ICgpID0+IG51bWJlciA9ICgpID0+IDA7XG5cbiAgICBwcml2YXRlIGFzeW5jIHZlcmlmeURvdWJsZVNwZW5kKHsgaXNTcGVudCB9OiBUcmFuc2FjdGlvblZlcmlmeU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IGlzRG91YmxlU3BlbmQgPSBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLmlucHV0cy5tYXAoaXNTcGVudCkpO1xuXG4gICAgICBpZiAoaXNEb3VibGVTcGVuZC5zb21lKCh2YWx1ZSkgPT4gdmFsdWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBWZXJpZnlFcnJvcignVHJhbnNhY3Rpb24gaXMgYSBkb3VibGUgc3BlbmQnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHZlcmlmeU91dHB1dHMoeyBnZXRBc3NldCwgY3VycmVudEhlaWdodCB9OiBUcmFuc2FjdGlvblZlcmlmeU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IG91dHB1dHNHcm91cGVkID0gT2JqZWN0LmVudHJpZXMoXy5ncm91cEJ5KHRoaXMub3V0cHV0cywgKG91dHB1dCkgPT4gY29tbW9uLnVJbnQyNTZUb0hleChvdXRwdXQuYXNzZXQpKSk7XG5cbiAgICAgIGNvbnN0IGhhc0ludmFsaWRPdXRwdXRzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIG91dHB1dHNHcm91cGVkLm1hcChhc3luYyAoW2Fzc2V0SGV4LCBvdXRwdXRzXSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGFzc2V0ID0gYXdhaXQgZ2V0QXNzZXQoeyBoYXNoOiBjb21tb24uaGV4VG9VSW50MjU2KGFzc2V0SGV4KSB9KTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBhc3NldC5leHBpcmF0aW9uIDw9IGN1cnJlbnRIZWlnaHQgKyAxICYmXG4gICAgICAgICAgICBhc3NldC50eXBlICE9PSBBc3NldFR5cGUuR292ZXJuaW5nVG9rZW4gJiZcbiAgICAgICAgICAgIGFzc2V0LnR5cGUgIT09IEFzc2V0VHlwZS5VdGlsaXR5VG9rZW5cbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBvdXRwdXRzLnNvbWUoXG4gICAgICAgICAgICAob3V0cHV0KSA9PiAhb3V0cHV0LnZhbHVlLm1vZCh1dGlscy5URU4ucG93KHV0aWxzLkVJR0hULnN1Ym4oYXNzZXQucHJlY2lzaW9uKSkpLmVxKHV0aWxzLlpFUk8pLFxuICAgICAgICAgICk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgaWYgKGhhc0ludmFsaWRPdXRwdXRzLnNvbWUoKHZhbHVlKSA9PiB2YWx1ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZlcmlmeUVycm9yKCdUcmFuc2FjdGlvbiBoYXMgaW52YWxpZCBvdXRwdXQnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHZlcmlmeVRyYW5zYWN0aW9uUmVzdWx0cyh7XG4gICAgICBnZXRPdXRwdXQsXG4gICAgICB1dGlsaXR5VG9rZW4sXG4gICAgICBnb3Zlcm5pbmdUb2tlbixcbiAgICAgIGZlZXMsXG4gICAgICByZWdpc3RlclZhbGlkYXRvckZlZSxcbiAgICB9OiBUcmFuc2FjdGlvblZlcmlmeU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmdldFRyYW5zYWN0aW9uUmVzdWx0cyh7IGdldE91dHB1dCB9KTtcbiAgICAgIGNvbnN0IHJlc3VsdHNEZXN0cm95ID0gT2JqZWN0LmVudHJpZXMocmVzdWx0cykuZmlsdGVyKFxuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkXG4gICAgICAgIChbX2tleSwgdmFsdWVdKSA9PiB2YWx1ZS5ndCh1dGlscy5aRVJPKSxcbiAgICAgICk7XG5cbiAgICAgIGlmIChcbiAgICAgICAgcmVzdWx0c0Rlc3Ryb3kubGVuZ3RoID4gMSB8fFxuICAgICAgICAocmVzdWx0c0Rlc3Ryb3kubGVuZ3RoID09PSAxICYmXG4gICAgICAgICAgIWNvbW1vbi51SW50MjU2RXF1YWwoY29tbW9uLmhleFRvVUludDI1NihyZXN1bHRzRGVzdHJveVswXVswXSksIHV0aWxpdHlUb2tlbi5oYXNoKSlcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ0ludmFsaWQgZGVzdHJveWVkIG91dHB1dC4nKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmVlQ29udGV4dCA9IHtcbiAgICAgICAgZ2V0T3V0cHV0LFxuICAgICAgICBnb3Zlcm5pbmdUb2tlbixcbiAgICAgICAgdXRpbGl0eVRva2VuLFxuICAgICAgICBmZWVzLFxuICAgICAgICByZWdpc3RlclZhbGlkYXRvckZlZSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHN5c3RlbUZlZSA9IHRoaXMuZ2V0U3lzdGVtRmVlKGZlZUNvbnRleHQpO1xuICAgICAgaWYgKHN5c3RlbUZlZS5ndCh1dGlscy5aRVJPKSAmJiAocmVzdWx0c0Rlc3Ryb3kubGVuZ3RoID09PSAwIHx8IHJlc3VsdHNEZXN0cm95WzBdWzFdLmx0KHN5c3RlbUZlZSkpKSB7XG4gICAgICAgIHRocm93IG5ldyBWZXJpZnlFcnJvcignTm90IGVub3VnaCBvdXRwdXQgdmFsdWUgZm9yIHN5c3RlbSBmZWUuJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWRcbiAgICAgIGNvbnN0IHJlc3VsdHNJc3N1ZSA9IE9iamVjdC5lbnRyaWVzKHJlc3VsdHMpLmZpbHRlcigoW19fLCB2YWx1ZV0pID0+IHZhbHVlLmx0KHV0aWxzLlpFUk8pKTtcblxuICAgICAgc3dpdGNoICh0aGlzLnR5cGUpIHtcbiAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuTWluZXI6XG4gICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLkNsYWltOlxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHJlc3VsdHNJc3N1ZS5zb21lKChbYXNzZXRIZXhdKSA9PiAhY29tbW9uLnVJbnQyNTZFcXVhbChjb21tb24uaGV4VG9VSW50MjU2KGFzc2V0SGV4KSwgdXRpbGl0eVRva2VuLmhhc2gpKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFZlcmlmeUVycm9yKCdJbnZhbGlkIG1pbmVyL2NsYWltIHJlc3VsdCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuSXNzdWU6XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZFxuICAgICAgICAgICAgcmVzdWx0c0lzc3VlLnNvbWUoKFthc3NldEhleCwgX19dKSA9PiBjb21tb24udUludDI1NkVxdWFsKGNvbW1vbi5oZXhUb1VJbnQyNTYoYXNzZXRIZXgpLCB1dGlsaXR5VG9rZW4uaGFzaCkpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ0ludmFsaWQgaXNzdWUgcmVzdWx0Jyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGlmIChyZXN1bHRzSXNzdWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFZlcmlmeUVycm9yKCdJbnZhbGlkIHJlc3VsdHMuJyk7XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgdmVyaWZ5U2NyaXB0cyh7XG4gICAgICBnZXRBc3NldCxcbiAgICAgIGdldE91dHB1dCxcbiAgICAgIHZlcmlmeVNjcmlwdCxcbiAgICB9OiBUcmFuc2FjdGlvblZlcmlmeU9wdGlvbnMpOiBQcm9taXNlPHJlYWRvbmx5IFZlcmlmeVNjcmlwdFJlc3VsdFtdPiB7XG4gICAgICBjb25zdCBoYXNoZXNBcnIgPSBhd2FpdCB0aGlzLmdldFNvcnRlZFNjcmlwdEhhc2hlc0ZvclZlcmlmeWluZyh7XG4gICAgICAgIGdldEFzc2V0LFxuICAgICAgICBnZXRPdXRwdXQsXG4gICAgICB9KTtcblxuICAgICAgaWYgKGhhc2hlc0Fyci5sZW5ndGggIT09IHRoaXMuc2NyaXB0cy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZlcmlmeUVycm9yKFxuICAgICAgICAgIGBJbnZhbGlkIHdpdG5lc3Nlcy4gRm91bmQgJHtoYXNoZXNBcnIubGVuZ3RofSBoYXNoZXMgYW5kICR7dGhpcy5zY3JpcHRzLmxlbmd0aH0gc2NyaXB0cy5gLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBoYXNoZXMgPSBoYXNoZXNBcnIubWFwKCh2YWx1ZSkgPT4gY29tbW9uLmhleFRvVUludDE2MCh2YWx1ZSkpO1xuXG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICAgIF8uemlwKGhhc2hlcywgdGhpcy5zY3JpcHRzKS5tYXAoYXN5bmMgKFtoYXNoLCB3aXRuZXNzXSkgPT5cbiAgICAgICAgICB2ZXJpZnlTY3JpcHQoe1xuICAgICAgICAgICAgc2NyaXB0Q29udGFpbmVyOiB7XG4gICAgICAgICAgICAgIHR5cGU6IFNjcmlwdENvbnRhaW5lclR5cGUuVHJhbnNhY3Rpb24sXG4gICAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1hbnlcbiAgICAgICAgICAgICAgdmFsdWU6IHRoaXMgYXMgYW55LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGhhc2g6IGhhc2ggYXMgVUludDE2MCxcbiAgICAgICAgICAgIHdpdG5lc3M6IHdpdG5lc3MgYXMgV2l0bmVzcyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFRyYW5zYWN0aW9uQmFzZUNsYXNzO1xufVxuIl19