1 | import { common, crypto, InvalidFormatError, IOHelper, } from '@neo-one/client-common-esnext-esm';
|
2 | import { BlockBase } from './BlockBase';
|
3 | import { MerkleTree } from './crypto';
|
4 | import { VerifyError } from './errors';
|
5 | import { Header } from './Header';
|
6 | import { ScriptContainerType } from './ScriptContainer';
|
7 | import { deserializeTransactionWireBase, TransactionType, } from './transaction';
|
8 | import { BinaryReader, utils } from './utils';
|
9 | export class Block extends BlockBase {
|
10 | constructor({ version, previousHash, timestamp, index, consensusData, nextConsensus, script, hash, transactions, merkleRoot = MerkleTree.computeRoot(transactions.map((transaction) => transaction.hash)), }) {
|
11 | super({
|
12 | version,
|
13 | previousHash,
|
14 | merkleRoot,
|
15 | timestamp,
|
16 | index,
|
17 | consensusData,
|
18 | nextConsensus,
|
19 | script,
|
20 | hash,
|
21 | });
|
22 | this.sizeExclusive = utils.lazy(() => IOHelper.sizeOfArray(this.transactions, (transaction) => transaction.size));
|
23 | this.headerInternal = utils.lazy(() => new Header({
|
24 | version: this.version,
|
25 | previousHash: this.previousHash,
|
26 | merkleRoot: this.merkleRoot,
|
27 | timestamp: this.timestamp,
|
28 | index: this.index,
|
29 | consensusData: this.consensusData,
|
30 | nextConsensus: this.nextConsensus,
|
31 | script: this.script,
|
32 | }));
|
33 | this.transactions = transactions;
|
34 | }
|
35 | static async calculateNetworkFee(context, transactions) {
|
36 | const fees = await Promise.all(transactions.map(async (transaction) => transaction.getNetworkFee(context)));
|
37 | return fees.reduce((acc, fee) => acc.add(fee), utils.ZERO);
|
38 | }
|
39 | static deserializeWireBase(options) {
|
40 | const { reader } = options;
|
41 | const blockBase = super.deserializeBlockBaseWireBase(options);
|
42 | const transactions = reader.readArray(() => deserializeTransactionWireBase(options), 0x10000);
|
43 | if (transactions.length === 0) {
|
44 | throw new InvalidFormatError('Expected at least one transcaction in the block');
|
45 | }
|
46 | const merkleRoot = MerkleTree.computeRoot(transactions.map((transaction) => transaction.hash));
|
47 | if (!common.uInt256Equal(merkleRoot, blockBase.merkleRoot)) {
|
48 | throw new InvalidFormatError('Invalid merkle root');
|
49 | }
|
50 | return new this({
|
51 | version: blockBase.version,
|
52 | previousHash: blockBase.previousHash,
|
53 | merkleRoot: blockBase.merkleRoot,
|
54 | timestamp: blockBase.timestamp,
|
55 | index: blockBase.index,
|
56 | consensusData: blockBase.consensusData,
|
57 | nextConsensus: blockBase.nextConsensus,
|
58 | script: blockBase.script,
|
59 | transactions,
|
60 | });
|
61 | }
|
62 | static deserializeWire(options) {
|
63 | return this.deserializeWireBase({
|
64 | context: options.context,
|
65 | reader: new BinaryReader(options.buffer),
|
66 | });
|
67 | }
|
68 | get header() {
|
69 | return this.headerInternal();
|
70 | }
|
71 | clone({ transactions, script, }) {
|
72 | return new Block({
|
73 | version: this.version,
|
74 | previousHash: this.previousHash,
|
75 | merkleRoot: this.merkleRoot,
|
76 | timestamp: this.timestamp,
|
77 | index: this.index,
|
78 | consensusData: this.consensusData,
|
79 | nextConsensus: this.nextConsensus,
|
80 | transactions,
|
81 | script,
|
82 | });
|
83 | }
|
84 | async getNetworkFee(context) {
|
85 | return Block.calculateNetworkFee(context, this.transactions);
|
86 | }
|
87 | getSystemFee(context) {
|
88 | return this.transactions.reduce((acc, transaction) => acc.add(transaction.getSystemFee(context)), utils.ZERO);
|
89 | }
|
90 | async verify(options) {
|
91 | const { completely = false } = options;
|
92 | if (this.transactions.length === 0 ||
|
93 | this.transactions[0].type !== TransactionType.Miner ||
|
94 | this.transactions.slice(1).some((transaction) => transaction.type === TransactionType.Miner)) {
|
95 | throw new VerifyError('Invalid miner transaction in block.');
|
96 | }
|
97 | await Promise.all([this.verifyBase(options), completely ? this.verifyComplete(options) : Promise.resolve()]);
|
98 | }
|
99 | serializeWireBase(writer) {
|
100 | super.serializeWireBase(writer);
|
101 | writer.writeArray(this.transactions, (transaction) => transaction.serializeWireBase(writer));
|
102 | }
|
103 | async serializeJSON(context) {
|
104 | const blockBaseJSON = super.serializeBlockBaseJSON(context);
|
105 | return {
|
106 | version: blockBaseJSON.version,
|
107 | hash: blockBaseJSON.hash,
|
108 | previousblockhash: blockBaseJSON.previousblockhash,
|
109 | merkleroot: blockBaseJSON.merkleroot,
|
110 | time: blockBaseJSON.time,
|
111 | index: blockBaseJSON.index,
|
112 | nonce: blockBaseJSON.nonce,
|
113 | nextconsensus: blockBaseJSON.nextconsensus,
|
114 | script: blockBaseJSON.script,
|
115 | tx: await Promise.all(this.transactions.map((transaction) => transaction.serializeJSON(context))),
|
116 | size: blockBaseJSON.size,
|
117 | confirmations: blockBaseJSON.confirmations,
|
118 | };
|
119 | }
|
120 | async verifyBase({ genesisBlock, tryGetBlock, tryGetHeader, verifyScript, }) {
|
121 | if (common.uInt256Equal(this.hash, genesisBlock.hash)) {
|
122 | return;
|
123 | }
|
124 | const existingBlock = await tryGetBlock({ hashOrIndex: this.hash });
|
125 | if (existingBlock !== undefined) {
|
126 | return;
|
127 | }
|
128 | const previousHeader = await tryGetHeader({
|
129 | hashOrIndex: this.previousHash,
|
130 | });
|
131 | if (previousHeader === undefined) {
|
132 | throw new VerifyError('Previous header does not exist.');
|
133 | }
|
134 | if (previousHeader.index + 1 !== this.index) {
|
135 | throw new VerifyError('Previous index + 1 does not match index.');
|
136 | }
|
137 | if (previousHeader.timestamp >= this.timestamp) {
|
138 | throw new VerifyError('Previous timestamp is greater than block.');
|
139 | }
|
140 | const { failureMessage } = await verifyScript({
|
141 | scriptContainer: { type: ScriptContainerType.Block, value: this },
|
142 | hash: previousHeader.nextConsensus,
|
143 | witness: this.script,
|
144 | });
|
145 | if (failureMessage !== undefined) {
|
146 | throw new VerifyError(failureMessage);
|
147 | }
|
148 | }
|
149 | async verifyComplete(options) {
|
150 | await Promise.all([
|
151 | this.verifyConsensus(options),
|
152 | this.verifyTransactions(options),
|
153 | this.verifyNetworkFee(options),
|
154 | ]);
|
155 | }
|
156 | async verifyConsensus({ getValidators }) {
|
157 | const validators = await getValidators(this.transactions);
|
158 | if (!common.uInt160Equal(this.nextConsensus, crypto.getConsensusAddress(validators))) {
|
159 | throw new VerifyError('Invalid next consensus address');
|
160 | }
|
161 | }
|
162 | async verifyTransactions(options) {
|
163 | const results = await Promise.all(this.transactions.map(async (transaction) => transaction.verify({
|
164 | isSpent: options.isSpent,
|
165 | getAsset: options.getAsset,
|
166 | getOutput: options.getOutput,
|
167 | tryGetAccount: options.tryGetAccount,
|
168 | calculateClaimAmount: options.calculateClaimAmount,
|
169 | standbyValidators: options.standbyValidators,
|
170 | getAllValidators: options.getAllValidators,
|
171 | verifyScript: options.verifyScript,
|
172 | currentHeight: options.currentHeight,
|
173 | governingToken: options.governingToken,
|
174 | utilityToken: options.utilityToken,
|
175 | fees: options.fees,
|
176 | registerValidatorFee: options.registerValidatorFee,
|
177 | })));
|
178 | const failureResults = results.filter((verifyResults) => verifyResults.some(({ failureMessage }) => failureMessage !== undefined));
|
179 | if (failureResults.length > 0) {
|
180 | const failureResult = failureResults[0].find(({ failureMessage }) => failureMessage !== undefined);
|
181 | if (failureResult !== undefined && failureResult.failureMessage !== undefined) {
|
182 | throw new VerifyError(failureResult.failureMessage);
|
183 | }
|
184 | }
|
185 | }
|
186 | async verifyNetworkFee(options) {
|
187 | const networkFee = await this.getNetworkFee({
|
188 | getOutput: options.getOutput,
|
189 | governingToken: options.governingToken,
|
190 | utilityToken: options.utilityToken,
|
191 | fees: options.fees,
|
192 | registerValidatorFee: options.registerValidatorFee,
|
193 | });
|
194 | const minerTransaction = this.transactions.find((transaction) => transaction.type === TransactionType.Miner);
|
195 | if (minerTransaction === undefined) {
|
196 | throw new VerifyError('Missing miner transaction');
|
197 | }
|
198 | const minerTransactionNetworkFee = minerTransaction.outputs.reduce((acc, output) => acc.add(output.value), utils.ZERO);
|
199 | if (!networkFee.eq(minerTransactionNetworkFee)) {
|
200 | throw new VerifyError('Miner output does not equal network fee.');
|
201 | }
|
202 | }
|
203 | }
|
204 |
|
205 | //# sourceMappingURL=data:application/json;charset=utf8;base64,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QUNILENBQUM7SUFFTyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsT0FBMkI7UUFDeEQsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDO1lBQzFDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixjQUFjLEVBQUUsT0FBTyxDQUFDLGNBQWM7WUFDdEMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO1lBQ2xDLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtZQUNsQixvQkFBb0IsRUFBRSxPQUFPLENBQUMsb0JBQW9CO1NBQ25ELENBQUMsQ0FBQztRQUVILE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEtBQUssZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTdHLElBQUksZ0JBQWdCLEtBQUssU0FBUyxFQUFFO1lBQ2xDLE1BQU0sSUFBSSxXQUFXLENBQUMsMkJBQTJCLENBQUMsQ0FBQztTQUNwRDtRQUVELE1BQU0sMEJBQTBCLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FDaEUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFDdEMsS0FBSyxDQUFDLElBQUksQ0FDWCxDQUFDO1FBRUYsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsMEJBQTBCLENBQUMsRUFBRTtZQUM5QyxNQUFNLElBQUksV0FBVyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7U0FDbkU7SUFDSCxDQUFDO0NBQ0YiLCJmaWxlIjoibmVvLW9uZS1ub2RlLWNvcmUvc3JjL0Jsb2NrLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQmluYXJ5V3JpdGVyLFxuICBCbG9ja0pTT04sXG4gIGNvbW1vbixcbiAgY3J5cHRvLFxuICBFQ1BvaW50LFxuICBJbnZhbGlkRm9ybWF0RXJyb3IsXG4gIElPSGVscGVyLFxuICBUcmFuc2FjdGlvbkpTT04sXG4gIFVJbnQxNjAsXG4gIFVJbnQyNTYsXG59IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb21tb24tZXNuZXh0LWVzbSc7XG5pbXBvcnQgQk4gZnJvbSAnYm4uanMnO1xuaW1wb3J0IHsgQWNjb3VudCwgQWNjb3VudEtleSB9IGZyb20gJy4vQWNjb3VudCc7XG5pbXBvcnQgeyBBc3NldCwgQXNzZXRLZXkgfSBmcm9tICcuL0Fzc2V0JztcbmltcG9ydCB7IEJsb2NrQmFzZSB9IGZyb20gJy4vQmxvY2tCYXNlJztcbmltcG9ydCB7IE1lcmtsZVRyZWUgfSBmcm9tICcuL2NyeXB0byc7XG5pbXBvcnQgeyBWZXJpZnlFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IEhlYWRlciwgSGVhZGVyS2V5IH0gZnJvbSAnLi9IZWFkZXInO1xuaW1wb3J0IHsgU2NyaXB0Q29udGFpbmVyVHlwZSB9IGZyb20gJy4vU2NyaXB0Q29udGFpbmVyJztcbmltcG9ydCB7XG4gIERlc2VyaWFsaXplV2lyZUJhc2VPcHRpb25zLFxuICBEZXNlcmlhbGl6ZVdpcmVPcHRpb25zLFxuICBTZXJpYWxpemFibGVKU09OLFxuICBTZXJpYWxpemFibGVXaXJlLFxuICBTZXJpYWxpemVKU09OQ29udGV4dCxcbn0gZnJvbSAnLi9TZXJpYWxpemFibGUnO1xuaW1wb3J0IHtcbiAgZGVzZXJpYWxpemVUcmFuc2FjdGlvbldpcmVCYXNlLFxuICBGZWVDb250ZXh0LFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBPdXRwdXRLZXksXG4gIFJlZ2lzdGVyVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uLFxuICBUcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJy4vdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgQmluYXJ5UmVhZGVyLCB1dGlscyB9IGZyb20gJy4vdXRpbHMnO1xuaW1wb3J0IHsgVmFsaWRhdG9yIH0gZnJvbSAnLi9WYWxpZGF0b3InO1xuaW1wb3J0IHsgVmVyaWZ5U2NyaXB0IH0gZnJvbSAnLi92bSc7XG5pbXBvcnQgeyBXaXRuZXNzIH0gZnJvbSAnLi9XaXRuZXNzJztcblxuZXhwb3J0IGludGVyZmFjZSBCbG9ja0FkZCB7XG4gIHJlYWRvbmx5IHZlcnNpb24/OiBudW1iZXI7XG4gIHJlYWRvbmx5IHByZXZpb3VzSGFzaDogVUludDI1NjtcbiAgcmVhZG9ubHkgbWVya2xlUm9vdD86IFVJbnQyNTY7XG4gIHJlYWRvbmx5IHRpbWVzdGFtcDogbnVtYmVyO1xuICByZWFkb25seSBpbmRleDogbnVtYmVyO1xuICByZWFkb25seSBjb25zZW5zdXNEYXRhOiBCTjtcbiAgcmVhZG9ubHkgbmV4dENvbnNlbnN1czogVUludDE2MDtcbiAgcmVhZG9ubHkgc2NyaXB0PzogV2l0bmVzcztcbiAgcmVhZG9ubHkgaGFzaD86IFVJbnQyNTY7XG4gIHJlYWRvbmx5IHRyYW5zYWN0aW9uczogUmVhZG9ubHlBcnJheTxUcmFuc2FjdGlvbj47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmxvY2tLZXkge1xuICByZWFkb25seSBoYXNoT3JJbmRleDogVUludDI1NiB8IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCbG9ja1ZlcmlmeU9wdGlvbnMge1xuICByZWFkb25seSBnZW5lc2lzQmxvY2s6IEJsb2NrO1xuICByZWFkb25seSB0cnlHZXRCbG9jazogKGJsb2NrOiBCbG9ja0tleSkgPT4gUHJvbWlzZTxCbG9jayB8IHVuZGVmaW5lZD47XG4gIHJlYWRvbmx5IHRyeUdldEhlYWRlcjogKGhlYWRlcjogSGVhZGVyS2V5KSA9PiBQcm9taXNlPEhlYWRlciB8IHVuZGVmaW5lZD47XG4gIHJlYWRvbmx5IGlzU3BlbnQ6IChrZXk6IE91dHB1dEtleSkgPT4gUHJvbWlzZTxib29sZWFuPjtcbiAgcmVhZG9ubHkgZ2V0QXNzZXQ6IChrZXk6IEFzc2V0S2V5KSA9PiBQcm9taXNlPEFzc2V0PjtcbiAgcmVhZG9ubHkgZ2V0T3V0cHV0OiAoa2V5OiBPdXRwdXRLZXkpID0+IFByb21pc2U8T3V0cHV0PjtcbiAgcmVhZG9ubHkgdHJ5R2V0QWNjb3VudDogKGtleTogQWNjb3VudEtleSkgPT4gUHJvbWlzZTxBY2NvdW50IHwgdW5kZWZpbmVkPjtcbiAgcmVhZG9ubHkgZ2V0VmFsaWRhdG9yczogKHRyYW5zYWN0aW9uczogUmVhZG9ubHlBcnJheTxUcmFuc2FjdGlvbj4pID0+IFByb21pc2U8UmVhZG9ubHlBcnJheTxFQ1BvaW50Pj47XG4gIHJlYWRvbmx5IHN0YW5kYnlWYWxpZGF0b3JzOiBSZWFkb25seUFycmF5PEVDUG9pbnQ+O1xuICByZWFkb25seSBnZXRBbGxWYWxpZGF0b3JzOiAoKSA9PiBQcm9taXNlPFJlYWRvbmx5QXJyYXk8VmFsaWRhdG9yPj47XG4gIHJlYWRvbmx5IGNhbGN1bGF0ZUNsYWltQW1vdW50OiAoaW5wdXRzOiBSZWFkb25seUFycmF5PElucHV0PikgPT4gUHJvbWlzZTxCTj47XG4gIHJlYWRvbmx5IHZlcmlmeVNjcmlwdDogVmVyaWZ5U2NyaXB0O1xuICByZWFkb25seSBjdXJyZW50SGVpZ2h0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGdvdmVybmluZ1Rva2VuOiBSZWdpc3RlclRyYW5zYWN0aW9uO1xuICByZWFkb25seSB1dGlsaXR5VG9rZW46IFJlZ2lzdGVyVHJhbnNhY3Rpb247XG4gIHJlYWRvbmx5IGZlZXM6IHsgW0sgaW4gVHJhbnNhY3Rpb25UeXBlXT86IEJOIH07XG4gIHJlYWRvbmx5IHJlZ2lzdGVyVmFsaWRhdG9yRmVlOiBCTjtcbiAgcmVhZG9ubHkgY29tcGxldGVseT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjbGFzcyBCbG9jayBleHRlbmRzIEJsb2NrQmFzZSBpbXBsZW1lbnRzIFNlcmlhbGl6YWJsZVdpcmU8QmxvY2s+LCBTZXJpYWxpemFibGVKU09OPEJsb2NrSlNPTj4ge1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGNhbGN1bGF0ZU5ldHdvcmtGZWUoY29udGV4dDogRmVlQ29udGV4dCwgdHJhbnNhY3Rpb25zOiBSZWFkb25seUFycmF5PFRyYW5zYWN0aW9uPik6IFByb21pc2U8Qk4+IHtcbiAgICBjb25zdCBmZWVzID0gYXdhaXQgUHJvbWlzZS5hbGwodHJhbnNhY3Rpb25zLm1hcChhc3luYyAodHJhbnNhY3Rpb24pID0+IHRyYW5zYWN0aW9uLmdldE5ldHdvcmtGZWUoY29udGV4dCkpKTtcblxuICAgIHJldHVybiBmZWVzLnJlZHVjZSgoYWNjLCBmZWUpID0+IGFjYy5hZGQoZmVlKSwgdXRpbHMuWkVSTyk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGRlc2VyaWFsaXplV2lyZUJhc2Uob3B0aW9uczogRGVzZXJpYWxpemVXaXJlQmFzZU9wdGlvbnMpOiBCbG9jayB7XG4gICAgY29uc3QgeyByZWFkZXIgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgYmxvY2tCYXNlID0gc3VwZXIuZGVzZXJpYWxpemVCbG9ja0Jhc2VXaXJlQmFzZShvcHRpb25zKTtcbiAgICBjb25zdCB0cmFuc2FjdGlvbnMgPSByZWFkZXIucmVhZEFycmF5KCgpID0+IGRlc2VyaWFsaXplVHJhbnNhY3Rpb25XaXJlQmFzZShvcHRpb25zKSwgMHgxMDAwMCk7XG5cbiAgICBpZiAodHJhbnNhY3Rpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRGb3JtYXRFcnJvcignRXhwZWN0ZWQgYXQgbGVhc3Qgb25lIHRyYW5zY2FjdGlvbiBpbiB0aGUgYmxvY2snKTtcbiAgICB9XG5cbiAgICBjb25zdCBtZXJrbGVSb290ID0gTWVya2xlVHJlZS5jb21wdXRlUm9vdCh0cmFuc2FjdGlvbnMubWFwKCh0cmFuc2FjdGlvbikgPT4gdHJhbnNhY3Rpb24uaGFzaCkpO1xuXG4gICAgaWYgKCFjb21tb24udUludDI1NkVxdWFsKG1lcmtsZVJvb3QsIGJsb2NrQmFzZS5tZXJrbGVSb290KSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRGb3JtYXRFcnJvcignSW52YWxpZCBtZXJrbGUgcm9vdCcpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgdGhpcyh7XG4gICAgICB2ZXJzaW9uOiBibG9ja0Jhc2UudmVyc2lvbixcbiAgICAgIHByZXZpb3VzSGFzaDogYmxvY2tCYXNlLnByZXZpb3VzSGFzaCxcbiAgICAgIG1lcmtsZVJvb3Q6IGJsb2NrQmFzZS5tZXJrbGVSb290LFxuICAgICAgdGltZXN0YW1wOiBibG9ja0Jhc2UudGltZXN0YW1wLFxuICAgICAgaW5kZXg6IGJsb2NrQmFzZS5pbmRleCxcbiAgICAgIGNvbnNlbnN1c0RhdGE6IGJsb2NrQmFzZS5jb25zZW5zdXNEYXRhLFxuICAgICAgbmV4dENvbnNlbnN1czogYmxvY2tCYXNlLm5leHRDb25zZW5zdXMsXG4gICAgICBzY3JpcHQ6IGJsb2NrQmFzZS5zY3JpcHQsXG4gICAgICB0cmFuc2FjdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGRlc2VyaWFsaXplV2lyZShvcHRpb25zOiBEZXNlcmlhbGl6ZVdpcmVPcHRpb25zKTogQmxvY2sge1xuICAgIHJldHVybiB0aGlzLmRlc2VyaWFsaXplV2lyZUJhc2Uoe1xuICAgICAgY29udGV4dDogb3B0aW9ucy5jb250ZXh0LFxuICAgICAgcmVhZGVyOiBuZXcgQmluYXJ5UmVhZGVyKG9wdGlvbnMuYnVmZmVyKSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSB0cmFuc2FjdGlvbnM6IFJlYWRvbmx5QXJyYXk8VHJhbnNhY3Rpb24+O1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc2l6ZUV4Y2x1c2l2ZSA9IHV0aWxzLmxhenkoKCkgPT5cbiAgICBJT0hlbHBlci5zaXplT2ZBcnJheSh0aGlzLnRyYW5zYWN0aW9ucywgKHRyYW5zYWN0aW9uKSA9PiB0cmFuc2FjdGlvbi5zaXplKSxcbiAgKTtcbiAgcHJpdmF0ZSByZWFkb25seSBoZWFkZXJJbnRlcm5hbCA9IHV0aWxzLmxhenkoXG4gICAgKCkgPT5cbiAgICAgIG5ldyBIZWFkZXIoe1xuICAgICAgICB2ZXJzaW9uOiB0aGlzLnZlcnNpb24sXG4gICAgICAgIHByZXZpb3VzSGFzaDogdGhpcy5wcmV2aW91c0hhc2gsXG4gICAgICAgIG1lcmtsZVJvb3Q6IHRoaXMubWVya2xlUm9vdCxcbiAgICAgICAgdGltZXN0YW1wOiB0aGlzLnRpbWVzdGFtcCxcbiAgICAgICAgaW5kZXg6IHRoaXMuaW5kZXgsXG4gICAgICAgIGNvbnNlbnN1c0RhdGE6IHRoaXMuY29uc2Vuc3VzRGF0YSxcbiAgICAgICAgbmV4dENvbnNlbnN1czogdGhpcy5uZXh0Q29uc2Vuc3VzLFxuICAgICAgICBzY3JpcHQ6IHRoaXMuc2NyaXB0LFxuICAgICAgfSksXG4gICk7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHtcbiAgICB2ZXJzaW9uLFxuICAgIHByZXZpb3VzSGFzaCxcbiAgICB0aW1lc3RhbXAsXG4gICAgaW5kZXgsXG4gICAgY29uc2Vuc3VzRGF0YSxcbiAgICBuZXh0Q29uc2Vuc3VzLFxuICAgIHNjcmlwdCxcbiAgICBoYXNoLFxuICAgIHRyYW5zYWN0aW9ucyxcbiAgICBtZXJrbGVSb290ID0gTWVya2xlVHJlZS5jb21wdXRlUm9vdCh0cmFuc2FjdGlvbnMubWFwKCh0cmFuc2FjdGlvbikgPT4gdHJhbnNhY3Rpb24uaGFzaCkpLFxuICB9OiBCbG9ja0FkZCkge1xuICAgIHN1cGVyKHtcbiAgICAgIHZlcnNpb24sXG4gICAgICBwcmV2aW91c0hhc2gsXG4gICAgICBtZXJrbGVSb290LFxuICAgICAgdGltZXN0YW1wLFxuICAgICAgaW5kZXgsXG4gICAgICBjb25zZW5zdXNEYXRhLFxuICAgICAgbmV4dENvbnNlbnN1cyxcbiAgICAgIHNjcmlwdCxcbiAgICAgIGhhc2gsXG4gICAgfSk7XG5cbiAgICB0aGlzLnRyYW5zYWN0aW9ucyA9IHRyYW5zYWN0aW9ucztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaGVhZGVyKCk6IEhlYWRlciB7XG4gICAgcmV0dXJuIHRoaXMuaGVhZGVySW50ZXJuYWwoKTtcbiAgfVxuXG4gIHB1YmxpYyBjbG9uZSh7XG4gICAgdHJhbnNhY3Rpb25zLFxuICAgIHNjcmlwdCxcbiAgfToge1xuICAgIHJlYWRvbmx5IHRyYW5zYWN0aW9uczogUmVhZG9ubHlBcnJheTxUcmFuc2FjdGlvbj47XG4gICAgcmVhZG9ubHkgc2NyaXB0OiBXaXRuZXNzO1xuICB9KTogQmxvY2sge1xuICAgIHJldHVybiBuZXcgQmxvY2soe1xuICAgICAgdmVyc2lvbjogdGhpcy52ZXJzaW9uLFxuICAgICAgcHJldmlvdXNIYXNoOiB0aGlzLnByZXZpb3VzSGFzaCxcbiAgICAgIG1lcmtsZVJvb3Q6IHRoaXMubWVya2xlUm9vdCxcbiAgICAgIHRpbWVzdGFtcDogdGhpcy50aW1lc3RhbXAsXG4gICAgICBpbmRleDogdGhpcy5pbmRleCxcbiAgICAgIGNvbnNlbnN1c0RhdGE6IHRoaXMuY29uc2Vuc3VzRGF0YSxcbiAgICAgIG5leHRDb25zZW5zdXM6IHRoaXMubmV4dENvbnNlbnN1cyxcbiAgICAgIHRyYW5zYWN0aW9ucyxcbiAgICAgIHNjcmlwdCxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBnZXROZXR3b3JrRmVlKGNvbnRleHQ6IEZlZUNvbnRleHQpOiBQcm9taXNlPEJOPiB7XG4gICAgcmV0dXJuIEJsb2NrLmNhbGN1bGF0ZU5ldHdvcmtGZWUoY29udGV4dCwgdGhpcy50cmFuc2FjdGlvbnMpO1xuICB9XG5cbiAgcHVibGljIGdldFN5c3RlbUZlZShjb250ZXh0OiBGZWVDb250ZXh0KTogQk4ge1xuICAgIHJldHVybiB0aGlzLnRyYW5zYWN0aW9ucy5yZWR1Y2UoKGFjYywgdHJhbnNhY3Rpb24pID0+IGFjYy5hZGQodHJhbnNhY3Rpb24uZ2V0U3lzdGVtRmVlKGNvbnRleHQpKSwgdXRpbHMuWkVSTyk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgdmVyaWZ5KG9wdGlvbnM6IEJsb2NrVmVyaWZ5T3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgY29tcGxldGVseSA9IGZhbHNlIH0gPSBvcHRpb25zO1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy50cmFuc2FjdGlvbnMubGVuZ3RoID09PSAwIHx8XG4gICAgICB0aGlzLnRyYW5zYWN0aW9uc1swXS50eXBlICE9PSBUcmFuc2FjdGlvblR5cGUuTWluZXIgfHxcbiAgICAgIHRoaXMudHJhbnNhY3Rpb25zLnNsaWNlKDEpLnNvbWUoKHRyYW5zYWN0aW9uKSA9PiB0cmFuc2FjdGlvbi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuTWluZXIpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ0ludmFsaWQgbWluZXIgdHJhbnNhY3Rpb24gaW4gYmxvY2suJyk7XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW3RoaXMudmVyaWZ5QmFzZShvcHRpb25zKSwgY29tcGxldGVseSA/IHRoaXMudmVyaWZ5Q29tcGxldGUob3B0aW9ucykgOiBQcm9taXNlLnJlc29sdmUoKV0pO1xuICB9XG5cbiAgcHVibGljIHNlcmlhbGl6ZVdpcmVCYXNlKHdyaXRlcjogQmluYXJ5V3JpdGVyKTogdm9pZCB7XG4gICAgc3VwZXIuc2VyaWFsaXplV2lyZUJhc2Uod3JpdGVyKTtcbiAgICB3cml0ZXIud3JpdGVBcnJheSh0aGlzLnRyYW5zYWN0aW9ucywgKHRyYW5zYWN0aW9uKSA9PiB0cmFuc2FjdGlvbi5zZXJpYWxpemVXaXJlQmFzZSh3cml0ZXIpKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzZXJpYWxpemVKU09OKGNvbnRleHQ6IFNlcmlhbGl6ZUpTT05Db250ZXh0KTogUHJvbWlzZTxCbG9ja0pTT04+IHtcbiAgICBjb25zdCBibG9ja0Jhc2VKU09OID0gc3VwZXIuc2VyaWFsaXplQmxvY2tCYXNlSlNPTihjb250ZXh0KTtcblxuICAgIHJldHVybiB7XG4gICAgICB2ZXJzaW9uOiBibG9ja0Jhc2VKU09OLnZlcnNpb24sXG4gICAgICBoYXNoOiBibG9ja0Jhc2VKU09OLmhhc2gsXG4gICAgICBwcmV2aW91c2Jsb2NraGFzaDogYmxvY2tCYXNlSlNPTi5wcmV2aW91c2Jsb2NraGFzaCxcbiAgICAgIG1lcmtsZXJvb3Q6IGJsb2NrQmFzZUpTT04ubWVya2xlcm9vdCxcbiAgICAgIHRpbWU6IGJsb2NrQmFzZUpTT04udGltZSxcbiAgICAgIGluZGV4OiBibG9ja0Jhc2VKU09OLmluZGV4LFxuICAgICAgbm9uY2U6IGJsb2NrQmFzZUpTT04ubm9uY2UsXG4gICAgICBuZXh0Y29uc2Vuc3VzOiBibG9ja0Jhc2VKU09OLm5leHRjb25zZW5zdXMsXG4gICAgICBzY3JpcHQ6IGJsb2NrQmFzZUpTT04uc2NyaXB0LFxuICAgICAgdHg6IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICB0aGlzLnRyYW5zYWN0aW9ucy5tYXAoXG4gICAgICAgICAgKHRyYW5zYWN0aW9uKSA9PiB0cmFuc2FjdGlvbi5zZXJpYWxpemVKU09OKGNvbnRleHQpIGFzIFRyYW5zYWN0aW9uSlNPTiB8IFByb21pc2VMaWtlPFRyYW5zYWN0aW9uSlNPTj4sXG4gICAgICAgICksXG4gICAgICApLFxuICAgICAgc2l6ZTogYmxvY2tCYXNlSlNPTi5zaXplLFxuICAgICAgY29uZmlybWF0aW9uczogYmxvY2tCYXNlSlNPTi5jb25maXJtYXRpb25zLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHZlcmlmeUJhc2Uoe1xuICAgIGdlbmVzaXNCbG9jayxcbiAgICB0cnlHZXRCbG9jayxcbiAgICB0cnlHZXRIZWFkZXIsXG4gICAgdmVyaWZ5U2NyaXB0LFxuICB9OiBCbG9ja1ZlcmlmeU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoY29tbW9uLnVJbnQyNTZFcXVhbCh0aGlzLmhhc2gsIGdlbmVzaXNCbG9jay5oYXNoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGV4aXN0aW5nQmxvY2sgPSBhd2FpdCB0cnlHZXRCbG9jayh7IGhhc2hPckluZGV4OiB0aGlzLmhhc2ggfSk7XG4gICAgaWYgKGV4aXN0aW5nQmxvY2sgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHByZXZpb3VzSGVhZGVyID0gYXdhaXQgdHJ5R2V0SGVhZGVyKHtcbiAgICAgIGhhc2hPckluZGV4OiB0aGlzLnByZXZpb3VzSGFzaCxcbiAgICB9KTtcblxuICAgIGlmIChwcmV2aW91c0hlYWRlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ1ByZXZpb3VzIGhlYWRlciBkb2VzIG5vdCBleGlzdC4nKTtcbiAgICB9XG5cbiAgICBpZiAocHJldmlvdXNIZWFkZXIuaW5kZXggKyAxICE9PSB0aGlzLmluZGV4KSB7XG4gICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ1ByZXZpb3VzIGluZGV4ICsgMSBkb2VzIG5vdCBtYXRjaCBpbmRleC4nKTtcbiAgICB9XG5cbiAgICBpZiAocHJldmlvdXNIZWFkZXIudGltZXN0YW1wID49IHRoaXMudGltZXN0YW1wKSB7XG4gICAgICB0aHJvdyBuZXcgVmVyaWZ5RXJyb3IoJ1ByZXZpb3VzIHRpbWVzdGFtcCBpcyBncmVhdGVyIHRoYW4gYmxvY2suJyk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBmYWlsdXJlTWVzc2FnZSB9ID0gYXdhaXQgdmVyaWZ5U2NyaXB0KHtcbiAgICAgIHNjcmlwdENvbnRhaW5lcjogeyB0eXBlOiBTY3JpcHRDb250YWluZXJUeXBlLkJsb2NrLCB2YWx1ZTogdGhpcyB9LFxuICAgICAgaGFzaDogcHJldmlvdXNIZWFkZXIubmV4dENvbnNlbnN1cyxcbiAgICAgIHdpdG5lc3M6IHRoaXMuc2NyaXB0LFxuICAgIH0pO1xuXG4gICAgaWYgKGZhaWx1cmVNZXNzYWdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBWZXJpZnlFcnJvcihmYWlsdXJlTWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB2ZXJpZnlDb21wbGV0ZShvcHRpb25zOiBCbG9ja1ZlcmlmeU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICB0aGlzLnZlcmlmeUNvbnNlbnN1cyhvcHRpb25zKSxcbiAgICAgIHRoaXMudmVyaWZ5VHJhbnNhY3Rpb25zKG9wdGlvbnMpLFxuICAgICAgdGhpcy52ZXJpZnlOZXR3b3JrRmVlKG9wdGlvbnMpLFxuICAgIF0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB2ZXJpZnlDb25zZW5zdXMoeyBnZXRWYWxpZGF0b3JzIH06IEJsb2NrVmVyaWZ5T3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHZhbGlkYXRvcnMgPSBhd2FpdCBnZXRWYWxpZGF0b3JzKHRoaXMudHJhbnNhY3Rpb25zKTtcbiAgICBpZiAoIWNvbW1vbi51SW50MTYwRXF1YWwodGhpcy5uZXh0Q29uc2Vuc3VzLCBjcnlwdG8uZ2V0Q29uc2Vuc3VzQWRkcmVzcyh2YWxpZGF0b3JzKSkpIHtcbiAgICAgIHRocm93IG5ldyBWZXJpZnlFcnJvcignSW52YWxpZCBuZXh0IGNvbnNlbnN1cyBhZGRyZXNzJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB2ZXJpZnlUcmFuc2FjdGlvbnMob3B0aW9uczogQmxvY2tWZXJpZnlPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgdGhpcy50cmFuc2FjdGlvbnMubWFwKGFzeW5jICh0cmFuc2FjdGlvbikgPT5cbiAgICAgICAgdHJhbnNhY3Rpb24udmVyaWZ5KHtcbiAgICAgICAgICBpc1NwZW50OiBvcHRpb25zLmlzU3BlbnQsXG4gICAgICAgICAgZ2V0QXNzZXQ6IG9wdGlvbnMuZ2V0QXNzZXQsXG4gICAgICAgICAgZ2V0T3V0cHV0OiBvcHRpb25zLmdldE91dHB1dCxcbiAgICAgICAgICB0cnlHZXRBY2NvdW50OiBvcHRpb25zLnRyeUdldEFjY291bnQsXG4gICAgICAgICAgY2FsY3VsYXRlQ2xhaW1BbW91bnQ6IG9wdGlvbnMuY2FsY3VsYXRlQ2xhaW1BbW91bnQsXG4gICAgICAgICAgc3RhbmRieVZhbGlkYXRvcnM6IG9wdGlvbnMuc3RhbmRieVZhbGlkYXRvcnMsXG4gICAgICAgICAgZ2V0QWxsVmFsaWRhdG9yczogb3B0aW9ucy5nZXRBbGxWYWxpZGF0b3JzLFxuICAgICAgICAgIHZlcmlmeVNjcmlwdDogb3B0aW9ucy52ZXJpZnlTY3JpcHQsXG4gICAgICAgICAgY3VycmVudEhlaWdodDogb3B0aW9ucy5jdXJyZW50SGVpZ2h0LFxuICAgICAgICAgIGdvdmVybmluZ1Rva2VuOiBvcHRpb25zLmdvdmVybmluZ1Rva2VuLFxuICAgICAgICAgIHV0aWxpdHlUb2tlbjogb3B0aW9ucy51dGlsaXR5VG9rZW4sXG4gICAgICAgICAgZmVlczogb3B0aW9ucy5mZWVzLFxuICAgICAgICAgIHJlZ2lzdGVyVmFsaWRhdG9yRmVlOiBvcHRpb25zLnJlZ2lzdGVyVmFsaWRhdG9yRmVlLFxuICAgICAgICB9KSxcbiAgICAgICksXG4gICAgKTtcbiAgICBjb25zdCBmYWlsdXJlUmVzdWx0cyA9IHJlc3VsdHMuZmlsdGVyKCh2ZXJpZnlSZXN1bHRzKSA9PlxuICAgICAgdmVyaWZ5UmVzdWx0cy5zb21lKCh7IGZhaWx1cmVNZXNzYWdlIH0pID0+IGZhaWx1cmVNZXNzYWdlICE9PSB1bmRlZmluZWQpLFxuICAgICk7XG4gICAgaWYgKGZhaWx1cmVSZXN1bHRzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGZhaWx1cmVSZXN1bHQgPSBmYWlsdXJlUmVzdWx0c1swXS5maW5kKCh7IGZhaWx1cmVNZXNzYWdlIH0pID0+IGZhaWx1cmVNZXNzYWdlICE9PSB1bmRlZmluZWQpO1xuICAgICAgaWYgKGZhaWx1cmVSZXN1bHQgIT09IHVuZGVmaW5lZCAmJiBmYWlsdXJlUmVzdWx0LmZhaWx1cmVNZXNzYWdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZlcmlmeUVycm9yKGZhaWx1cmVSZXN1bHQuZmFpbHVyZU1lc3NhZ2UpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdmVyaWZ5TmV0d29ya0ZlZShvcHRpb25zOiBCbG9ja1ZlcmlmeU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBuZXR3b3JrRmVlID0gYXdhaXQgdGhpcy5nZXROZXR3b3JrRmVlKHtcbiAgICAgIGdldE91dHB1dDogb3B0aW9ucy5nZXRPdXRwdXQsXG4gICAgICBnb3Zlcm5pbmdUb2tlbjogb3B0aW9ucy5nb3Zlcm5pbmdUb2tlbixcbiAgICAgIHV0aWxpdHlUb2tlbjogb3B0aW9ucy51dGlsaXR5VG9rZW4sXG4gICAgICBmZWVzOiBvcHRpb25zLmZlZXMsXG4gICAgICByZWdpc3RlclZhbGlkYXRvckZlZTogb3B0aW9ucy5yZWdpc3RlclZhbGlkYXRvckZlZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IG1pbmVyVHJhbnNhY3Rpb24gPSB0aGlzLnRyYW5zYWN0aW9ucy5maW5kKCh0cmFuc2FjdGlvbikgPT4gdHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLk1pbmVyKTtcblxuICAgIGlmIChtaW5lclRyYW5zYWN0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBWZXJpZnlFcnJvcignTWlzc2luZyBtaW5lciB0cmFuc2FjdGlvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IG1pbmVyVHJhbnNhY3Rpb25OZXR3b3JrRmVlID0gbWluZXJUcmFuc2FjdGlvbi5vdXRwdXRzLnJlZHVjZShcbiAgICAgIChhY2MsIG91dHB1dCkgPT4gYWNjLmFkZChvdXRwdXQudmFsdWUpLFxuICAgICAgdXRpbHMuWkVSTyxcbiAgICApO1xuXG4gICAgaWYgKCFuZXR3b3JrRmVlLmVxKG1pbmVyVHJhbnNhY3Rpb25OZXR3b3JrRmVlKSkge1xuICAgICAgdGhyb3cgbmV3IFZlcmlmeUVycm9yKCdNaW5lciBvdXRwdXQgZG9lcyBub3QgZXF1YWwgbmV0d29yayBmZWUuJyk7XG4gICAgfVxuICB9XG59XG4iXX0=
|