UNPKG

38.6 kBJavaScriptView Raw
1import { common, createSerializeWire, crypto, InvalidFormatError, IOHelper, } from '@neo-one/client-common-esnext-esm';
2import { BinaryReader, Block, ConsensusPayload, deserializeTransactionWire, } from '@neo-one/node-core-esnext-esm';
3import { makeErrorWithCode, utils } from '@neo-one/utils-esnext-esm';
4import { Transform } from 'stream';
5import { assertCommand, Command } from './Command';
6import { AddrPayload, FilterAddPayload, FilterLoadPayload, GetBlocksPayload, HeadersPayload, InvPayload, MerkleBlockPayload, VersionPayload, } from './payload';
7export const COMMAND_LENGTH = 12;
8export const PAYLOAD_MAX_SIZE = 0x02000000;
9const calculateChecksum = (buffer) => common.toUInt32LE(crypto.hash256(buffer));
10const deserializeMessageHeader = ({ context, reader, }) => {
11 if (reader.readUInt32LE() !== context.messageMagic) {
12 throw new InvalidFormatError();
13 }
14 const command = assertCommand(reader.readFixedString(COMMAND_LENGTH));
15 const length = reader.readUInt32LE();
16 if (length > PAYLOAD_MAX_SIZE) {
17 throw new InvalidFormatError();
18 }
19 const checksum = reader.readUInt32LE();
20 return { command, length, checksum };
21};
22export class Message {
23 constructor({ magic, value }) {
24 this.serializeWire = createSerializeWire(this.serializeWireBase.bind(this));
25 this.magic = magic;
26 this.value = value;
27 }
28 static deserializeWireBase(options) {
29 const { reader, context } = options;
30 const { command, length, checksum } = deserializeMessageHeader(options);
31 const payloadBuffer = reader.readBytes(length);
32 if (calculateChecksum(payloadBuffer) !== checksum) {
33 throw new InvalidFormatError();
34 }
35 const payloadOptions = {
36 context: options.context,
37 buffer: payloadBuffer,
38 };
39 let value;
40 switch (command) {
41 case Command.addr:
42 value = {
43 command: Command.addr,
44 payload: AddrPayload.deserializeWire(payloadOptions),
45 };
46 break;
47 case Command.block:
48 value = {
49 command: Command.block,
50 payload: Block.deserializeWire(payloadOptions),
51 };
52 break;
53 case Command.consensus:
54 value = {
55 command: Command.consensus,
56 payload: ConsensusPayload.deserializeWire(payloadOptions),
57 };
58 break;
59 case Command.filteradd:
60 value = {
61 command: Command.filteradd,
62 payload: FilterAddPayload.deserializeWire(payloadOptions),
63 };
64 break;
65 case Command.filterclear:
66 value = { command: Command.filterclear };
67 break;
68 case Command.filterload:
69 value = {
70 command: Command.filterload,
71 payload: FilterLoadPayload.deserializeWire(payloadOptions),
72 };
73 break;
74 case Command.getaddr:
75 value = { command: Command.getaddr };
76 break;
77 case Command.getblocks:
78 value = {
79 command: Command.getblocks,
80 payload: GetBlocksPayload.deserializeWire(payloadOptions),
81 };
82 break;
83 case Command.getdata:
84 value = {
85 command: Command.getdata,
86 payload: InvPayload.deserializeWire(payloadOptions),
87 };
88 break;
89 case Command.getheaders:
90 value = {
91 command: Command.getheaders,
92 payload: GetBlocksPayload.deserializeWire(payloadOptions),
93 };
94 break;
95 case Command.headers:
96 value = {
97 command: Command.headers,
98 payload: HeadersPayload.deserializeWire(payloadOptions),
99 };
100 break;
101 case Command.inv:
102 value = {
103 command: Command.inv,
104 payload: InvPayload.deserializeWire(payloadOptions),
105 };
106 break;
107 case Command.mempool:
108 value = { command: Command.mempool };
109 break;
110 case Command.tx:
111 value = {
112 command: Command.tx,
113 payload: deserializeTransactionWire(payloadOptions),
114 };
115 break;
116 case Command.verack:
117 value = { command: Command.verack };
118 break;
119 case Command.version:
120 value = {
121 command: Command.version,
122 payload: VersionPayload.deserializeWire(payloadOptions),
123 };
124 break;
125 case Command.alert:
126 value = { command: Command.alert };
127 break;
128 case Command.merkleblock:
129 value = {
130 command: Command.merkleblock,
131 payload: MerkleBlockPayload.deserializeWire(payloadOptions),
132 };
133 break;
134 case Command.notfound:
135 value = { command: Command.notfound };
136 break;
137 case Command.ping:
138 value = { command: Command.ping };
139 break;
140 case Command.pong:
141 value = { command: Command.pong };
142 break;
143 case Command.reject:
144 value = { command: Command.reject };
145 break;
146 default:
147 utils.assertNever(command);
148 throw new InvalidFormatError();
149 }
150 return new this({ magic: context.messageMagic, value });
151 }
152 static deserializeWire(options) {
153 return this.deserializeWireBase({
154 context: options.context,
155 reader: new BinaryReader(options.buffer),
156 });
157 }
158 serializeWireBase(writer) {
159 const { value } = this;
160 writer.writeUInt32LE(this.magic);
161 writer.writeFixedString(value.command, COMMAND_LENGTH);
162 let payload = Buffer.alloc(0);
163 switch (value.command) {
164 case Command.addr:
165 payload = value.payload.serializeWire();
166 break;
167 case Command.block:
168 payload = value.payload.serializeWire();
169 break;
170 case Command.consensus:
171 payload = value.payload.serializeWire();
172 break;
173 case Command.filteradd:
174 payload = value.payload.serializeWire();
175 break;
176 case Command.filterclear:
177 break;
178 case Command.filterload:
179 payload = value.payload.serializeWire();
180 break;
181 case Command.getaddr:
182 break;
183 case Command.getblocks:
184 payload = value.payload.serializeWire();
185 break;
186 case Command.getdata:
187 payload = value.payload.serializeWire();
188 break;
189 case Command.getheaders:
190 payload = value.payload.serializeWire();
191 break;
192 case Command.headers:
193 payload = value.payload.serializeWire();
194 break;
195 case Command.inv:
196 payload = value.payload.serializeWire();
197 break;
198 case Command.mempool:
199 break;
200 case Command.tx:
201 payload = value.payload.serializeWire();
202 break;
203 case Command.verack:
204 break;
205 case Command.version:
206 payload = value.payload.serializeWire();
207 break;
208 case Command.alert:
209 break;
210 case Command.merkleblock:
211 payload = value.payload.serializeWire();
212 break;
213 case Command.notfound:
214 break;
215 case Command.ping:
216 break;
217 case Command.pong:
218 break;
219 case Command.reject:
220 break;
221 default:
222 utils.assertNever(value);
223 throw new InvalidFormatError();
224 }
225 writer.writeUInt32LE(payload.length);
226 writer.writeUInt32LE(calculateChecksum(payload));
227 writer.writeBytes(payload);
228 }
229}
230export const InvalidMessageTransformEncodingError = makeErrorWithCode('INVALID_MESSAGE_TRANSFORM_ENCODING', (message) => message);
231const SIZE_OF_MESSAGE_HEADER = IOHelper.sizeOfUInt32LE +
232 IOHelper.sizeOfFixedString(COMMAND_LENGTH) +
233 IOHelper.sizeOfUInt32LE +
234 IOHelper.sizeOfUInt32LE;
235export class MessageTransform extends Transform {
236 constructor(context) {
237 super({ readableObjectMode: true });
238 this.context = context;
239 this.mutableBuffer = Buffer.from([]);
240 }
241 _transform(chunk, encoding, callback) {
242 if (typeof chunk === 'string') {
243 throw new InvalidMessageTransformEncodingError(`Invalid Message Transform Chunk Type. Expected chunk type to be 'string', found: ${typeof chunk}`);
244 }
245 if (encoding !== 'buffer') {
246 throw new InvalidMessageTransformEncodingError(`Invalid Message Transform Encoding. Expected: 'buffer', found: ${encoding}`);
247 }
248 this.mutableBuffer = Buffer.concat([this.mutableBuffer, chunk]);
249 try {
250 const { remainingBuffer, mutableMessages } = this.processBuffer(new BinaryReader(this.mutableBuffer));
251 this.mutableBuffer = remainingBuffer;
252 mutableMessages.forEach((message) => this.push(message));
253 callback(undefined);
254 }
255 catch (error) {
256 callback(error);
257 }
258 }
259 processBuffer(reader) {
260 if (reader.remaining < SIZE_OF_MESSAGE_HEADER) {
261 return { remainingBuffer: reader.remainingBuffer, mutableMessages: [] };
262 }
263 const { length } = deserializeMessageHeader({
264 context: this.context,
265 reader: reader.clone(),
266 });
267 if (reader.remaining < SIZE_OF_MESSAGE_HEADER + length) {
268 return { remainingBuffer: reader.remainingBuffer, mutableMessages: [] };
269 }
270 const message = Message.deserializeWireBase({
271 context: this.context,
272 reader,
273 });
274 const { remainingBuffer, mutableMessages } = this.processBuffer(reader);
275 mutableMessages.push(message);
276 return { remainingBuffer, mutableMessages };
277 }
278}
279
280//# sourceMappingURL=data:application/json;charset=utf8;base64,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LENBQUM7U0FDekU7UUFFRCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsd0JBQXdCLENBQUM7WUFDMUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ3JCLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxFQUFFO1NBQ3ZCLENBQUMsQ0FBQztRQUVILElBQUksTUFBTSxDQUFDLFNBQVMsR0FBRyxzQkFBc0IsR0FBRyxNQUFNLEVBQUU7WUFDdEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLENBQUMsZUFBZSxFQUFFLGVBQWUsRUFBRSxFQUFFLEVBQUUsQ0FBQztTQUN6RTtRQUVELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQztZQUMxQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsTUFBTTtTQUNQLENBQUMsQ0FBQztRQUVILE1BQU0sRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4RSxlQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTlCLE9BQU8sRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLENBQUM7SUFDOUMsQ0FBQztDQUNGIiwiZmlsZSI6Im5lby1vbmUtbm9kZS1wcm90b2NvbC9zcmMvTWVzc2FnZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEJpbmFyeVdyaXRlcixcbiAgY29tbW9uLFxuICBjcmVhdGVTZXJpYWxpemVXaXJlLFxuICBjcnlwdG8sXG4gIEludmFsaWRGb3JtYXRFcnJvcixcbiAgSU9IZWxwZXIsXG4gIFNlcmlhbGl6YWJsZVdpcmUsXG4gIFNlcmlhbGl6ZVdpcmUsXG59IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb21tb24tZXNuZXh0LWVzbSc7XG5pbXBvcnQge1xuICBCaW5hcnlSZWFkZXIsXG4gIEJsb2NrLFxuICBDb25zZW5zdXNQYXlsb2FkLFxuICBkZXNlcmlhbGl6ZVRyYW5zYWN0aW9uV2lyZSxcbiAgRGVzZXJpYWxpemVXaXJlQmFzZU9wdGlvbnMsXG4gIERlc2VyaWFsaXplV2lyZUNvbnRleHQsXG4gIERlc2VyaWFsaXplV2lyZU9wdGlvbnMsXG4gIFRyYW5zYWN0aW9uLFxufSBmcm9tICdAbmVvLW9uZS9ub2RlLWNvcmUtZXNuZXh0LWVzbSc7XG5pbXBvcnQgeyBtYWtlRXJyb3JXaXRoQ29kZSwgdXRpbHMgfSBmcm9tICdAbmVvLW9uZS91dGlscy1lc25leHQtZXNtJztcbmltcG9ydCB7IFRyYW5zZm9ybSB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBhc3NlcnRDb21tYW5kLCBDb21tYW5kIH0gZnJvbSAnLi9Db21tYW5kJztcbmltcG9ydCB7XG4gIEFkZHJQYXlsb2FkLFxuICBGaWx0ZXJBZGRQYXlsb2FkLFxuICBGaWx0ZXJMb2FkUGF5bG9hZCxcbiAgR2V0QmxvY2tzUGF5bG9hZCxcbiAgSGVhZGVyc1BheWxvYWQsXG4gIEludlBheWxvYWQsXG4gIE1lcmtsZUJsb2NrUGF5bG9hZCxcbiAgVmVyc2lvblBheWxvYWQsXG59IGZyb20gJy4vcGF5bG9hZCc7XG5leHBvcnQgdHlwZSBNZXNzYWdlVmFsdWUgPVxuICB8IHsgcmVhZG9ubHkgY29tbWFuZDogQ29tbWFuZC5hZGRyOyByZWFkb25seSBwYXlsb2FkOiBBZGRyUGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLmJsb2NrOyByZWFkb25seSBwYXlsb2FkOiBCbG9jayB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLmNvbnNlbnN1czsgcmVhZG9ubHkgcGF5bG9hZDogQ29uc2Vuc3VzUGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLmZpbHRlcmFkZDsgcmVhZG9ubHkgcGF5bG9hZDogRmlsdGVyQWRkUGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLmZpbHRlcmNsZWFyIH1cbiAgfCB7IHJlYWRvbmx5IGNvbW1hbmQ6IENvbW1hbmQuZmlsdGVybG9hZDsgcmVhZG9ubHkgcGF5bG9hZDogRmlsdGVyTG9hZFBheWxvYWQgfVxuICB8IHsgcmVhZG9ubHkgY29tbWFuZDogQ29tbWFuZC5nZXRhZGRyIH1cbiAgfCB7IHJlYWRvbmx5IGNvbW1hbmQ6IENvbW1hbmQuZ2V0YmxvY2tzOyByZWFkb25seSBwYXlsb2FkOiBHZXRCbG9ja3NQYXlsb2FkIH1cbiAgfCB7IHJlYWRvbmx5IGNvbW1hbmQ6IENvbW1hbmQuZ2V0ZGF0YTsgcmVhZG9ubHkgcGF5bG9hZDogSW52UGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLmdldGhlYWRlcnM7IHJlYWRvbmx5IHBheWxvYWQ6IEdldEJsb2Nrc1BheWxvYWQgfVxuICB8IHsgcmVhZG9ubHkgY29tbWFuZDogQ29tbWFuZC5oZWFkZXJzOyByZWFkb25seSBwYXlsb2FkOiBIZWFkZXJzUGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLmludjsgcmVhZG9ubHkgcGF5bG9hZDogSW52UGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLm1lbXBvb2wgfVxuICB8IHsgcmVhZG9ubHkgY29tbWFuZDogQ29tbWFuZC50eDsgcmVhZG9ubHkgcGF5bG9hZDogVHJhbnNhY3Rpb24gfVxuICB8IHsgcmVhZG9ubHkgY29tbWFuZDogQ29tbWFuZC52ZXJhY2sgfVxuICB8IHsgcmVhZG9ubHkgY29tbWFuZDogQ29tbWFuZC52ZXJzaW9uOyByZWFkb25seSBwYXlsb2FkOiBWZXJzaW9uUGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLmFsZXJ0IH1cbiAgfCB7IHJlYWRvbmx5IGNvbW1hbmQ6IENvbW1hbmQubWVya2xlYmxvY2s7IHJlYWRvbmx5IHBheWxvYWQ6IE1lcmtsZUJsb2NrUGF5bG9hZCB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLm5vdGZvdW5kIH1cbiAgfCB7IHJlYWRvbmx5IGNvbW1hbmQ6IENvbW1hbmQucGluZyB9XG4gIHwgeyByZWFkb25seSBjb21tYW5kOiBDb21tYW5kLnBvbmcgfVxuICB8IHsgcmVhZG9ubHkgY29tbWFuZDogQ29tbWFuZC5yZWplY3QgfTtcbmV4cG9ydCBpbnRlcmZhY2UgTWVzc2FnZUFkZCB7XG4gIHJlYWRvbmx5IG1hZ2ljOiBudW1iZXI7XG4gIHJlYWRvbmx5IHZhbHVlOiBNZXNzYWdlVmFsdWU7XG59XG5cbmV4cG9ydCBjb25zdCBDT01NQU5EX0xFTkdUSCA9IDEyO1xuZXhwb3J0IGNvbnN0IFBBWUxPQURfTUFYX1NJWkUgPSAweDAyMDAwMDAwO1xuXG5jb25zdCBjYWxjdWxhdGVDaGVja3N1bSA9IChidWZmZXI6IEJ1ZmZlcikgPT4gY29tbW9uLnRvVUludDMyTEUoY3J5cHRvLmhhc2gyNTYoYnVmZmVyKSk7XG5cbmNvbnN0IGRlc2VyaWFsaXplTWVzc2FnZUhlYWRlciA9ICh7XG4gIGNvbnRleHQsXG4gIHJlYWRlcixcbn06IERlc2VyaWFsaXplV2lyZUJhc2VPcHRpb25zKToge1xuICByZWFkb25seSBjb21tYW5kOiBDb21tYW5kO1xuICByZWFkb25seSBsZW5ndGg6IG51bWJlcjtcbiAgcmVhZG9ubHkgY2hlY2tzdW06IG51bWJlcjtcbn0gPT4ge1xuICBpZiAocmVhZGVyLnJlYWRVSW50MzJMRSgpICE9PSBjb250ZXh0Lm1lc3NhZ2VNYWdpYykge1xuICAgIHRocm93IG5ldyBJbnZhbGlkRm9ybWF0RXJyb3IoKTtcbiAgfVxuICBjb25zdCBjb21tYW5kID0gYXNzZXJ0Q29tbWFuZChyZWFkZXIucmVhZEZpeGVkU3RyaW5nKENPTU1BTkRfTEVOR1RIKSk7XG4gIGNvbnN0IGxlbmd0aCA9IHJlYWRlci5yZWFkVUludDMyTEUoKTtcbiAgaWYgKGxlbmd0aCA+IFBBWUxPQURfTUFYX1NJWkUpIHtcbiAgICB0aHJvdyBuZXcgSW52YWxpZEZvcm1hdEVycm9yKCk7XG4gIH1cbiAgY29uc3QgY2hlY2tzdW0gPSByZWFkZXIucmVhZFVJbnQzMkxFKCk7XG5cbiAgcmV0dXJuIHsgY29tbWFuZCwgbGVuZ3RoLCBjaGVja3N1bSB9O1xufTtcblxuZXhwb3J0IGNsYXNzIE1lc3NhZ2UgaW1wbGVtZW50cyBTZXJpYWxpemFibGVXaXJlPE1lc3NhZ2U+IHtcbiAgcHVibGljIHN0YXRpYyBkZXNlcmlhbGl6ZVdpcmVCYXNlKG9wdGlvbnM6IERlc2VyaWFsaXplV2lyZUJhc2VPcHRpb25zKTogTWVzc2FnZSB7XG4gICAgY29uc3QgeyByZWFkZXIsIGNvbnRleHQgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgeyBjb21tYW5kLCBsZW5ndGgsIGNoZWNrc3VtIH0gPSBkZXNlcmlhbGl6ZU1lc3NhZ2VIZWFkZXIob3B0aW9ucyk7XG4gICAgY29uc3QgcGF5bG9hZEJ1ZmZlciA9IHJlYWRlci5yZWFkQnl0ZXMobGVuZ3RoKTtcbiAgICBpZiAoY2FsY3VsYXRlQ2hlY2tzdW0ocGF5bG9hZEJ1ZmZlcikgIT09IGNoZWNrc3VtKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEZvcm1hdEVycm9yKCk7XG4gICAgfVxuXG4gICAgY29uc3QgcGF5bG9hZE9wdGlvbnMgPSB7XG4gICAgICBjb250ZXh0OiBvcHRpb25zLmNvbnRleHQsXG4gICAgICBidWZmZXI6IHBheWxvYWRCdWZmZXIsXG4gICAgfTtcblxuICAgIGxldCB2YWx1ZTogTWVzc2FnZVZhbHVlO1xuICAgIHN3aXRjaCAoY29tbWFuZCkge1xuICAgICAgY2FzZSBDb21tYW5kLmFkZHI6XG4gICAgICAgIHZhbHVlID0ge1xuICAgICAgICAgIGNvbW1hbmQ6IENvbW1hbmQuYWRkcixcbiAgICAgICAgICBwYXlsb2FkOiBBZGRyUGF5bG9hZC5kZXNlcmlhbGl6ZVdpcmUocGF5bG9hZE9wdGlvbnMpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmJsb2NrOlxuICAgICAgICB2YWx1ZSA9IHtcbiAgICAgICAgICBjb21tYW5kOiBDb21tYW5kLmJsb2NrLFxuICAgICAgICAgIHBheWxvYWQ6IEJsb2NrLmRlc2VyaWFsaXplV2lyZShwYXlsb2FkT3B0aW9ucyksXG4gICAgICAgIH07XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuY29uc2Vuc3VzOlxuICAgICAgICB2YWx1ZSA9IHtcbiAgICAgICAgICBjb21tYW5kOiBDb21tYW5kLmNvbnNlbnN1cyxcbiAgICAgICAgICBwYXlsb2FkOiBDb25zZW5zdXNQYXlsb2FkLmRlc2VyaWFsaXplV2lyZShwYXlsb2FkT3B0aW9ucyksXG4gICAgICAgIH07XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuZmlsdGVyYWRkOlxuICAgICAgICB2YWx1ZSA9IHtcbiAgICAgICAgICBjb21tYW5kOiBDb21tYW5kLmZpbHRlcmFkZCxcbiAgICAgICAgICBwYXlsb2FkOiBGaWx0ZXJBZGRQYXlsb2FkLmRlc2VyaWFsaXplV2lyZShwYXlsb2FkT3B0aW9ucyksXG4gICAgICAgIH07XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuZmlsdGVyY2xlYXI6XG4gICAgICAgIHZhbHVlID0geyBjb21tYW5kOiBDb21tYW5kLmZpbHRlcmNsZWFyIH07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmZpbHRlcmxvYWQ6XG4gICAgICAgIHZhbHVlID0ge1xuICAgICAgICAgIGNvbW1hbmQ6IENvbW1hbmQuZmlsdGVybG9hZCxcbiAgICAgICAgICBwYXlsb2FkOiBGaWx0ZXJMb2FkUGF5bG9hZC5kZXNlcmlhbGl6ZVdpcmUocGF5bG9hZE9wdGlvbnMpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmdldGFkZHI6XG4gICAgICAgIHZhbHVlID0geyBjb21tYW5kOiBDb21tYW5kLmdldGFkZHIgfTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuZ2V0YmxvY2tzOlxuICAgICAgICB2YWx1ZSA9IHtcbiAgICAgICAgICBjb21tYW5kOiBDb21tYW5kLmdldGJsb2NrcyxcbiAgICAgICAgICBwYXlsb2FkOiBHZXRCbG9ja3NQYXlsb2FkLmRlc2VyaWFsaXplV2lyZShwYXlsb2FkT3B0aW9ucyksXG4gICAgICAgIH07XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuZ2V0ZGF0YTpcbiAgICAgICAgdmFsdWUgPSB7XG4gICAgICAgICAgY29tbWFuZDogQ29tbWFuZC5nZXRkYXRhLFxuICAgICAgICAgIHBheWxvYWQ6IEludlBheWxvYWQuZGVzZXJpYWxpemVXaXJlKHBheWxvYWRPcHRpb25zKSxcbiAgICAgICAgfTtcblxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5nZXRoZWFkZXJzOlxuICAgICAgICB2YWx1ZSA9IHtcbiAgICAgICAgICBjb21tYW5kOiBDb21tYW5kLmdldGhlYWRlcnMsXG4gICAgICAgICAgcGF5bG9hZDogR2V0QmxvY2tzUGF5bG9hZC5kZXNlcmlhbGl6ZVdpcmUocGF5bG9hZE9wdGlvbnMpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmhlYWRlcnM6XG4gICAgICAgIHZhbHVlID0ge1xuICAgICAgICAgIGNvbW1hbmQ6IENvbW1hbmQuaGVhZGVycyxcbiAgICAgICAgICBwYXlsb2FkOiBIZWFkZXJzUGF5bG9hZC5kZXNlcmlhbGl6ZVdpcmUocGF5bG9hZE9wdGlvbnMpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmludjpcbiAgICAgICAgdmFsdWUgPSB7XG4gICAgICAgICAgY29tbWFuZDogQ29tbWFuZC5pbnYsXG4gICAgICAgICAgcGF5bG9hZDogSW52UGF5bG9hZC5kZXNlcmlhbGl6ZVdpcmUocGF5bG9hZE9wdGlvbnMpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLm1lbXBvb2w6XG4gICAgICAgIHZhbHVlID0geyBjb21tYW5kOiBDb21tYW5kLm1lbXBvb2wgfTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQudHg6XG4gICAgICAgIHZhbHVlID0ge1xuICAgICAgICAgIGNvbW1hbmQ6IENvbW1hbmQudHgsXG4gICAgICAgICAgcGF5bG9hZDogZGVzZXJpYWxpemVUcmFuc2FjdGlvbldpcmUocGF5bG9hZE9wdGlvbnMpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnZlcmFjazpcbiAgICAgICAgdmFsdWUgPSB7IGNvbW1hbmQ6IENvbW1hbmQudmVyYWNrIH07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnZlcnNpb246XG4gICAgICAgIHZhbHVlID0ge1xuICAgICAgICAgIGNvbW1hbmQ6IENvbW1hbmQudmVyc2lvbixcbiAgICAgICAgICBwYXlsb2FkOiBWZXJzaW9uUGF5bG9hZC5kZXNlcmlhbGl6ZVdpcmUocGF5bG9hZE9wdGlvbnMpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmFsZXJ0OlxuICAgICAgICB2YWx1ZSA9IHsgY29tbWFuZDogQ29tbWFuZC5hbGVydCB9O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5tZXJrbGVibG9jazpcbiAgICAgICAgdmFsdWUgPSB7XG4gICAgICAgICAgY29tbWFuZDogQ29tbWFuZC5tZXJrbGVibG9jayxcbiAgICAgICAgICBwYXlsb2FkOiBNZXJrbGVCbG9ja1BheWxvYWQuZGVzZXJpYWxpemVXaXJlKHBheWxvYWRPcHRpb25zKSxcbiAgICAgICAgfTtcblxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5ub3Rmb3VuZDpcbiAgICAgICAgdmFsdWUgPSB7IGNvbW1hbmQ6IENvbW1hbmQubm90Zm91bmQgfTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQucGluZzpcbiAgICAgICAgdmFsdWUgPSB7IGNvbW1hbmQ6IENvbW1hbmQucGluZyB9O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5wb25nOlxuICAgICAgICB2YWx1ZSA9IHsgY29tbWFuZDogQ29tbWFuZC5wb25nIH07XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnJlamVjdDpcbiAgICAgICAgdmFsdWUgPSB7IGNvbW1hbmQ6IENvbW1hbmQucmVqZWN0IH07XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdXRpbHMuYXNzZXJ0TmV2ZXIoY29tbWFuZCk7XG4gICAgICAgIHRocm93IG5ldyBJbnZhbGlkRm9ybWF0RXJyb3IoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IHRoaXMoeyBtYWdpYzogY29udGV4dC5tZXNzYWdlTWFnaWMsIHZhbHVlIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBkZXNlcmlhbGl6ZVdpcmUob3B0aW9uczogRGVzZXJpYWxpemVXaXJlT3B0aW9ucyk6IE1lc3NhZ2Uge1xuICAgIHJldHVybiB0aGlzLmRlc2VyaWFsaXplV2lyZUJhc2Uoe1xuICAgICAgY29udGV4dDogb3B0aW9ucy5jb250ZXh0LFxuICAgICAgcmVhZGVyOiBuZXcgQmluYXJ5UmVhZGVyKG9wdGlvbnMuYnVmZmVyKSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBtYWdpYzogbnVtYmVyO1xuICBwdWJsaWMgcmVhZG9ubHkgdmFsdWU6IE1lc3NhZ2VWYWx1ZTtcbiAgcHVibGljIHJlYWRvbmx5IHNlcmlhbGl6ZVdpcmU6IFNlcmlhbGl6ZVdpcmUgPSBjcmVhdGVTZXJpYWxpemVXaXJlKHRoaXMuc2VyaWFsaXplV2lyZUJhc2UuYmluZCh0aGlzKSk7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHsgbWFnaWMsIHZhbHVlIH06IE1lc3NhZ2VBZGQpIHtcbiAgICB0aGlzLm1hZ2ljID0gbWFnaWM7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG5cbiAgcHVibGljIHNlcmlhbGl6ZVdpcmVCYXNlKHdyaXRlcjogQmluYXJ5V3JpdGVyKTogdm9pZCB7XG4gICAgY29uc3QgeyB2YWx1ZSB9ID0gdGhpcztcblxuICAgIHdyaXRlci53cml0ZVVJbnQzMkxFKHRoaXMubWFnaWMpO1xuICAgIHdyaXRlci53cml0ZUZpeGVkU3RyaW5nKHZhbHVlLmNvbW1hbmQsIENPTU1BTkRfTEVOR1RIKTtcblxuICAgIGxldCBwYXlsb2FkID0gQnVmZmVyLmFsbG9jKDApO1xuICAgIHN3aXRjaCAodmFsdWUuY29tbWFuZCkge1xuICAgICAgY2FzZSBDb21tYW5kLmFkZHI6XG4gICAgICAgIHBheWxvYWQgPSB2YWx1ZS5wYXlsb2FkLnNlcmlhbGl6ZVdpcmUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuYmxvY2s6XG4gICAgICAgIHBheWxvYWQgPSB2YWx1ZS5wYXlsb2FkLnNlcmlhbGl6ZVdpcmUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuY29uc2Vuc3VzOlxuICAgICAgICBwYXlsb2FkID0gdmFsdWUucGF5bG9hZC5zZXJpYWxpemVXaXJlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmZpbHRlcmFkZDpcbiAgICAgICAgcGF5bG9hZCA9IHZhbHVlLnBheWxvYWQuc2VyaWFsaXplV2lyZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5maWx0ZXJjbGVhcjpcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuZmlsdGVybG9hZDpcbiAgICAgICAgcGF5bG9hZCA9IHZhbHVlLnBheWxvYWQuc2VyaWFsaXplV2lyZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5nZXRhZGRyOlxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5nZXRibG9ja3M6XG4gICAgICAgIHBheWxvYWQgPSB2YWx1ZS5wYXlsb2FkLnNlcmlhbGl6ZVdpcmUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuZ2V0ZGF0YTpcbiAgICAgICAgcGF5bG9hZCA9IHZhbHVlLnBheWxvYWQuc2VyaWFsaXplV2lyZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5nZXRoZWFkZXJzOlxuICAgICAgICBwYXlsb2FkID0gdmFsdWUucGF5bG9hZC5zZXJpYWxpemVXaXJlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLmhlYWRlcnM6XG4gICAgICAgIHBheWxvYWQgPSB2YWx1ZS5wYXlsb2FkLnNlcmlhbGl6ZVdpcmUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQuaW52OlxuICAgICAgICBwYXlsb2FkID0gdmFsdWUucGF5bG9hZC5zZXJpYWxpemVXaXJlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLm1lbXBvb2w6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnR4OlxuICAgICAgICBwYXlsb2FkID0gdmFsdWUucGF5bG9hZC5zZXJpYWxpemVXaXJlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnZlcmFjazpcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQudmVyc2lvbjpcbiAgICAgICAgcGF5bG9hZCA9IHZhbHVlLnBheWxvYWQuc2VyaWFsaXplV2lyZSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ29tbWFuZC5hbGVydDpcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQubWVya2xlYmxvY2s6XG4gICAgICAgIHBheWxvYWQgPSB2YWx1ZS5wYXlsb2FkLnNlcmlhbGl6ZVdpcmUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIENvbW1hbmQubm90Zm91bmQ6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnBpbmc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnBvbmc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBDb21tYW5kLnJlamVjdDpcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB1dGlscy5hc3NlcnROZXZlcih2YWx1ZSk7XG4gICAgICAgIHRocm93IG5ldyBJbnZhbGlkRm9ybWF0RXJyb3IoKTtcbiAgICB9XG5cbiAgICB3cml0ZXIud3JpdGVVSW50MzJMRShwYXlsb2FkLmxlbmd0aCk7XG4gICAgd3JpdGVyLndyaXRlVUludDMyTEUoY2FsY3VsYXRlQ2hlY2tzdW0ocGF5bG9hZCkpO1xuICAgIHdyaXRlci53cml0ZUJ5dGVzKHBheWxvYWQpO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBJbnZhbGlkTWVzc2FnZVRyYW5zZm9ybUVuY29kaW5nRXJyb3IgPSBtYWtlRXJyb3JXaXRoQ29kZShcbiAgJ0lOVkFMSURfTUVTU0FHRV9UUkFOU0ZPUk1fRU5DT0RJTkcnLFxuICAobWVzc2FnZTogc3RyaW5nKSA9PiBtZXNzYWdlLFxuKTtcblxuY29uc3QgU0laRV9PRl9NRVNTQUdFX0hFQURFUiA9XG4gIElPSGVscGVyLnNpemVPZlVJbnQzMkxFICtcbiAgSU9IZWxwZXIuc2l6ZU9mRml4ZWRTdHJpbmcoQ09NTUFORF9MRU5HVEgpICtcbiAgSU9IZWxwZXIuc2l6ZU9mVUludDMyTEUgK1xuICBJT0hlbHBlci5zaXplT2ZVSW50MzJMRTtcblxuZXhwb3J0IGNsYXNzIE1lc3NhZ2VUcmFuc2Zvcm0gZXh0ZW5kcyBUcmFuc2Zvcm0ge1xuICBwdWJsaWMgcmVhZG9ubHkgY29udGV4dDogRGVzZXJpYWxpemVXaXJlQ29udGV4dDtcbiAgcHVibGljIG11dGFibGVCdWZmZXI6IEJ1ZmZlcjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoY29udGV4dDogRGVzZXJpYWxpemVXaXJlQ29udGV4dCkge1xuICAgIHN1cGVyKHsgcmVhZGFibGVPYmplY3RNb2RlOiB0cnVlIH0pO1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgdGhpcy5tdXRhYmxlQnVmZmVyID0gQnVmZmVyLmZyb20oW10pO1xuICB9XG5cbiAgcHVibGljIF90cmFuc2Zvcm0oXG4gICAgY2h1bms6IEJ1ZmZlciB8IHN0cmluZyxcbiAgICBlbmNvZGluZzogc3RyaW5nLFxuICAgIGNhbGxiYWNrOiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkLCBkYXRhPzogQnVmZmVyIHwgc3RyaW5nKSA9PiB2b2lkLFxuICApOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIGNodW5rID09PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRNZXNzYWdlVHJhbnNmb3JtRW5jb2RpbmdFcnJvcihcbiAgICAgICAgYEludmFsaWQgTWVzc2FnZSBUcmFuc2Zvcm0gQ2h1bmsgVHlwZS4gRXhwZWN0ZWQgY2h1bmsgdHlwZSB0byBiZSAnc3RyaW5nJywgZm91bmQ6ICR7dHlwZW9mIGNodW5rfWAsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoZW5jb2RpbmcgIT09ICdidWZmZXInKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZE1lc3NhZ2VUcmFuc2Zvcm1FbmNvZGluZ0Vycm9yKFxuICAgICAgICBgSW52YWxpZCBNZXNzYWdlIFRyYW5zZm9ybSBFbmNvZGluZy4gRXhwZWN0ZWQ6ICdidWZmZXInLCBmb3VuZDogJHtlbmNvZGluZ31gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLm11dGFibGVCdWZmZXIgPSBCdWZmZXIuY29uY2F0KFt0aGlzLm11dGFibGVCdWZmZXIsIGNodW5rXSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgcmVtYWluaW5nQnVmZmVyLCBtdXRhYmxlTWVzc2FnZXMgfSA9IHRoaXMucHJvY2Vzc0J1ZmZlcihuZXcgQmluYXJ5UmVhZGVyKHRoaXMubXV0YWJsZUJ1ZmZlcikpO1xuXG4gICAgICB0aGlzLm11dGFibGVCdWZmZXIgPSByZW1haW5pbmdCdWZmZXI7XG4gICAgICBtdXRhYmxlTWVzc2FnZXMuZm9yRWFjaCgobWVzc2FnZSkgPT4gdGhpcy5wdXNoKG1lc3NhZ2UpKTtcbiAgICAgIGNhbGxiYWNrKHVuZGVmaW5lZCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNhbGxiYWNrKGVycm9yKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NCdWZmZXIoXG4gICAgcmVhZGVyOiBCaW5hcnlSZWFkZXIsXG4gICk6IHtcbiAgICByZWFkb25seSByZW1haW5pbmdCdWZmZXI6IEJ1ZmZlcjtcbiAgICByZWFkb25seSBtdXRhYmxlTWVzc2FnZXM6IE1lc3NhZ2VbXTtcbiAgfSB7XG4gICAgaWYgKHJlYWRlci5yZW1haW5pbmcgPCBTSVpFX09GX01FU1NBR0VfSEVBREVSKSB7XG4gICAgICByZXR1cm4geyByZW1haW5pbmdCdWZmZXI6IHJlYWRlci5yZW1haW5pbmdCdWZmZXIsIG11dGFibGVNZXNzYWdlczogW10gfTtcbiAgICB9XG5cbiAgICBjb25zdCB7IGxlbmd0aCB9ID0gZGVzZXJpYWxpemVNZXNzYWdlSGVhZGVyKHtcbiAgICAgIGNvbnRleHQ6IHRoaXMuY29udGV4dCxcbiAgICAgIHJlYWRlcjogcmVhZGVyLmNsb25lKCksXG4gICAgfSk7XG5cbiAgICBpZiAocmVhZGVyLnJlbWFpbmluZyA8IFNJWkVfT0ZfTUVTU0FHRV9IRUFERVIgKyBsZW5ndGgpIHtcbiAgICAgIHJldHVybiB7IHJlbWFpbmluZ0J1ZmZlcjogcmVhZGVyLnJlbWFpbmluZ0J1ZmZlciwgbXV0YWJsZU1lc3NhZ2VzOiBbXSB9O1xuICAgIH1cblxuICAgIGNvbnN0IG1lc3NhZ2UgPSBNZXNzYWdlLmRlc2VyaWFsaXplV2lyZUJhc2Uoe1xuICAgICAgY29udGV4dDogdGhpcy5jb250ZXh0LFxuICAgICAgcmVhZGVyLFxuICAgIH0pO1xuXG4gICAgY29uc3QgeyByZW1haW5pbmdCdWZmZXIsIG11dGFibGVNZXNzYWdlcyB9ID0gdGhpcy5wcm9jZXNzQnVmZmVyKHJlYWRlcik7XG4gICAgbXV0YWJsZU1lc3NhZ2VzLnB1c2gobWVzc2FnZSk7XG5cbiAgICByZXR1cm4geyByZW1haW5pbmdCdWZmZXIsIG11dGFibGVNZXNzYWdlcyB9O1xuICB9XG59XG4iXX0=