@bitgo/abstract-utxo 1.0.1-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.eslintignore +5 -0
  2. package/CHANGELOG.md +11 -0
  3. package/LICENSE +191 -0
  4. package/README.md +1 -0
  5. package/dist/src/abstractUtxoCoin.d.ts +388 -0
  6. package/dist/src/abstractUtxoCoin.d.ts.map +1 -0
  7. package/dist/src/abstractUtxoCoin.js +955 -0
  8. package/dist/src/config.d.ts +7 -0
  9. package/dist/src/config.d.ts.map +1 -0
  10. package/dist/src/config.js +12 -0
  11. package/dist/src/index.d.ts +6 -0
  12. package/dist/src/index.d.ts.map +1 -0
  13. package/dist/src/index.js +18 -0
  14. package/dist/src/parseOutput.d.ts +22 -0
  15. package/dist/src/parseOutput.d.ts.map +1 -0
  16. package/dist/src/parseOutput.js +169 -0
  17. package/dist/src/recovery/RecoveryProvider.d.ts +18 -0
  18. package/dist/src/recovery/RecoveryProvider.d.ts.map +1 -0
  19. package/dist/src/recovery/RecoveryProvider.js +23 -0
  20. package/dist/src/recovery/backupKeyRecovery.d.ts +56 -0
  21. package/dist/src/recovery/backupKeyRecovery.d.ts.map +1 -0
  22. package/dist/src/recovery/backupKeyRecovery.js +273 -0
  23. package/dist/src/recovery/baseApi.d.ts +27 -0
  24. package/dist/src/recovery/baseApi.d.ts.map +1 -0
  25. package/dist/src/recovery/baseApi.js +73 -0
  26. package/dist/src/recovery/coingeckoApi.d.ts +9 -0
  27. package/dist/src/recovery/coingeckoApi.d.ts.map +1 -0
  28. package/dist/src/recovery/coingeckoApi.js +47 -0
  29. package/dist/src/recovery/crossChainRecovery.d.ts +95 -0
  30. package/dist/src/recovery/crossChainRecovery.d.ts.map +1 -0
  31. package/dist/src/recovery/crossChainRecovery.js +318 -0
  32. package/dist/src/recovery/index.d.ts +8 -0
  33. package/dist/src/recovery/index.d.ts.map +1 -0
  34. package/dist/src/recovery/index.js +20 -0
  35. package/dist/src/recovery/mempoolApi.d.ts +7 -0
  36. package/dist/src/recovery/mempoolApi.d.ts.map +1 -0
  37. package/dist/src/recovery/mempoolApi.js +33 -0
  38. package/dist/src/recovery/smartbitApi.d.ts +11 -0
  39. package/dist/src/recovery/smartbitApi.d.ts.map +1 -0
  40. package/dist/src/recovery/smartbitApi.js +36 -0
  41. package/dist/src/replayProtection.d.ts +5 -0
  42. package/dist/src/replayProtection.d.ts.map +1 -0
  43. package/dist/src/replayProtection.js +21 -0
  44. package/dist/src/sign.d.ts +29 -0
  45. package/dist/src/sign.d.ts.map +1 -0
  46. package/dist/src/sign.js +104 -0
  47. package/dist/tsconfig.tsbuildinfo +7371 -0
  48. package/package.json +55 -0
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.signAndVerifyWalletTransaction = exports.TransactionSigningError = exports.InputSigningError = void 0;
4
+ /**
5
+ * @prettier
6
+ */
7
+ const utxolib = require("@bitgo/utxo-lib");
8
+ const bitgo_1 = require("@bitgo/utxo-lib/dist/src/bitgo");
9
+ const debugLib = require("debug");
10
+ const replayProtection_1 = require("./replayProtection");
11
+ const debug = debugLib('bitgo:v2:utxo');
12
+ class InputSigningError extends Error {
13
+ constructor(inputIndex, unspent, reason) {
14
+ super(`signing error at input ${inputIndex}: unspentId=${unspent.id}: ${reason}`);
15
+ this.inputIndex = inputIndex;
16
+ this.unspent = unspent;
17
+ this.reason = reason;
18
+ }
19
+ static expectedWalletUnspent(inputIndex, unspent) {
20
+ return new InputSigningError(inputIndex, unspent, `not a wallet unspent, not a replay protection unspent`);
21
+ }
22
+ }
23
+ exports.InputSigningError = InputSigningError;
24
+ class TransactionSigningError extends Error {
25
+ constructor(signErrors, verifyError) {
26
+ super(`sign errors at inputs: [${signErrors.join(',')}], ` +
27
+ `verify errors at inputs: [${verifyError.join(',')}], see log for details`);
28
+ }
29
+ }
30
+ exports.TransactionSigningError = TransactionSigningError;
31
+ /**
32
+ * Sign all inputs of a wallet transaction and verify signatures after signing.
33
+ * Collects and logs signing errors and verification errors, throws error in the end if any of them
34
+ * failed.
35
+ *
36
+ * @param transaction - wallet transaction (builder) to be signed
37
+ * @param unspents - transaction unspents
38
+ * @param walletSigner - signing parameters
39
+ * @param isLastSignature - Returns full-signed transaction when true. Builds half-signed when false.
40
+ */
41
+ function signAndVerifyWalletTransaction(transaction, unspents, walletSigner, { isLastSignature }) {
42
+ const network = transaction.network;
43
+ const prevOutputs = unspents.map((u) => bitgo_1.toOutput(u, network));
44
+ let txBuilder;
45
+ if (transaction instanceof utxolib.bitgo.UtxoTransaction) {
46
+ txBuilder = utxolib.bitgo.createTransactionBuilderFromTransaction(transaction, prevOutputs);
47
+ if (transaction.ins.length !== unspents.length) {
48
+ throw new Error(`transaction inputs must match unspents`);
49
+ }
50
+ }
51
+ else if (transaction instanceof utxolib.bitgo.UtxoTransactionBuilder) {
52
+ txBuilder = transaction;
53
+ }
54
+ else {
55
+ throw new Error(`must pass UtxoTransaction or UtxoTransactionBuilder`);
56
+ }
57
+ const signErrors = unspents
58
+ .map((unspent, inputIndex) => {
59
+ if (replayProtection_1.isReplayProtectionUnspent(unspent, network)) {
60
+ debug('Skipping signature for input %d of %d (RP input?)', inputIndex + 1, unspents.length);
61
+ return;
62
+ }
63
+ if (!bitgo_1.isWalletUnspent(unspent)) {
64
+ return InputSigningError.expectedWalletUnspent(inputIndex, unspent);
65
+ }
66
+ try {
67
+ bitgo_1.signInputWithUnspent(txBuilder, inputIndex, unspent, walletSigner);
68
+ debug('Successfully signed input %d of %d', inputIndex + 1, unspents.length);
69
+ }
70
+ catch (e) {
71
+ return new InputSigningError(inputIndex, unspent, e);
72
+ }
73
+ })
74
+ .filter((e) => e !== undefined);
75
+ const signedTransaction = isLastSignature ? txBuilder.build() : txBuilder.buildIncomplete();
76
+ const verifyErrors = signedTransaction.ins
77
+ .map((input, inputIndex) => {
78
+ const unspent = unspents[inputIndex];
79
+ if (replayProtection_1.isReplayProtectionUnspent(unspent, network)) {
80
+ debug('Skipping input signature %d of %d (unspent from replay protection address which is platform signed only)', inputIndex + 1, unspents.length);
81
+ return;
82
+ }
83
+ if (!bitgo_1.isWalletUnspent(unspent)) {
84
+ return InputSigningError.expectedWalletUnspent(inputIndex, unspent);
85
+ }
86
+ try {
87
+ const publicKey = walletSigner.deriveForChainAndIndex(unspent.chain, unspent.index).signer.publicKey;
88
+ if (!utxolib.bitgo.verifySignatureWithPublicKey(signedTransaction, inputIndex, prevOutputs, publicKey)) {
89
+ return new InputSigningError(inputIndex, unspent, new Error(`invalid signature`));
90
+ }
91
+ }
92
+ catch (e) {
93
+ debug('Invalid signature');
94
+ return new InputSigningError(inputIndex, unspent, e);
95
+ }
96
+ })
97
+ .filter((e) => e !== undefined);
98
+ if (signErrors.length || verifyErrors.length) {
99
+ throw new TransactionSigningError(signErrors, verifyErrors);
100
+ }
101
+ return signedTransaction;
102
+ }
103
+ exports.signAndVerifyWalletTransaction = signAndVerifyWalletTransaction;
104
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zaWduLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBOztHQUVHO0FBQ0gsMkNBQTJDO0FBQzNDLDBEQU93QztBQUN4QyxrQ0FBa0M7QUFFbEMseURBQStEO0FBRS9ELE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUV4QyxNQUFhLGlCQUFrQixTQUFRLEtBQUs7SUFLMUMsWUFBbUIsVUFBa0IsRUFBUyxPQUFnQixFQUFTLE1BQXNCO1FBQzNGLEtBQUssQ0FBQywwQkFBMEIsVUFBVSxlQUFlLE9BQU8sQ0FBQyxFQUFFLEtBQUssTUFBTSxFQUFFLENBQUMsQ0FBQztRQURqRSxlQUFVLEdBQVYsVUFBVSxDQUFRO1FBQVMsWUFBTyxHQUFQLE9BQU8sQ0FBUztRQUFTLFdBQU0sR0FBTixNQUFNLENBQWdCO0lBRTdGLENBQUM7SUFORCxNQUFNLENBQUMscUJBQXFCLENBQUMsVUFBa0IsRUFBRSxPQUFnQjtRQUMvRCxPQUFPLElBQUksaUJBQWlCLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSx1REFBdUQsQ0FBQyxDQUFDO0lBQzdHLENBQUM7Q0FLRjtBQVJELDhDQVFDO0FBRUQsTUFBYSx1QkFBd0IsU0FBUSxLQUFLO0lBQ2hELFlBQVksVUFBK0IsRUFBRSxXQUFnQztRQUMzRSxLQUFLLENBQ0gsMkJBQTJCLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUs7WUFDbEQsNkJBQTZCLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUM3RSxDQUFDO0lBQ0osQ0FBQztDQUNGO0FBUEQsMERBT0M7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxTQUFnQiw4QkFBOEIsQ0FDNUMsV0FBaUYsRUFDakYsUUFBbUIsRUFDbkIsWUFBaUQsRUFDakQsRUFBRSxlQUFlLEVBQWdDO0lBRWpELE1BQU0sT0FBTyxHQUFHLFdBQVcsQ0FB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aUJBQWlCLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxTQUFTLENBQUMsRUFBRTtnQkFDdEcsT0FBTyxJQUFJLGlCQUFpQixDQUFDLFVBQVUsRUFBRSxPQUFPLEVBQUUsSUFBSSxLQUFLLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO2FBQ25GO1NBQ0Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzNCLE9BQU8sSUFBSSxpQkFBaUIsQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ3REO0lBQ0gsQ0FBQyxDQUFDO1NBQ0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUEwQixFQUFFLENBQUMsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxDQUFDO0lBRTFELElBQUksVUFBVSxDQUFDLE1BQU0sSUFBSSxZQUFZLENBQUMsTUFBTSxFQUFFO1FBQzVDLE1BQU0sSUFBSSx1QkFBdUIsQ0FBQyxVQUFVLEVBQUUsWUFBWSxDQUFDLENBQUM7S0FDN0Q7SUFFRCxPQUFPLGlCQUFpQixDQUFDO0FBQzNCLENBQUM7QUF4RUQsd0VBd0VDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuaW1wb3J0ICogYXMgdXR4b2xpYiBmcm9tICdAYml0Z28vdXR4by1saWInO1xuaW1wb3J0IHtcbiAgaXNXYWxsZXRVbnNwZW50LFxuICBSb290V2FsbGV0S2V5cyxcbiAgc2lnbklucHV0V2l0aFVuc3BlbnQsXG4gIHRvT3V0cHV0LFxuICBVbnNwZW50LFxuICBXYWxsZXRVbnNwZW50U2lnbmVyLFxufSBmcm9tICdAYml0Z28vdXR4by1saWIvZGlzdC9zcmMvYml0Z28nO1xuaW1wb3J0ICogYXMgZGVidWdMaWIgZnJvbSAnZGVidWcnO1xuXG5pbXBvcnQgeyBpc1JlcGxheVByb3RlY3Rpb25VbnNwZW50IH0gZnJvbSAnLi9yZXBsYXlQcm90ZWN0aW9uJztcblxuY29uc3QgZGVidWcgPSBkZWJ1Z0xpYignYml0Z286djI6dXR4bycpO1xuXG5leHBvcnQgY2xhc3MgSW5wdXRTaWduaW5nRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIHN0YXRpYyBleHBlY3RlZFdhbGxldFVuc3BlbnQoaW5wdXRJbmRleDogbnVtYmVyLCB1bnNwZW50OiBVbnNwZW50KTogSW5wdXRTaWduaW5nRXJyb3Ige1xuICAgIHJldHVybiBuZXcgSW5wdXRTaWduaW5nRXJyb3IoaW5wdXRJbmRleCwgdW5zcGVudCwgYG5vdCBhIHdhbGxldCB1bnNwZW50LCBub3QgYSByZXBsYXkgcHJvdGVjdGlvbiB1bnNwZW50YCk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgaW5wdXRJbmRleDogbnVtYmVyLCBwdWJsaWMgdW5zcGVudDogVW5zcGVudCwgcHVibGljIHJlYXNvbjogRXJyb3IgfCBzdHJpbmcpIHtcbiAgICBzdXBlcihgc2lnbmluZyBlcnJvciBhdCBpbnB1dCAke2lucHV0SW5kZXh9OiB1bnNwZW50SWQ9JHt1bnNwZW50LmlkfTogJHtyZWFzb259YCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRyYW5zYWN0aW9uU2lnbmluZ0Vycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihzaWduRXJyb3JzOiBJbnB1dFNpZ25pbmdFcnJvcltdLCB2ZXJpZnlFcnJvcjogSW5wdXRTaWduaW5nRXJyb3JbXSkge1xuICAgIHN1cGVyKFxuICAgICAgYHNpZ24gZXJyb3JzIGF0IGlucHV0czogWyR7c2lnbkVycm9ycy5qb2luKCcsJyl9XSwgYCArXG4gICAgICAgIGB2ZXJpZnkgZXJyb3JzIGF0IGlucHV0czogWyR7dmVyaWZ5RXJyb3Iuam9pbignLCcpfV0sIHNlZSBsb2cgZm9yIGRldGFpbHNgXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIFNpZ24gYWxsIGlucHV0cyBvZiBhIHdhbGxldCB0cmFuc2FjdGlvbiBhbmQgdmVyaWZ5IHNpZ25hdHVyZXMgYWZ0ZXIgc2lnbmluZy5cbiAqIENvbGxlY3RzIGFuZCBsb2dzIHNpZ25pbmcgZXJyb3JzIGFuZCB2ZXJpZmljYXRpb24gZXJyb3JzLCB0aHJvd3MgZXJyb3IgaW4gdGhlIGVuZCBpZiBhbnkgb2YgdGhlbVxuICogZmFpbGVkLlxuICpcbiAqIEBwYXJhbSB0cmFuc2FjdGlvbiAtIHdhbGxldCB0cmFuc2FjdGlvbiAoYnVpbGRlcikgdG8gYmUgc2lnbmVkXG4gKiBAcGFyYW0gdW5zcGVudHMgLSB0cmFuc2FjdGlvbiB1bnNwZW50c1xuICogQHBhcmFtIHdhbGxldFNpZ25lciAtIHNpZ25pbmcgcGFyYW1ldGVyc1xuICogQHBhcmFtIGlzTGFzdFNpZ25hdHVyZSAtIFJldHVybnMgZnVsbC1zaWduZWQgdHJhbnNhY3Rpb24gd2hlbiB0cnVlLiBCdWlsZHMgaGFsZi1zaWduZWQgd2hlbiBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNpZ25BbmRWZXJpZnlXYWxsZXRUcmFuc2FjdGlvbihcbiAgdHJhbnNhY3Rpb246IHV0eG9saWIuYml0Z28uVXR4b1RyYW5zYWN0aW9uIHwgdXR4b2xpYi5iaXRnby5VdHhvVHJhbnNhY3Rpb25CdWlsZGVyLFxuICB1bnNwZW50czogVW5zcGVudFtdLFxuICB3YWxsZXRTaWduZXI6IFdhbGxldFVuc3BlbnRTaWduZXI8Um9vdFdhbGxldEtleXM+LFxuICB7IGlzTGFzdFNpZ25hdHVyZSB9OiB7IGlzTGFzdFNpZ25hdHVyZTogYm9vbGVhbiB9XG4pOiB1dHhvbGliLmJpdGdvLlV0eG9UcmFuc2FjdGlvbiB7XG4gIGNvbnN0IG5ldHdvcmsgPSB0cmFuc2FjdGlvbi5uZXR3b3JrIGFzIHV0eG9saWIuTmV0d29yaztcbiAgY29uc3QgcHJldk91dHB1dHMgPSB1bnNwZW50cy5tYXAoKHUpID0+IHRvT3V0cHV0KHUsIG5ldHdvcmspKTtcblxuICBsZXQgdHhCdWlsZGVyOiB1dHhvbGliLmJpdGdvLlV0eG9UcmFuc2FjdGlvbkJ1aWxkZXI7XG4gIGlmICh0cmFuc2FjdGlvbiBpbnN0YW5jZW9mIHV0eG9saWIuYml0Z28uVXR4b1RyYW5zYWN0aW9uKSB7XG4gICAgdHhCdWlsZGVyID0gdXR4b2xpYi5iaXRnby5jcmVhdGVUcmFuc2FjdGlvbkJ1aWxkZXJGcm9tVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24sIHByZXZPdXRwdXRzKTtcbiAgICBpZiAodHJhbnNhY3Rpb24uaW5zLmxlbmd0aCAhPT0gdW5zcGVudHMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHRyYW5zYWN0aW9uIGlucHV0cyBtdXN0IG1hdGNoIHVuc3BlbnRzYCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgdXR4b2xpYi5iaXRnby5VdHhvVHJhbnNhY3Rpb25CdWlsZGVyKSB7XG4gICAgdHhCdWlsZGVyID0gdHJhbnNhY3Rpb247XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBtdXN0IHBhc3MgVXR4b1RyYW5zYWN0aW9uIG9yIFV0eG9UcmFuc2FjdGlvbkJ1aWxkZXJgKTtcbiAgfVxuXG4gIGNvbnN0IHNpZ25FcnJvcnM6IElucHV0U2lnbmluZ0Vycm9yW10gPSB1bnNwZW50c1xuICAgIC5tYXAoKHVuc3BlbnQ6IFVuc3BlbnQsIGlucHV0SW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgaWYgKGlzUmVwbGF5UHJvdGVjdGlvblVuc3BlbnQodW5zcGVudCwgbmV0d29yaykpIHtcbiAgICAgICAgZGVidWcoJ1NraXBwaW5nIHNpZ25hdHVyZSBmb3IgaW5wdXQgJWQgb2YgJWQgKFJQIGlucHV0PyknLCBpbnB1dEluZGV4ICsgMSwgdW5zcGVudHMubGVuZ3RoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKCFpc1dhbGxldFVuc3BlbnQodW5zcGVudCkpIHtcbiAgICAgICAgcmV0dXJuIElucHV0U2lnbmluZ0Vycm9yLmV4cGVjdGVkV2FsbGV0VW5zcGVudChpbnB1dEluZGV4LCB1bnNwZW50KTtcbiAgICAgIH1cbiAgICAgIHRyeSB7XG4gICAgICAgIHNpZ25JbnB1dFdpdGhVbnNwZW50KHR4QnVpbGRlciwgaW5wdXRJbmRleCwgdW5zcGVudCwgd2FsbGV0U2lnbmVyKTtcbiAgICAgICAgZGVidWcoJ1N1Y2Nlc3NmdWxseSBzaWduZWQgaW5wdXQgJWQgb2YgJWQnLCBpbnB1dEluZGV4ICsgMSwgdW5zcGVudHMubGVuZ3RoKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnB1dFNpZ25pbmdFcnJvcihpbnB1dEluZGV4LCB1bnNwZW50LCBlKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC5maWx0ZXIoKGUpOiBlIGlzIElucHV0U2lnbmluZ0Vycm9yID0+IGUgIT09IHVuZGVmaW5lZCk7XG5cbiAgY29uc3Qgc2lnbmVkVHJhbnNhY3Rpb24gPSBpc0xhc3RTaWduYXR1cmUgPyB0eEJ1aWxkZXIuYnVpbGQoKSA6IHR4QnVpbGRlci5idWlsZEluY29tcGxldGUoKTtcblxuICBjb25zdCB2ZXJpZnlFcnJvcnM6IElucHV0U2lnbmluZ0Vycm9yW10gPSBzaWduZWRUcmFuc2FjdGlvbi5pbnNcbiAgICAubWFwKChpbnB1dCwgaW5wdXRJbmRleCkgPT4ge1xuICAgICAgY29uc3QgdW5zcGVudCA9IHVuc3BlbnRzW2lucHV0SW5kZXhdIGFzIFVuc3BlbnQ7XG4gICAgICBpZiAoaXNSZXBsYXlQcm90ZWN0aW9uVW5zcGVudCh1bnNwZW50LCBuZXR3b3JrKSkge1xuICAgICAgICBkZWJ1ZyhcbiAgICAgICAgICAnU2tpcHBpbmcgaW5wdXQgc2lnbmF0dXJlICVkIG9mICVkICh1bnNwZW50IGZyb20gcmVwbGF5IHByb3RlY3Rpb24gYWRkcmVzcyB3aGljaCBpcyBwbGF0Zm9ybSBzaWduZWQgb25seSknLFxuICAgICAgICAgIGlucHV0SW5kZXggKyAxLFxuICAgICAgICAgIHVuc3BlbnRzLmxlbmd0aFxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWlzV2FsbGV0VW5zcGVudCh1bnNwZW50KSkge1xuICAgICAgICByZXR1cm4gSW5wdXRTaWduaW5nRXJyb3IuZXhwZWN0ZWRXYWxsZXRVbnNwZW50KGlucHV0SW5kZXgsIHVuc3BlbnQpO1xuICAgICAgfVxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcHVibGljS2V5ID0gd2FsbGV0U2lnbmVyLmRlcml2ZUZvckNoYWluQW5kSW5kZXgodW5zcGVudC5jaGFpbiwgdW5zcGVudC5pbmRleCkuc2lnbmVyLnB1YmxpY0tleTtcbiAgICAgICAgaWYgKCF1dHhvbGliLmJpdGdvLnZlcmlmeVNpZ25hdHVyZVdpdGhQdWJsaWNLZXkoc2lnbmVkVHJhbnNhY3Rpb24sIGlucHV0SW5kZXgsIHByZXZPdXRwdXRzLCBwdWJsaWNLZXkpKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBJbnB1dFNpZ25pbmdFcnJvcihpbnB1dEluZGV4LCB1bnNwZW50LCBuZXcgRXJyb3IoYGludmFsaWQgc2lnbmF0dXJlYCkpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGRlYnVnKCdJbnZhbGlkIHNpZ25hdHVyZScpO1xuICAgICAgICByZXR1cm4gbmV3IElucHV0U2lnbmluZ0Vycm9yKGlucHV0SW5kZXgsIHVuc3BlbnQsIGUpO1xuICAgICAgfVxuICAgIH0pXG4gICAgLmZpbHRlcigoZSk6IGUgaXMgSW5wdXRTaWduaW5nRXJyb3IgPT4gZSAhPT0gdW5kZWZpbmVkKTtcblxuICBpZiAoc2lnbkVycm9ycy5sZW5ndGggfHwgdmVyaWZ5RXJyb3JzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBUcmFuc2FjdGlvblNpZ25pbmdFcnJvcihzaWduRXJyb3JzLCB2ZXJpZnlFcnJvcnMpO1xuICB9XG5cbiAgcmV0dXJuIHNpZ25lZFRyYW5zYWN0aW9uO1xufVxuIl19