@bitgo-beta/utxo-staking 1.1.1-beta.91 → 1.1.1-beta.910

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 (137) hide show
  1. package/dist/cjs/scripts/babylon-sync.d.ts +2 -0
  2. package/dist/cjs/scripts/babylon-sync.d.ts.map +1 -0
  3. package/dist/cjs/scripts/babylon-sync.js +126 -0
  4. package/dist/cjs/src/babylon/delegationMessage.d.ts +38 -0
  5. package/dist/cjs/src/babylon/delegationMessage.d.ts.map +1 -0
  6. package/dist/cjs/src/babylon/delegationMessage.js +285 -0
  7. package/dist/cjs/src/babylon/descriptor.d.ts +48 -0
  8. package/dist/cjs/src/babylon/descriptor.d.ts.map +1 -0
  9. package/dist/cjs/src/babylon/descriptor.js +97 -0
  10. package/dist/cjs/src/babylon/index.d.ts +8 -0
  11. package/dist/cjs/src/babylon/index.d.ts.map +1 -0
  12. package/dist/cjs/src/babylon/index.js +51 -0
  13. package/dist/cjs/src/babylon/network.d.ts +7 -0
  14. package/dist/cjs/src/babylon/network.d.ts.map +1 -0
  15. package/dist/cjs/src/babylon/network.js +66 -0
  16. package/dist/cjs/src/babylon/params.mainnet.json +152 -0
  17. package/dist/cjs/src/babylon/params.testnet.json +212 -0
  18. package/dist/cjs/src/babylon/parseDescriptor.d.ts +26 -0
  19. package/dist/cjs/src/babylon/parseDescriptor.d.ts.map +1 -0
  20. package/dist/cjs/src/babylon/parseDescriptor.js +159 -0
  21. package/dist/cjs/src/babylon/stakingManager.d.ts +6 -0
  22. package/dist/cjs/src/babylon/stakingManager.d.ts.map +1 -0
  23. package/dist/cjs/src/babylon/stakingManager.js +120 -0
  24. package/dist/cjs/src/babylon/stakingParams.d.ts +40 -0
  25. package/dist/cjs/src/babylon/stakingParams.d.ts.map +1 -0
  26. package/dist/cjs/src/babylon/stakingParams.js +132 -0
  27. package/dist/cjs/src/babylon/undelegation/UndelegationResponse.d.ts +24 -0
  28. package/dist/cjs/src/babylon/undelegation/UndelegationResponse.d.ts.map +1 -0
  29. package/dist/cjs/src/babylon/undelegation/UndelegationResponse.js +55 -0
  30. package/dist/cjs/src/babylon/undelegation/index.d.ts +3 -0
  31. package/dist/cjs/src/babylon/undelegation/index.d.ts.map +1 -0
  32. package/dist/{src → cjs/src/babylon/undelegation}/index.js +3 -4
  33. package/dist/cjs/src/babylon/undelegation/unbonding.d.ts +16 -0
  34. package/dist/cjs/src/babylon/undelegation/unbonding.d.ts.map +1 -0
  35. package/dist/cjs/src/babylon/undelegation/unbonding.js +111 -0
  36. package/dist/cjs/src/coreDao/descriptor.d.ts.map +1 -0
  37. package/dist/cjs/src/coreDao/descriptor.js +38 -0
  38. package/dist/cjs/src/coreDao/index.d.ts.map +1 -0
  39. package/dist/{src → cjs/src}/coreDao/index.js +1 -1
  40. package/dist/cjs/src/coreDao/opReturn.d.ts.map +1 -0
  41. package/dist/cjs/src/coreDao/opReturn.js +183 -0
  42. package/dist/{src → cjs/src}/coreDao/transaction.d.ts +16 -7
  43. package/dist/cjs/src/coreDao/transaction.d.ts.map +1 -0
  44. package/dist/cjs/src/coreDao/transaction.js +34 -0
  45. package/dist/cjs/src/index.d.ts +3 -0
  46. package/dist/cjs/src/index.d.ts.map +1 -0
  47. package/dist/cjs/src/index.js +39 -0
  48. package/dist/cjs/test/unit/babylon/bug71.d.ts +2 -0
  49. package/dist/cjs/test/unit/babylon/bug71.d.ts.map +1 -0
  50. package/dist/cjs/test/unit/babylon/bug71.js +108 -0
  51. package/dist/cjs/test/unit/babylon/key.utils.d.ts +6 -0
  52. package/dist/cjs/test/unit/babylon/key.utils.d.ts.map +1 -0
  53. package/dist/cjs/test/unit/babylon/key.utils.js +68 -0
  54. package/dist/cjs/test/unit/babylon/transactions.d.ts +2 -0
  55. package/dist/cjs/test/unit/babylon/transactions.d.ts.map +1 -0
  56. package/dist/cjs/test/unit/babylon/transactions.js +338 -0
  57. package/dist/cjs/test/unit/babylon/undelegation.d.ts +2 -0
  58. package/dist/cjs/test/unit/babylon/undelegation.d.ts.map +1 -0
  59. package/dist/cjs/test/unit/babylon/undelegation.js +156 -0
  60. package/dist/cjs/test/unit/babylon/vendor.utils.d.ts +13 -0
  61. package/dist/cjs/test/unit/babylon/vendor.utils.d.ts.map +1 -0
  62. package/dist/cjs/test/unit/babylon/vendor.utils.js +78 -0
  63. package/dist/cjs/test/unit/coreDao/descriptor.d.ts +2 -0
  64. package/dist/cjs/test/unit/coreDao/descriptor.d.ts.map +1 -0
  65. package/dist/cjs/test/unit/coreDao/descriptor.js +144 -0
  66. package/dist/cjs/test/unit/coreDao/opReturn.d.ts +2 -0
  67. package/dist/cjs/test/unit/coreDao/opReturn.d.ts.map +1 -0
  68. package/dist/cjs/test/unit/coreDao/opReturn.js +275 -0
  69. package/dist/cjs/test/unit/coreDao/utils.d.ts +5 -0
  70. package/dist/cjs/test/unit/coreDao/utils.d.ts.map +1 -0
  71. package/dist/cjs/test/unit/coreDao/utils.js +54 -0
  72. package/dist/cjs/test/unit/fixtures.utils.d.ts +9 -0
  73. package/dist/cjs/test/unit/fixtures.utils.d.ts.map +1 -0
  74. package/dist/cjs/test/unit/fixtures.utils.js +91 -0
  75. package/dist/cjs/tsconfig.tsbuildinfo +1 -0
  76. package/dist/esm/babylon/delegationMessage.d.ts +38 -0
  77. package/dist/esm/babylon/delegationMessage.d.ts.map +1 -0
  78. package/dist/esm/babylon/delegationMessage.js +239 -0
  79. package/dist/esm/babylon/descriptor.d.ts +48 -0
  80. package/dist/esm/babylon/descriptor.d.ts.map +1 -0
  81. package/dist/esm/babylon/descriptor.js +91 -0
  82. package/dist/esm/babylon/index.d.ts +8 -0
  83. package/dist/esm/babylon/index.d.ts.map +1 -0
  84. package/dist/esm/babylon/index.js +13 -0
  85. package/dist/esm/babylon/network.d.ts +7 -0
  86. package/dist/esm/babylon/network.d.ts.map +1 -0
  87. package/dist/esm/babylon/network.js +29 -0
  88. package/dist/esm/babylon/params.mainnet.json +152 -0
  89. package/dist/esm/babylon/params.testnet.json +212 -0
  90. package/dist/esm/babylon/parseDescriptor.d.ts +26 -0
  91. package/dist/esm/babylon/parseDescriptor.d.ts.map +1 -0
  92. package/dist/esm/babylon/parseDescriptor.js +155 -0
  93. package/dist/esm/babylon/stakingManager.d.ts +6 -0
  94. package/dist/esm/babylon/stakingManager.d.ts.map +1 -0
  95. package/dist/esm/babylon/stakingManager.js +83 -0
  96. package/dist/esm/babylon/stakingParams.d.ts +40 -0
  97. package/dist/esm/babylon/stakingParams.d.ts.map +1 -0
  98. package/dist/esm/babylon/stakingParams.js +86 -0
  99. package/dist/esm/babylon/undelegation/UndelegationResponse.d.ts +24 -0
  100. package/dist/esm/babylon/undelegation/UndelegationResponse.d.ts.map +1 -0
  101. package/dist/esm/babylon/undelegation/UndelegationResponse.js +18 -0
  102. package/dist/esm/babylon/undelegation/index.d.ts +3 -0
  103. package/dist/esm/babylon/undelegation/index.d.ts.map +1 -0
  104. package/dist/esm/babylon/undelegation/index.js +3 -0
  105. package/dist/esm/babylon/undelegation/unbonding.d.ts +16 -0
  106. package/dist/esm/babylon/undelegation/unbonding.d.ts.map +1 -0
  107. package/dist/esm/babylon/undelegation/unbonding.js +70 -0
  108. package/dist/esm/coreDao/descriptor.d.ts +18 -0
  109. package/dist/{src → esm}/coreDao/descriptor.d.ts.map +1 -1
  110. package/dist/esm/coreDao/descriptor.js +35 -0
  111. package/dist/esm/coreDao/index.d.ts +4 -0
  112. package/dist/esm/coreDao/index.js +4 -0
  113. package/dist/esm/coreDao/opReturn.d.ts +41 -0
  114. package/dist/esm/coreDao/opReturn.js +175 -0
  115. package/dist/esm/coreDao/transaction.d.ts +28 -0
  116. package/dist/esm/coreDao/transaction.d.ts.map +1 -0
  117. package/dist/esm/coreDao/transaction.js +30 -0
  118. package/dist/esm/index.d.ts +3 -0
  119. package/dist/{src → esm}/index.d.ts.map +1 -1
  120. package/dist/esm/index.js +3 -0
  121. package/package.json +42 -12
  122. package/.eslintignore +0 -5
  123. package/.mocharc.yml +0 -8
  124. package/CHANGELOG.md +0 -63
  125. package/dist/src/coreDao/descriptor.js +0 -37
  126. package/dist/src/coreDao/opReturn.js +0 -183
  127. package/dist/src/coreDao/transaction.d.ts.map +0 -1
  128. package/dist/src/coreDao/transaction.js +0 -26
  129. package/dist/src/index.d.ts +0 -3
  130. package/dist/src/transaction.d.ts +0 -32
  131. package/dist/src/transaction.d.ts.map +0 -1
  132. package/dist/src/transaction.js +0 -54
  133. /package/dist/{src → cjs/src}/coreDao/descriptor.d.ts +0 -0
  134. /package/dist/{src → cjs/src}/coreDao/index.d.ts +0 -0
  135. /package/dist/{src → cjs/src}/coreDao/opReturn.d.ts +0 -0
  136. /package/dist/{src → esm}/coreDao/index.d.ts.map +0 -0
  137. /package/dist/{src → esm}/coreDao/opReturn.d.ts.map +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vendor.utils.d.ts","sourceRoot":"","sources":["../../../../../test/unit/babylon/vendor.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,MAAM,MAAM,2CAA2C,CAAC;AACpE,OAAO,KAAK,eAAe,MAAM,kCAAkC,CAAC;AAIpE,OAAO,EACL,wBAAwB,EAGxB,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAI9B,KAAK,MAAM,GAAG;IACZ,qBAAqB,EAAE,gBAAgB,CAAC,eAAe,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC;IAC7F,SAAS,EAAE,YAAY,CAAC,WAAW,CAAC;CACrC,CAAC;AAEF,wBAAsB,yCAAyC,CAC7D,OAAO,EAAE,YAAY,CAAC,OAAO,EAC7B,SAAS,EAAE,eAAe,EAC1B,gBAAgB,EAAE,eAAe,EACjC,iBAAiB,EAAE,wBAAwB,EAC3C,aAAa,EAAE,MAAM,CAAC,sBAAsB,EAAE,EAC9C,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAoBjB;AAED,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,YAAY,CAAC,OAAO,EAC7B,SAAS,EAAE,eAAe,EAC1B,gBAAgB,EAAE,eAAe,EACjC,iBAAiB,EAAE,wBAAwB,EAC3C,aAAa,EAAE,MAAM,CAAC,sBAAsB,EAAE,EAC9C,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAuCjB"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getBitGoUtxoStakingMsgCreateBtcDelegation = getBitGoUtxoStakingMsgCreateBtcDelegation;
37
+ exports.getVendorMsgCreateBtcDelegation = getVendorMsgCreateBtcDelegation;
38
+ const vendor = __importStar(require("@bitgo-beta/babylonlabs-io-btc-staking-ts"));
39
+ const babylonProtobuf = __importStar(require("@babylonlabs-io/babylon-proto-ts"));
40
+ const address_1 = require("bitcoinjs-lib/src/address");
41
+ const babylonlabs_io_btc_staking_ts_1 = require("@bitgo-beta/babylonlabs-io-btc-staking-ts");
42
+ const babylon_1 = require("../../../src/babylon");
43
+ const key_utils_1 = require("./key.utils");
44
+ async function getBitGoUtxoStakingMsgCreateBtcDelegation(network, stakerKey, finalityProvider, descriptorBuilder, stakingParams, changeAddress, amount, utxo, feeRateSatB, blockHeight) {
45
+ return await (0, babylon_1.createUnsignedPreStakeRegistrationBabylonTransactionWithBtcProvider)((0, babylon_1.getBtcProviderForECKey)(descriptorBuilder, stakerKey), network, {
46
+ address: changeAddress,
47
+ publicKeyNoCoordHex: (0, key_utils_1.getXOnlyPubkey)(stakerKey).toString('hex'),
48
+ }, {
49
+ finalityProviderPksNoCoordHex: [(0, key_utils_1.getXOnlyPubkey)(finalityProvider).toString('hex')],
50
+ stakingAmountSat: amount,
51
+ stakingTimelock: (0, babylonlabs_io_btc_staking_ts_1.getBabylonParamByBtcHeight)(blockHeight, stakingParams).minStakingTimeBlocks,
52
+ }, 800000, [utxo], feeRateSatB, (0, address_1.toBech32)(Buffer.from('test'), 0, 'bbn'), 'delegation:create', stakingParams);
53
+ }
54
+ async function getVendorMsgCreateBtcDelegation(network, stakerKey, finalityProvider, descriptorBuilder, stakingParams, changeAddress, amount, utxo, feeRateSatB, blockHeight) {
55
+ const babylonProvider = {
56
+ async signTransaction(msg) {
57
+ // return unsigned payload
58
+ return babylonProtobuf.btcstakingtx.MsgCreateBTCDelegation.encode(msg.value).finish();
59
+ },
60
+ };
61
+ const manager = new vendor.BabylonBtcStakingManager(network, stakingParams, (0, babylon_1.getBtcProviderForECKey)(descriptorBuilder, stakerKey), babylonProvider);
62
+ const result = await manager.preStakeRegistrationBabylonTransaction({
63
+ address: changeAddress,
64
+ publicKeyNoCoordHex: (0, key_utils_1.getXOnlyPubkey)(stakerKey).toString('hex'),
65
+ }, {
66
+ finalityProviderPksNoCoordHex: [(0, key_utils_1.getXOnlyPubkey)(finalityProvider).toString('hex')],
67
+ stakingAmountSat: amount,
68
+ stakingTimelock: (0, babylonlabs_io_btc_staking_ts_1.getBabylonParamByBtcHeight)(blockHeight, stakingParams).minStakingTimeBlocks,
69
+ }, blockHeight, [utxo], feeRateSatB, (0, address_1.toBech32)(Buffer.from('test'), 0, 'bbn'));
70
+ return {
71
+ unsignedDelegationMsg: {
72
+ typeUrl: '/babylon.btcstaking.v1.MsgCreateBTCDelegation',
73
+ value: babylonProtobuf.btcstakingtx.MsgCreateBTCDelegation.decode(result.signedBabylonTx),
74
+ },
75
+ stakingTx: result.stakingTx,
76
+ };
77
+ }
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVuZG9yLnV0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGVzdC91bml0L2JhYnlsb24vdmVuZG9yLnV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUJBLDhGQStCQztBQUVELDBFQWtEQztBQXRHRCxrRkFBb0U7QUFDcEUsa0ZBQW9FO0FBQ3BFLHVEQUFxRDtBQUNyRCw2RkFBdUY7QUFFdkYsa0RBSzhCO0FBRTlCLDJDQUE2QztBQU90QyxLQUFLLFVBQVUseUNBQXlDLENBQzdELE9BQTZCLEVBQzdCLFNBQTBCLEVBQzFCLGdCQUFpQyxFQUNqQyxpQkFBMkMsRUFDM0MsYUFBOEMsRUFDOUMsYUFBcUIsRUFDckIsTUFBYyxFQUNkLElBQWlCLEVBQ2pCLFdBQW1CLEVBQ25CLFdBQW1CO0lBRW5CLE9BQU8sTUFBTSxJQUFBLDZFQUFtRSxFQUM5RSxJQUFBLGdDQUFzQixFQUFDLGlCQUFpQixFQUFFLFNBQVMsQ0FBQyxFQUNwRCxPQUFPLEVBQ1A7UUFDRSxPQUFPLEVBQUUsYUFBYTtRQUN0QixtQkFBbUIsRUFBRSxJQUFBLDBCQUFjLEVBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztLQUMvRCxFQUNEO1FBQ0UsNkJBQTZCLEVBQUUsQ0FBQyxJQUFBLDBCQUFjLEVBQUMsZ0JBQWdCLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakYsZ0JBQWdCLEVBQUUsTUFBTTtRQUN4QixlQUFlLEVBQUUsSUFBQSwwREFBMEIsRUFBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUMsb0JBQW9CO0tBQzdGLEVBQ0QsTUFBTyxFQUNQLENBQUMsSUFBSSxDQUFDLEVBQ04sV0FBVyxFQUNYLElBQUEsa0JBQVEsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLENBQUMsRUFDdkMsbUJBQW1CLEVBQ25CLGFBQWEsQ0FDZCxDQUFDO0FBQ0osQ0FBQztBQUVNLEtBQUssVUFBVSwrQkFBK0IsQ0FDbkQsT0FBNkIsRUFDN0IsU0FBMEIsRUFDMUIsZ0JBQWlDLEVBQ2pDLGlCQUEyQyxFQUMzQyxhQUE4QyxFQUM5QyxhQUFxQixFQUNyQixNQUFjLEVBQ2QsSUFBaUIsRUFDakIsV0FBbUIsRUFDbkIsV0FBbUI7SUFFbkIsTUFBTSxlQUFlLEdBQTJCO1FBQzlDLEtBQUssQ0FBQyxlQUFlLENBQUMsR0FBRztZQUN2QiwwQkFBMEI7WUFDMUIsT0FBTyxlQUFlLENBQUMsWUFBWSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FDL0QsR0FBRyxDQUFDLEtBQTRELENBQ2pFLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDYixDQUFDO0tBQ0YsQ0FBQztJQUNGLE1BQU0sT0FBTyxHQUFHLElBQUksTUFBTSxDQUFDLHdCQUF3QixDQUNqRCxPQUFPLEVBQ1AsYUFBYSxFQUNiLElBQUEsZ0NBQXNCLEVBQUMsaUJBQWlCLEVBQUUsU0FBUyxDQUFDLEVBQ3BELGVBQWUsQ0FDaEIsQ0FBQztJQUVGLE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLHNDQUFzQyxDQUNqRTtRQUNFLE9BQU8sRUFBRSxhQUFhO1FBQ3RCLG1CQUFtQixFQUFFLElBQUEsMEJBQWMsRUFBQyxTQUFTLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDO0tBQy9ELEVBQ0Q7UUFDRSw2QkFBNkIsRUFBRSxDQUFDLElBQUEsMEJBQWMsRUFBQyxnQkFBZ0IsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqRixnQkFBZ0IsRUFBRSxNQUFNO1FBQ3hCLGVBQWUsRUFBRSxJQUFBLDBEQUEwQixFQUFDLFdBQVcsRUFBRSxhQUFhLENBQUMsQ0FBQyxvQkFBb0I7S0FDN0YsRUFDRCxXQUFXLEVBQ1gsQ0FBQyxJQUFJLENBQUMsRUFDTixXQUFXLEVBQ1gsSUFBQSxrQkFBUSxFQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUN4QyxDQUFDO0lBRUYsT0FBTztRQUNMLHFCQUFxQixFQUFFO1lBQ3JCLE9BQU8sRUFBRSwrQ0FBK0M7WUFDeEQsS0FBSyxFQUFFLGVBQWUsQ0FBQyxZQUFZLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUM7U0FDMUY7UUFDRCxTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7S0FDNUIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBiaXRjb2luanNsaWIgZnJvbSAnYml0Y29pbmpzLWxpYic7XG5pbXBvcnQgeyBFQ1BhaXJJbnRlcmZhY2UgfSBmcm9tICdAYml0Z28tYmV0YS91dHhvLWxpYic7XG5pbXBvcnQgKiBhcyB2ZW5kb3IgZnJvbSAnQGJpdGdvLWJldGEvYmFieWxvbmxhYnMtaW8tYnRjLXN0YWtpbmctdHMnO1xuaW1wb3J0ICogYXMgYmFieWxvblByb3RvYnVmIGZyb20gJ0BiYWJ5bG9ubGFicy1pby9iYWJ5bG9uLXByb3RvLXRzJztcbmltcG9ydCB7IHRvQmVjaDMyIH0gZnJvbSAnYml0Y29pbmpzLWxpYi9zcmMvYWRkcmVzcyc7XG5pbXBvcnQgeyBnZXRCYWJ5bG9uUGFyYW1CeUJ0Y0hlaWdodCB9IGZyb20gJ0BiaXRnby1iZXRhL2JhYnlsb25sYWJzLWlvLWJ0Yy1zdGFraW5nLXRzJztcblxuaW1wb3J0IHtcbiAgQmFieWxvbkRlc2NyaXB0b3JCdWlsZGVyLFxuICBjcmVhdGVVbnNpZ25lZFByZVN0YWtlUmVnaXN0cmF0aW9uQmFieWxvblRyYW5zYWN0aW9uV2l0aEJ0Y1Byb3ZpZGVyLFxuICBnZXRCdGNQcm92aWRlckZvckVDS2V5LFxuICBWYWx1ZVdpdGhUeXBlVXJsLFxufSBmcm9tICcuLi8uLi8uLi9zcmMvYmFieWxvbic7XG5cbmltcG9ydCB7IGdldFhPbmx5UHVia2V5IH0gZnJvbSAnLi9rZXkudXRpbHMnO1xuXG50eXBlIFJlc3VsdCA9IHtcbiAgdW5zaWduZWREZWxlZ2F0aW9uTXNnOiBWYWx1ZVdpdGhUeXBlVXJsPGJhYnlsb25Qcm90b2J1Zi5idGNzdGFraW5ndHguTXNnQ3JlYXRlQlRDRGVsZWdhdGlvbj47XG4gIHN0YWtpbmdUeDogYml0Y29pbmpzbGliLlRyYW5zYWN0aW9uO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEJpdEdvVXR4b1N0YWtpbmdNc2dDcmVhdGVCdGNEZWxlZ2F0aW9uKFxuICBuZXR3b3JrOiBiaXRjb2luanNsaWIuTmV0d29yayxcbiAgc3Rha2VyS2V5OiBFQ1BhaXJJbnRlcmZhY2UsXG4gIGZpbmFsaXR5UHJvdmlkZXI6IEVDUGFpckludGVyZmFjZSxcbiAgZGVzY3JpcHRvckJ1aWxkZXI6IEJhYnlsb25EZXNjcmlwdG9yQnVpbGRlcixcbiAgc3Rha2luZ1BhcmFtczogdmVuZG9yLlZlcnNpb25lZFN0YWtpbmdQYXJhbXNbXSxcbiAgY2hhbmdlQWRkcmVzczogc3RyaW5nLFxuICBhbW91bnQ6IG51bWJlcixcbiAgdXR4bzogdmVuZG9yLlVUWE8sXG4gIGZlZVJhdGVTYXRCOiBudW1iZXIsXG4gIGJsb2NrSGVpZ2h0OiBudW1iZXJcbik6IFByb21pc2U8UmVzdWx0PiB7XG4gIHJldHVybiBhd2FpdCBjcmVhdGVVbnNpZ25lZFByZVN0YWtlUmVnaXN0cmF0aW9uQmFieWxvblRyYW5zYWN0aW9uV2l0aEJ0Y1Byb3ZpZGVyKFxuICAgIGdldEJ0Y1Byb3ZpZGVyRm9yRUNLZXkoZGVzY3JpcHRvckJ1aWxkZXIsIHN0YWtlcktleSksXG4gICAgbmV0d29yayxcbiAgICB7XG4gICAgICBhZGRyZXNzOiBjaGFuZ2VBZGRyZXNzLFxuICAgICAgcHVibGljS2V5Tm9Db29yZEhleDogZ2V0WE9ubHlQdWJrZXkoc3Rha2VyS2V5KS50b1N0cmluZygnaGV4JyksXG4gICAgfSxcbiAgICB7XG4gICAgICBmaW5hbGl0eVByb3ZpZGVyUGtzTm9Db29yZEhleDogW2dldFhPbmx5UHVia2V5KGZpbmFsaXR5UHJvdmlkZXIpLnRvU3RyaW5nKCdoZXgnKV0sXG4gICAgICBzdGFraW5nQW1vdW50U2F0OiBhbW91bnQsXG4gICAgICBzdGFraW5nVGltZWxvY2s6IGdldEJhYnlsb25QYXJhbUJ5QnRjSGVpZ2h0KGJsb2NrSGVpZ2h0LCBzdGFraW5nUGFyYW1zKS5taW5TdGFraW5nVGltZUJsb2NrcyxcbiAgICB9LFxuICAgIDgwMF8wMDAsXG4gICAgW3V0eG9dLFxuICAgIGZlZVJhdGVTYXRCLFxuICAgIHRvQmVjaDMyKEJ1ZmZlci5mcm9tKCd0ZXN0JyksIDAsICdiYm4nKSxcbiAgICAnZGVsZWdhdGlvbjpjcmVhdGUnLFxuICAgIHN0YWtpbmdQYXJhbXNcbiAgKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFZlbmRvck1zZ0NyZWF0ZUJ0Y0RlbGVnYXRpb24oXG4gIG5ldHdvcms6IGJpdGNvaW5qc2xpYi5OZXR3b3JrLFxuICBzdGFrZXJLZXk6IEVDUGFpckludGVyZmFjZSxcbiAgZmluYWxpdHlQcm92aWRlcjogRUNQYWlySW50ZXJmYWNlLFxuICBkZXNjcmlwdG9yQnVpbGRlcjogQmFieWxvbkRlc2NyaXB0b3JCdWlsZGVyLFxuICBzdGFraW5nUGFyYW1zOiB2ZW5kb3IuVmVyc2lvbmVkU3Rha2luZ1BhcmFtc1tdLFxuICBjaGFuZ2VBZGRyZXNzOiBzdHJpbmcsXG4gIGFtb3VudDogbnVtYmVyLFxuICB1dHhvOiB2ZW5kb3IuVVRYTyxcbiAgZmVlUmF0ZVNhdEI6IG51bWJlcixcbiAgYmxvY2tIZWlnaHQ6IG51bWJlclxuKTogUHJvbWlzZTxSZXN1bHQ+IHtcbiAgY29uc3QgYmFieWxvblByb3ZpZGVyOiB2ZW5kb3IuQmFieWxvblByb3ZpZGVyID0ge1xuICAgIGFzeW5jIHNpZ25UcmFuc2FjdGlvbihtc2cpIHtcbiAgICAgIC8vIHJldHVybiB1bnNpZ25lZCBwYXlsb2FkXG4gICAgICByZXR1cm4gYmFieWxvblByb3RvYnVmLmJ0Y3N0YWtpbmd0eC5Nc2dDcmVhdGVCVENEZWxlZ2F0aW9uLmVuY29kZShcbiAgICAgICAgbXNnLnZhbHVlIGFzIGJhYnlsb25Qcm90b2J1Zi5idGNzdGFraW5ndHguTXNnQ3JlYXRlQlRDRGVsZWdhdGlvblxuICAgICAgKS5maW5pc2goKTtcbiAgICB9LFxuICB9O1xuICBjb25zdCBtYW5hZ2VyID0gbmV3IHZlbmRvci5CYWJ5bG9uQnRjU3Rha2luZ01hbmFnZXIoXG4gICAgbmV0d29yayxcbiAgICBzdGFraW5nUGFyYW1zLFxuICAgIGdldEJ0Y1Byb3ZpZGVyRm9yRUNLZXkoZGVzY3JpcHRvckJ1aWxkZXIsIHN0YWtlcktleSksXG4gICAgYmFieWxvblByb3ZpZGVyXG4gICk7XG5cbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbWFuYWdlci5wcmVTdGFrZVJlZ2lzdHJhdGlvbkJhYnlsb25UcmFuc2FjdGlvbihcbiAgICB7XG4gICAgICBhZGRyZXNzOiBjaGFuZ2VBZGRyZXNzLFxuICAgICAgcHVibGljS2V5Tm9Db29yZEhleDogZ2V0WE9ubHlQdWJrZXkoc3Rha2VyS2V5KS50b1N0cmluZygnaGV4JyksXG4gICAgfSxcbiAgICB7XG4gICAgICBmaW5hbGl0eVByb3ZpZGVyUGtzTm9Db29yZEhleDogW2dldFhPbmx5UHVia2V5KGZpbmFsaXR5UHJvdmlkZXIpLnRvU3RyaW5nKCdoZXgnKV0sXG4gICAgICBzdGFraW5nQW1vdW50U2F0OiBhbW91bnQsXG4gICAgICBzdGFraW5nVGltZWxvY2s6IGdldEJhYnlsb25QYXJhbUJ5QnRjSGVpZ2h0KGJsb2NrSGVpZ2h0LCBzdGFraW5nUGFyYW1zKS5taW5TdGFraW5nVGltZUJsb2NrcyxcbiAgICB9LFxuICAgIGJsb2NrSGVpZ2h0LFxuICAgIFt1dHhvXSxcbiAgICBmZWVSYXRlU2F0QixcbiAgICB0b0JlY2gzMihCdWZmZXIuZnJvbSgndGVzdCcpLCAwLCAnYmJuJylcbiAgKTtcblxuICByZXR1cm4ge1xuICAgIHVuc2lnbmVkRGVsZWdhdGlvbk1zZzoge1xuICAgICAgdHlwZVVybDogJy9iYWJ5bG9uLmJ0Y3N0YWtpbmcudjEuTXNnQ3JlYXRlQlRDRGVsZWdhdGlvbicsXG4gICAgICB2YWx1ZTogYmFieWxvblByb3RvYnVmLmJ0Y3N0YWtpbmd0eC5Nc2dDcmVhdGVCVENEZWxlZ2F0aW9uLmRlY29kZShyZXN1bHQuc2lnbmVkQmFieWxvblR4KSxcbiAgICB9LFxuICAgIHN0YWtpbmdUeDogcmVzdWx0LnN0YWtpbmdUeCxcbiAgfTtcbn1cbiJdfQ==
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=descriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"descriptor.d.ts","sourceRoot":"","sources":["../../../../../test/unit/coreDao/descriptor.ts"],"names":[],"mappings":""}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const assert = __importStar(require("assert"));
37
+ const utxolib = __importStar(require("@bitgo-beta/utxo-lib"));
38
+ const wasm_utxo_1 = require("@bitgo/wasm-utxo");
39
+ const testutil_1 = require("@bitgo-beta/utxo-core/testutil");
40
+ const coreDao_1 = require("../../../src/coreDao");
41
+ const utils_1 = require("./utils");
42
+ describe('descriptor', function () {
43
+ const baseFixturePath = 'test/fixtures/coreDao/descriptor/';
44
+ const rootWalletKeys = utxolib.testutil.getDefaultWalletKeys();
45
+ const key1 = rootWalletKeys.triple[0];
46
+ const key2 = rootWalletKeys.triple[1];
47
+ const key3 = rootWalletKeys.triple[2];
48
+ const validLocktime = 2048;
49
+ it('should fail if m is longer than the number of keys or not at least 1', function () {
50
+ assert.throws(() => {
51
+ (0, coreDao_1.createMultiSigDescriptor)('sh', validLocktime, 3, [key1, key2], false);
52
+ });
53
+ assert.throws(() => {
54
+ (0, coreDao_1.createMultiSigDescriptor)('sh', validLocktime, 0, [key1, key2], false);
55
+ });
56
+ });
57
+ it('should fail if locktime is invalid', function () {
58
+ assert.throws(() => {
59
+ (0, coreDao_1.createMultiSigDescriptor)('sh', 0, 2, [key1, key2], false);
60
+ });
61
+ });
62
+ async function runTestForParams(scriptType, m, keys) {
63
+ const fixturePath = baseFixturePath + `${scriptType}-${m}of${keys.length}`;
64
+ describe(`should create a ${m} of ${keys.length} multi-sig ${scriptType} descriptor`, function () {
65
+ it('has expected descriptor string', async function () {
66
+ const descriptorString = (0, coreDao_1.createMultiSigDescriptor)(scriptType, validLocktime, m, keys, false);
67
+ assert.strictEqual(descriptorString, await (0, testutil_1.getFixture)(fixturePath + `-string.txt`, descriptorString), descriptorString);
68
+ });
69
+ it('has expected AST', async function () {
70
+ const descriptor = wasm_utxo_1.Descriptor.fromString((0, coreDao_1.createMultiSigDescriptor)(scriptType, validLocktime, m, keys, false), 'derivable');
71
+ assert.deepStrictEqual(descriptor.node(), await (0, testutil_1.getFixture)(fixturePath + '-ast.json', descriptor.node()));
72
+ });
73
+ it('has expected asm', async function () {
74
+ const descriptor = wasm_utxo_1.Descriptor.fromString((0, coreDao_1.createMultiSigDescriptor)(scriptType, validLocktime, m, keys, false), 'derivable');
75
+ const asmString = descriptor.atDerivationIndex(0).toAsmString();
76
+ assert.strictEqual(asmString, await (0, testutil_1.getFixture)(fixturePath + '-asm.txt', asmString), asmString);
77
+ });
78
+ it('can be signed', async function () {
79
+ // Derive the script from the descriptor
80
+ const descriptor = wasm_utxo_1.Descriptor.fromString((0, coreDao_1.createMultiSigDescriptor)(scriptType, validLocktime, m, keys, false), 'derivable');
81
+ const descriptorAt0 = descriptor.atDerivationIndex(0);
82
+ const script = Buffer.from(descriptorAt0.scriptPubkey());
83
+ // Make the prevTx
84
+ const prevPsbt = utxolib.testutil.constructPsbt([{ scriptType: 'p2wsh', value: BigInt(1.1e8) }], [{ script: script.toString('hex'), value: BigInt(1e8) }], utxolib.networks.bitcoin, rootWalletKeys, 'fullsigned');
85
+ const prevTx = prevPsbt.finalizeAllInputs().extractTransaction();
86
+ // Create the PSBT and sign
87
+ const psbt = Object.assign(new utxolib.Psbt({ network: utxolib.networks.bitcoin }), {
88
+ locktime: validLocktime,
89
+ });
90
+ psbt.addInput({
91
+ hash: prevTx.getId(),
92
+ index: 0,
93
+ sequence: 0xfffffffe,
94
+ });
95
+ if (scriptType === 'sh-wsh') {
96
+ psbt.updateInput(0, { witnessUtxo: { script, value: BigInt(1e8) } });
97
+ }
98
+ else {
99
+ psbt.updateInput(0, { nonWitnessUtxo: prevTx.toBuffer() });
100
+ }
101
+ psbt.addOutput({ script, value: BigInt(0.9e8) });
102
+ (0, utils_1.updateInputWithDescriptor)(psbt, 0, descriptorAt0);
103
+ keys.forEach((signer, i) => {
104
+ if (i >= m) {
105
+ return;
106
+ }
107
+ psbt.signAllInputsHD(signer);
108
+ });
109
+ // Get the fully signed transaction and check
110
+ const signedTx = (0, utils_1.finalizePsbt)(psbt).extractTransaction().toBuffer();
111
+ assert.strictEqual(signedTx.toString('hex'), await (0, testutil_1.getFixture)(fixturePath + '-tx.txt', signedTx.toString('hex')));
112
+ });
113
+ });
114
+ }
115
+ runTestForParams('sh', 2, [key1, key2]);
116
+ runTestForParams('sh-wsh', 2, [key1, key2]);
117
+ runTestForParams('sh', 3, [key1, key2, key3]);
118
+ runTestForParams('wsh', 3, [key1, key2, key3]);
119
+ it('should recreate the script used in testnet staking transaction', function () {
120
+ // Source: https://mempool.space/testnet/address/2MxTi2EhHKgdJFKRTBttVGGxir9ZzjmKCXw
121
+ // 2 of 2 multisig
122
+ const timelock = 'fce4cb66';
123
+ const pubkey1 = '03ecb6d4b7f5d56962e547fc52dd588359f5729c0ba856d6978b84723895a16691';
124
+ const pubkey2 = '024aaea25d82b1db2be030a05b641d6302e48ed652b1ca9cb08a67267fcbb56747';
125
+ const redeemScriptASM = [
126
+ 'OP_PUSHBYTES_4',
127
+ timelock,
128
+ 'OP_CLTV',
129
+ 'OP_DROP',
130
+ 'OP_PUSHNUM_2',
131
+ 'OP_PUSHBYTES_33',
132
+ pubkey1,
133
+ 'OP_PUSHBYTES_33',
134
+ pubkey2,
135
+ 'OP_PUSHNUM_2',
136
+ 'OP_CHECKMULTISIG',
137
+ ].join(' ');
138
+ const decodedTimelock = (0, coreDao_1.decodeTimelock)(Buffer.from(timelock, 'hex'));
139
+ const descriptor = (0, coreDao_1.createMultiSigDescriptor)('sh', decodedTimelock, 2, [Buffer.from(pubkey1, 'hex'), Buffer.from(pubkey2, 'hex')], false);
140
+ const descriptorASM = wasm_utxo_1.Descriptor.fromString(descriptor, 'definite').toAsmString();
141
+ assert.deepStrictEqual(redeemScriptASM, descriptorASM);
142
+ });
143
+ });
144
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzY3JpcHRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9jb3JlRGFvL2Rlc2NyaXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBaUM7QUFFakMsOERBQWdEO0FBQ2hELGdEQUE4QztBQUM5Qyw2REFBNEQ7QUFFNUQsa0RBQWdGO0FBRWhGLG1DQUFrRTtBQUVsRSxRQUFRLENBQUMsWUFBWSxFQUFFO0lBQ3JCLE1BQU0sZUFBZSxHQUFHLG1DQUFtQyxDQUFDO0lBQzVELE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztJQUMvRCxNQUFNLElBQUksR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RDLE1BQU0sSUFBSSxHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsTUFBTSxJQUFJLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0QyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFFM0IsRUFBRSxDQUFDLHNFQUFzRSxFQUFFO1FBQ3pFLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFO1lBQ2pCLElBQUEsa0NBQXdCLEVBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxDQUFDLENBQUM7UUFFSCxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRTtZQUNqQixJQUFBLGtDQUF3QixFQUFDLElBQUksRUFBRSxhQUFhLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hFLENBQUMsQ0FBQyxDQUFD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O1FBQ2xCLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQztRQUM1QixNQUFNLE9BQU8sR0FBRyxvRUFBb0UsQ0FBQztRQUNyRixNQUFNLE9BQU8sR0FBRyxvRUFBb0UsQ0FBQztRQUNyRixNQUFNLGVBQWUsR0FBRztZQUN0QixnQkFBZ0I7WUFDaEIsUUFBUTtZQUNSLFNBQVM7WUFDVCxTQUFTO1lBQ1QsY0FBYztZQUNkLGlCQUFpQjtZQUNqQixPQUFPO1lBQ1AsaUJBQWlCO1lBQ2pCLE9BQU87WUFDUCxjQUFjO1lBQ2Qsa0JBQWtCO1NBQ25CLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRVosTUFBTSxlQUFlLEdBQUcsSUFBQSx3QkFBYyxFQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDckUsTUFBTSxVQUFVLEdBQUcsSUFBQSxrQ0FBd0IsRUFDekMsSUFBSSxFQUNKLGVBQWUsRUFDZixDQUFDLEVBQ0QsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQyxFQUMxRCxLQUFLLENBQ04sQ0FBQztRQUNGLE1BQU0sYUFBYSxHQUFHLHNCQUFVLENBQUMsVUFBVSxDQUFDLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNsRixNQUFNLENBQUMsZUFBZSxDQUFDLGVBQWUsRUFBRSxhQUFhLENBQUMsQ0FBQztJQUN6RCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5cbmltcG9ydCAqIGFzIHV0eG9saWIgZnJvbSAnQGJpdGdvLWJldGEvdXR4by1saWInO1xuaW1wb3J0IHsgRGVzY3JpcHRvciB9IGZyb20gJ0BiaXRnby93YXNtLXV0eG8nO1xuaW1wb3J0IHsgZ2V0Rml4dHVyZSB9IGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tY29yZS90ZXN0dXRpbCc7XG5cbmltcG9ydCB7IGNyZWF0ZU11bHRpU2lnRGVzY3JpcHRvciwgZGVjb2RlVGltZWxvY2sgfSBmcm9tICcuLi8uLi8uLi9zcmMvY29yZURhbyc7XG5cbmltcG9ydCB7IGZpbmFsaXplUHNidCwgdXBkYXRlSW5wdXRXaXRoRGVzY3JpcHRvciB9IGZyb20gJy4vdXRpbHMnO1xuXG5kZXNjcmliZSgnZGVzY3JpcHRvcicsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgYmFzZUZpeHR1cmVQYXRoID0gJ3Rlc3QvZml4dHVyZXMvY29yZURhby9kZXNjcmlwdG9yLyc7XG4gIGNvbnN0IHJvb3RXYWxsZXRLZXlzID0gdXR4b2xpYi50ZXN0dXRpbC5nZXREZWZhdWx0V2FsbGV0S2V5cygpO1xuICBjb25zdCBrZXkxID0gcm9vdFdhbGxldEtleXMudHJpcGxlWzBdO1xuICBjb25zdCBrZXkyID0gcm9vdFdhbGxldEtleXMudHJpcGxlWzFdO1xuICBjb25zdCBrZXkzID0gcm9vdFdhbGxldEtleXMudHJpcGxlWzJdO1xuICBjb25zdCB2YWxpZExvY2t0aW1lID0gMjA0ODtcblxuICBpdCgnc2hvdWxkIGZhaWwgaWYgbSBpcyBsb25nZXIgdGhhbiB0aGUgbnVtYmVyIG9mIGtleXMgb3Igbm90IGF0IGxlYXN0IDEnLCBmdW5jdGlvbiAoKSB7XG4gICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICBjcmVhdGVNdWx0aVNpZ0Rlc2NyaXB0b3IoJ3NoJywgdmFsaWRMb2NrdGltZSwgMywgW2tleTEsIGtleTJdLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBhc3NlcnQudGhyb3dzKCgpID0+IHtcbiAgICAgIGNyZWF0ZU11bHRpU2lnRGVzY3JpcHRvcignc2gnLCB2YWxpZExvY2t0aW1lLCAwLCBba2V5MSwga2V5Ml0sIGZhbHNlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBmYWlsIGlmIGxvY2t0aW1lIGlzIGludmFsaWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgYXNzZXJ0LnRocm93cygoKSA9PiB7XG4gICAgICBjcmVhdGVNdWx0aVNpZ0Rlc2NyaXB0b3IoJ3NoJywgMCwgMiwgW2tleTEsIGtleTJdLCBmYWxzZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIHJ1blRlc3RGb3JQYXJhbXMoc2NyaXB0VHlwZTogJ3NoJyB8ICdzaC13c2gnIHwgJ3dzaCcsIG06IG51bWJlciwga2V5czogdXR4b2xpYi5CSVAzMkludGVyZmFjZVtdKSB7XG4gICAgY29uc3QgZml4dHVyZVBhdGggPSBiYXNlRml4dHVyZVBhdGggKyBgJHtzY3JpcHRUeXBlfS0ke219b2Yke2tleXMubGVuZ3RofWA7XG4gICAgZGVzY3JpYmUoYHNob3VsZCBjcmVhdGUgYSAke219IG9mICR7a2V5cy5sZW5ndGh9IG11bHRpLXNpZyAke3NjcmlwdFR5cGV9IGRlc2NyaXB0b3JgLCBmdW5jdGlvbiAoKSB7XG4gICAgICBpdCgnaGFzIGV4cGVjdGVkIGRlc2NyaXB0b3Igc3RyaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBkZXNjcmlwdG9yU3RyaW5nID0gY3JlYXRlTXVsdGlTaWdEZXNjcmlwdG9yKHNjcmlwdFR5cGUsIHZhbGlkTG9ja3RpbWUsIG0sIGtleXMsIGZhbHNlKTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICAgIGRlc2NyaXB0b3JTdHJpbmcsXG4gICAgICAgICAgYXdhaXQgZ2V0Rml4dHVyZShmaXh0dXJlUGF0aCArIGAtc3RyaW5nLnR4dGAsIGRlc2NyaXB0b3JTdHJpbmcpLFxuICAgICAgICAgIGRlc2NyaXB0b3JTdHJpbmdcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnaGFzIGV4cGVjdGVkIEFTVCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IERlc2NyaXB0b3IuZnJvbVN0cmluZyhcbiAgICAgICAgICBjcmVhdGVNdWx0aVNpZ0Rlc2NyaXB0b3Ioc2NyaXB0VHlwZSwgdmFsaWRMb2NrdGltZSwgbSwga2V5cywgZmFsc2UpLFxuICAgICAgICAgICdkZXJpdmFibGUnXG4gICAgICAgICk7XG5cbiAgICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChkZXNjcmlwdG9yLm5vZGUoKSwgYXdhaXQgZ2V0Rml4dHVyZShmaXh0dXJlUGF0aCArICctYXN0Lmpzb24nLCBkZXNjcmlwdG9yLm5vZGUoKSkpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdoYXMgZXhwZWN0ZWQgYXNtJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKFxuICAgICAgICAgIGNyZWF0ZU11bHRpU2lnRGVzY3JpcHRvcihzY3JpcHRUeXBlLCB2YWxpZExvY2t0aW1lLCBtLCBrZXlzLCBmYWxzZSksXG4gICAgICAgICAgJ2Rlcml2YWJsZSdcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgYXNtU3RyaW5nID0gZGVzY3JpcHRvci5hdERlcml2YXRpb25JbmRleCgwKS50b0FzbVN0cmluZygpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXNtU3RyaW5nLCBhd2FpdCBnZXRGaXh0dXJlKGZpeHR1cmVQYXRoICsgJy1hc20udHh0JywgYXNtU3RyaW5nKSwgYXNtU3RyaW5nKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnY2FuIGJlIHNpZ25lZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gRGVyaXZlIHRoZSBzY3JpcHQgZnJvbSB0aGUgZGVzY3JpcHRvclxuICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKFxuICAgICAgICAgIGNyZWF0ZU11bHRpU2lnRGVzY3JpcHRvcihzY3JpcHRUeXBlLCB2YWxpZExvY2t0aW1lLCBtLCBrZXlzLCBmYWxzZSksXG4gICAgICAgICAgJ2Rlcml2YWJsZSdcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvckF0MCA9IGRlc2NyaXB0b3IuYXREZXJpdmF0aW9uSW5kZXgoMCk7XG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IEJ1ZmZlci5mcm9tKGRlc2NyaXB0b3JBdDAuc2NyaXB0UHVia2V5KCkpO1xuXG4gICAgICAgIC8vIE1ha2UgdGhlIHByZXZUeFxuICAgICAgICBjb25zdCBwcmV2UHNidCA9IHV0eG9saWIudGVzdHV0aWwuY29uc3RydWN0UHNidChcbiAgICAgICAgICBbeyBzY3JpcHRUeXBlOiAncDJ3c2gnLCB2YWx1ZTogQmlnSW50KDEuMWU4KSB9XSxcbiAgICAgICAgICBbeyBzY3JpcHQ6IHNjcmlwdC50b1N0cmluZygnaGV4JyksIHZhbHVlOiBCaWdJbnQoMWU4KSB9XSxcbiAgICAgICAgICB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4sXG4gICAgICAgICAgcm9vdFdhbGxldEtleXMsXG4gICAgICAgICAgJ2Z1bGxzaWduZWQnXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHByZXZUeCA9IHByZXZQc2J0LmZpbmFsaXplQWxsSW5wdXRzKCkuZXh0cmFjdFRyYW5zYWN0aW9uKCk7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBQU0JUIGFuZCBzaWduXG4gICAgICAgIGNvbnN0IHBzYnQgPSBPYmplY3QuYXNzaWduKG5ldyB1dHhvbGliLlBzYnQoeyBuZXR3b3JrOiB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4gfSksIHtcbiAgICAgICAgICBsb2NrdGltZTogdmFsaWRMb2NrdGltZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHBzYnQuYWRkSW5wdXQoe1xuICAgICAgICAgIGhhc2g6IHByZXZUeC5nZXRJZCgpLFxuICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgIHNlcXVlbmNlOiAweGZmZmZmZmZlLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHNjcmlwdFR5cGUgPT09ICdzaC13c2gnKSB7XG4gICAgICAgICAgcHNidC51cGRhdGVJbnB1dCgwLCB7IHdpdG5lc3NVdHhvOiB7IHNjcmlwdCwgdmFsdWU6IEJpZ0ludCgxZTgpIH0gfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcHNidC51cGRhdGVJbnB1dCgwLCB7IG5vbldpdG5lc3NVdHhvOiBwcmV2VHgudG9CdWZmZXIoKSB9KTtcbiAgICAgICAgfVxuICAgICAgICBwc2J0LmFkZE91dHB1dCh7IHNjcmlwdCwgdmFsdWU6IEJpZ0ludCgwLjllOCkgfSk7XG4gICAgICAgIHVwZGF0ZUlucHV0V2l0aERlc2NyaXB0b3IocHNidCwgMCwgZGVzY3JpcHRvckF0MCk7XG4gICAgICAgIGtleXMuZm9yRWFjaCgoc2lnbmVyLCBpKSA9PiB7XG4gICAgICAgICAgaWYgKGkgPj0gbSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwc2J0LnNpZ25BbGxJbnB1dHNIRChzaWduZXIpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBHZXQgdGhlIGZ1bGx5IHNpZ25lZCB0cmFuc2FjdGlvbiBhbmQgY2hlY2tcbiAgICAgICAgY29uc3Qgc2lnbmVkVHggPSBmaW5hbGl6ZVBzYnQocHNidCkuZXh0cmFjdFRyYW5zYWN0aW9uKCkudG9CdWZmZXIoKTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICAgIHNpZ25lZFR4LnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgICBhd2FpdCBnZXRGaXh0dXJlKGZpeHR1cmVQYXRoICsgJy10eC50eHQnLCBzaWduZWRUeC50b1N0cmluZygnaGV4JykpXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHJ1blRlc3RGb3JQYXJhbXMoJ3NoJywgMiwgW2tleTEsIGtleTJdKTtcbiAgcnVuVGVzdEZvclBhcmFtcygnc2gtd3NoJywgMiwgW2tleTEsIGtleTJdKTtcbiAgcnVuVGVzdEZvclBhcmFtcygnc2gnLCAzLCBba2V5MSwga2V5Miwga2V5M10pO1xuICBydW5UZXN0Rm9yUGFyYW1zKCd3c2gnLCAzLCBba2V5MSwga2V5Miwga2V5M10pO1xuXG4gIGl0KCdzaG91bGQgcmVjcmVhdGUgdGhlIHNjcmlwdCB1c2VkIGluIHRlc3RuZXQgc3Rha2luZyB0cmFuc2FjdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBTb3VyY2U6IGh0dHBzOi8vbWVtcG9vbC5zcGFjZS90ZXN0bmV0L2FkZHJlc3MvMk14VGkyRWhIS2dkSkZLUlRCdHRWR0d4aXI5WnpqbUtDWHdcbiAgICAvLyAyIG9mIDIgbXVsdGlzaWdcbiAgICBjb25zdCB0aW1lbG9jayA9ICdmY2U0Y2I2Nic7XG4gICAgY29uc3QgcHVia2V5MSA9ICcwM2VjYjZkNGI3ZjVkNTY5NjJlNTQ3ZmM1MmRkNTg4MzU5ZjU3MjljMGJhODU2ZDY5NzhiODQ3MjM4OTVhMTY2OTEnO1xuICAgIGNvbnN0IHB1YmtleTIgPSAnMDI0YWFlYTI1ZDgyYjFkYjJiZTAzMGEwNWI2NDFkNjMwMmU0OGVkNjUyYjFjYTljYjA4YTY3MjY3ZmNiYjU2NzQ3JztcbiAgICBjb25zdCByZWRlZW1TY3JpcHRBU00gPSBbXG4gICAgICAnT1BfUFVTSEJZVEVTXzQnLFxuICAgICAgdGltZWxvY2ssXG4gICAgICAnT1BfQ0xUVicsXG4gICAgICAnT1BfRFJPUCcsXG4gICAgICAnT1BfUFVTSE5VTV8yJyxcbiAgICAgICdPUF9QVVNIQllURVNfMzMnLFxuICAgICAgcHVia2V5MSxcbiAgICAgICdPUF9QVVNIQllURVNfMzMnLFxuICAgICAgcHVia2V5MixcbiAgICAgICdPUF9QVVNITlVNXzInLFxuICAgICAgJ09QX0NIRUNLTVVMVElTSUcnLFxuICAgIF0uam9pbignICcpO1xuXG4gICAgY29uc3QgZGVjb2RlZFRpbWVsb2NrID0gZGVjb2RlVGltZWxvY2soQnVmZmVyLmZyb20odGltZWxvY2ssICdoZXgnKSk7XG4gICAgY29uc3QgZGVzY3JpcHRvciA9IGNyZWF0ZU11bHRpU2lnRGVzY3JpcHRvcihcbiAgICAgICdzaCcsXG4gICAgICBkZWNvZGVkVGltZWxvY2ssXG4gICAgICAyLFxuICAgICAgW0J1ZmZlci5mcm9tKHB1YmtleTEsICdoZXgnKSwgQnVmZmVyLmZyb20ocHVia2V5MiwgJ2hleCcpXSxcbiAgICAgIGZhbHNlXG4gICAgKTtcbiAgICBjb25zdCBkZXNjcmlwdG9yQVNNID0gRGVzY3JpcHRvci5mcm9tU3RyaW5nKGRlc2NyaXB0b3IsICdkZWZpbml0ZScpLnRvQXNtU3RyaW5nKCk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChyZWRlZW1TY3JpcHRBU00sIGRlc2NyaXB0b3JBU00pO1xuICB9KTtcbn0pO1xuIl19
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=opReturn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opReturn.d.ts","sourceRoot":"","sources":["../../../../../test/unit/coreDao/opReturn.ts"],"names":[],"mappings":""}
@@ -0,0 +1,275 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const assert_1 = __importDefault(require("assert"));
7
+ const utxo_lib_1 = require("@bitgo-beta/utxo-lib");
8
+ const testutil_1 = require("@bitgo-beta/utxo-core/testutil");
9
+ const coreDao_1 = require("../../../src/coreDao");
10
+ describe('OP_RETURN', function () {
11
+ const validVersion = 2;
12
+ const validChainId = coreDao_1.CORE_DAO_MAINNET_CHAIN_ID;
13
+ // random 20 byte buffers
14
+ const validDelegator = Buffer.alloc(20, utxo_lib_1.testutil.getKey('wasm-possum').publicKey);
15
+ const validValidator = Buffer.alloc(20, utxo_lib_1.testutil.getKey('possum-wasm').publicKey);
16
+ const validFee = 1;
17
+ const validRedeemScript = Buffer.from('522103a8295453660d5e212d55556666666666666666666666666666666666', 'hex');
18
+ const validTimelock = 800800;
19
+ let defaultScript;
20
+ before(async function () {
21
+ // https://docs.coredao.org/docs/Learn/products/btc-staking/design#op_return-output-1
22
+ const script = await (0, testutil_1.getFixture)('test/fixtures/coreDao/opReturn/documentation.txt', undefined);
23
+ (0, assert_1.default)(typeof script === 'string');
24
+ defaultScript = script;
25
+ });
26
+ describe('createCoreDaoOpReturnOutputScript', function () {
27
+ it('should throw if invalid parameters are passed', function () {
28
+ assert_1.default.throws(() => (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
29
+ version: 292,
30
+ chainId: validChainId,
31
+ delegator: validDelegator,
32
+ validator: validValidator,
33
+ fee: validFee,
34
+ timelock: validTimelock,
35
+ }));
36
+ assert_1.default.throws(() => (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
37
+ version: validVersion,
38
+ chainId: Buffer.alloc(32, 0),
39
+ delegator: validDelegator,
40
+ validator: validValidator,
41
+ fee: validFee,
42
+ timelock: validTimelock,
43
+ }));
44
+ assert_1.default.throws(() => (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
45
+ version: validVersion,
46
+ chainId: validChainId,
47
+ delegator: Buffer.alloc(19, 0),
48
+ validator: validValidator,
49
+ fee: validFee,
50
+ timelock: validTimelock,
51
+ }));
52
+ assert_1.default.throws(() => (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
53
+ version: validVersion,
54
+ chainId: validChainId,
55
+ delegator: validDelegator,
56
+ validator: Buffer.alloc(19, 0),
57
+ fee: validFee,
58
+ timelock: validTimelock,
59
+ }));
60
+ assert_1.default.throws(() => (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
61
+ version: validVersion,
62
+ chainId: validChainId,
63
+ delegator: validDelegator,
64
+ validator: validValidator,
65
+ fee: 256,
66
+ timelock: validTimelock,
67
+ }));
68
+ assert_1.default.throws(() => (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
69
+ version: validVersion,
70
+ chainId: validChainId,
71
+ delegator: validDelegator,
72
+ validator: validValidator,
73
+ fee: validFee,
74
+ timelock: -1,
75
+ }));
76
+ });
77
+ it('should throw if the length of the script is too long', function () {
78
+ assert_1.default.throws(() => (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
79
+ version: validVersion,
80
+ chainId: validChainId,
81
+ delegator: validDelegator,
82
+ validator: validValidator,
83
+ fee: validFee,
84
+ redeemScript: Buffer.alloc(100),
85
+ }));
86
+ });
87
+ it('should return a buffer with the correct length', function () {
88
+ const script = (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
89
+ version: validVersion,
90
+ chainId: validChainId,
91
+ delegator: validDelegator,
92
+ validator: validValidator,
93
+ fee: validFee,
94
+ timelock: validTimelock,
95
+ });
96
+ // Make sure that the first byte is the OP_RETURN opcode
97
+ assert_1.default.strictEqual(script[0], 0x6a);
98
+ // Make sure that the length of the script matches what is in the buffer
99
+ assert_1.default.strictEqual(
100
+ // We do not count the OP_RETURN opcode or the bytes for the length
101
+ script.length - 2, script[1]);
102
+ });
103
+ it('should have the correct placement of the values provided with a redeem script', function () {
104
+ // This should produce an Op_RETURN that needs the extra push bytes for the length
105
+ const script = (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
106
+ version: validVersion,
107
+ chainId: validChainId,
108
+ delegator: validDelegator,
109
+ validator: validValidator,
110
+ fee: validFee,
111
+ redeemScript: validRedeemScript,
112
+ });
113
+ // Make sure that the first byte is the OP_RETURN opcode
114
+ assert_1.default.strictEqual(script[0], 0x6a);
115
+ // Make sure that the length of the script matches what is in the buffer
116
+ assert_1.default.strictEqual(script[1], 0x4c);
117
+ assert_1.default.strictEqual(
118
+ // We do not count the OP_RETURN opcode or the length + pushbytes
119
+ script.length - 3, script[2]);
120
+ // Satoshi plus identifier
121
+ assert_1.default.deepStrictEqual(script.subarray(3, 7).toString('hex'), coreDao_1.CORE_DAO_SATOSHI_PLUS_IDENTIFIER.toString('hex'));
122
+ // Make sure that the version is correct
123
+ assert_1.default.strictEqual(script[7], validVersion);
124
+ // Make sure that the chainId is correct
125
+ assert_1.default.deepStrictEqual(script.subarray(8, 10).toString('hex'), validChainId.toString('hex'));
126
+ // Make sure that the delegator is correct
127
+ assert_1.default.deepStrictEqual(script.subarray(10, 30).toString('hex'), validDelegator.toString('hex'));
128
+ // Make sure that the validator is correct
129
+ assert_1.default.deepStrictEqual(script.subarray(30, 50).toString('hex'), validValidator.toString('hex'));
130
+ // Make sure that the fee is correct
131
+ assert_1.default.strictEqual(script[50], validFee);
132
+ // Make sure that the redeemScript is correct
133
+ assert_1.default.deepStrictEqual(script.subarray(51, 51 + validRedeemScript.length).toString('hex'), validRedeemScript.toString('hex'));
134
+ });
135
+ it('should have the correct placement of the values provided with a blockheight timelock', function () {
136
+ // This should produce an Op_RETURN that needs the extra push bytes for the length
137
+ const script = (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
138
+ version: validVersion,
139
+ chainId: validChainId,
140
+ delegator: validDelegator,
141
+ validator: validValidator,
142
+ fee: validFee,
143
+ timelock: validTimelock,
144
+ });
145
+ // Make sure that the first byte is the OP_RETURN opcode
146
+ assert_1.default.strictEqual(script[0], 0x6a);
147
+ // Make sure that the length of the script matches what is in the buffer
148
+ assert_1.default.strictEqual(
149
+ // We do not count the OP_RETURN opcode or the length
150
+ script.length - 2, script[1]);
151
+ // Satoshi plus identifier
152
+ assert_1.default.deepStrictEqual(script.subarray(2, 6).toString('hex'), coreDao_1.CORE_DAO_SATOSHI_PLUS_IDENTIFIER.toString('hex'));
153
+ // Make sure that the version is correct
154
+ assert_1.default.strictEqual(script[6], validVersion);
155
+ // Make sure that the chainId is correct
156
+ assert_1.default.deepStrictEqual(script.subarray(7, 9).toString('hex'), validChainId.toString('hex'));
157
+ // Make sure that the delegator is correct
158
+ assert_1.default.deepStrictEqual(script.subarray(9, 29).toString('hex'), validDelegator.toString('hex'));
159
+ // Make sure that the validator is correct
160
+ assert_1.default.deepStrictEqual(script.subarray(29, 49).toString('hex'), validValidator.toString('hex'));
161
+ // Make sure that the fee is correct
162
+ assert_1.default.strictEqual(script[49], validFee);
163
+ // Make sure that the redeemScript is correct
164
+ assert_1.default.deepStrictEqual(script.subarray(50, 54).toString('hex'), (0, coreDao_1.encodeTimelock)(validTimelock).toString('hex'));
165
+ assert_1.default.deepStrictEqual((0, coreDao_1.decodeTimelock)(script.subarray(50, 54)), validTimelock);
166
+ });
167
+ it('should have the correct placement of the values provided with a time timelock', function () {
168
+ // This should produce an Op_RETURN that needs the extra push bytes for the length
169
+ const timelock = new Date('2022-01-01T00:00:00Z').getTime() / 1000;
170
+ const script = (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
171
+ version: validVersion,
172
+ chainId: validChainId,
173
+ delegator: validDelegator,
174
+ validator: validValidator,
175
+ fee: validFee,
176
+ timelock,
177
+ });
178
+ // Make sure that the first byte is the OP_RETURN opcode
179
+ assert_1.default.strictEqual(script[0], 0x6a);
180
+ // Make sure that the length of the script matches what is in the buffer
181
+ assert_1.default.strictEqual(
182
+ // We do not count the OP_RETURN opcode or the length
183
+ script.length - 2, script[1]);
184
+ // Satoshi plus identifier
185
+ assert_1.default.deepStrictEqual(script.subarray(2, 6).toString('hex'), coreDao_1.CORE_DAO_SATOSHI_PLUS_IDENTIFIER.toString('hex'));
186
+ // Make sure that the version is correct
187
+ assert_1.default.strictEqual(script[6], validVersion);
188
+ // Make sure that the chainId is correct
189
+ assert_1.default.deepStrictEqual(script.subarray(7, 9).toString('hex'), validChainId.toString('hex'));
190
+ // Make sure that the delegator is correct
191
+ assert_1.default.deepStrictEqual(script.subarray(9, 29).toString('hex'), validDelegator.toString('hex'));
192
+ // Make sure that the validator is correct
193
+ assert_1.default.deepStrictEqual(script.subarray(29, 49).toString('hex'), validValidator.toString('hex'));
194
+ // Make sure that the fee is correct
195
+ assert_1.default.strictEqual(script[49], validFee);
196
+ // Make sure that the redeemScript is correct
197
+ assert_1.default.deepStrictEqual(script.subarray(50, 54).toString('hex'), (0, coreDao_1.encodeTimelock)(timelock).toString('hex'));
198
+ assert_1.default.deepStrictEqual((0, coreDao_1.decodeTimelock)(script.subarray(50, 54)), timelock);
199
+ });
200
+ it('should recreate the example OP_RETURN correctly', function () {
201
+ assert_1.default.deepStrictEqual((0, coreDao_1.createCoreDaoOpReturnOutputScript)({
202
+ version: 1,
203
+ chainId: Buffer.from('045b', 'hex'),
204
+ delegator: Buffer.from('de60b7d0e6b758ca5dd8c61d377a2c5f1af51ec1', 'hex'),
205
+ validator: Buffer.from('a9e209f5ea0036c8c2f41078a3cebee57d8a47d5', 'hex'),
206
+ fee: 1,
207
+ redeemScript: Buffer.from('041f5e0e66b17576a914c4b8ae927ff2b9ce218e20bf06d425d6b68424fd88ac', 'hex'),
208
+ }).toString('hex'), defaultScript);
209
+ });
210
+ });
211
+ describe('parseCoreDaoOpReturnOutputScript', function () {
212
+ it('should parse a valid script with a timelock', function () {
213
+ const script = (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
214
+ version: validVersion,
215
+ chainId: validChainId,
216
+ delegator: validDelegator,
217
+ validator: validValidator,
218
+ fee: validFee,
219
+ timelock: validTimelock,
220
+ });
221
+ const parsed = (0, coreDao_1.parseCoreDaoOpReturnOutputScript)(script);
222
+ assert_1.default.strictEqual(parsed.version, validVersion);
223
+ assert_1.default.deepStrictEqual(parsed.chainId, validChainId);
224
+ assert_1.default.deepStrictEqual(parsed.delegator, validDelegator);
225
+ assert_1.default.deepStrictEqual(parsed.validator, validValidator);
226
+ assert_1.default.strictEqual(parsed.fee, validFee);
227
+ (0, assert_1.default)('timelock' in parsed);
228
+ assert_1.default.deepStrictEqual(parsed.timelock, validTimelock);
229
+ });
230
+ it('should parse a valid script with a redeem script', function () {
231
+ const script = (0, coreDao_1.createCoreDaoOpReturnOutputScript)({
232
+ version: validVersion,
233
+ chainId: validChainId,
234
+ delegator: validDelegator,
235
+ validator: validValidator,
236
+ fee: validFee,
237
+ redeemScript: validRedeemScript,
238
+ });
239
+ const parsed = (0, coreDao_1.parseCoreDaoOpReturnOutputScript)(script);
240
+ assert_1.default.strictEqual(parsed.version, validVersion);
241
+ assert_1.default.deepStrictEqual(parsed.chainId, validChainId);
242
+ assert_1.default.deepStrictEqual(parsed.delegator, validDelegator);
243
+ assert_1.default.deepStrictEqual(parsed.validator, validValidator);
244
+ assert_1.default.strictEqual(parsed.fee, validFee);
245
+ (0, assert_1.default)('redeemScript' in parsed);
246
+ assert_1.default.deepStrictEqual(parsed.redeemScript, validRedeemScript);
247
+ });
248
+ it('should parse valid opreturn script from testnet', async function () {
249
+ // Source: https://mempool.space/testnet/tx/66ed4cea26a410248a6d87f14b2bca514f33920c54d4af63ed46a903793115d5
250
+ const baseFixturePath = 'test/fixtures/coreDao/opReturn/66ed4cea26a410248a6d87f14b2bca514f33920c54d4af63ed46a903793115d5';
251
+ const opReturnHex = await (0, testutil_1.getFixture)(baseFixturePath + '.txt', undefined);
252
+ (0, assert_1.default)(typeof opReturnHex === 'string');
253
+ const parsed = (0, coreDao_1.parseCoreDaoOpReturnOutputScript)(Buffer.from(opReturnHex, 'hex'));
254
+ const parsedFixture = await (0, testutil_1.getFixture)(baseFixturePath + '.json', JSON.parse((0, coreDao_1.toString)(parsed)));
255
+ assert_1.default.deepStrictEqual((0, coreDao_1.toString)(parsed), JSON.stringify(parsedFixture));
256
+ });
257
+ it('should fail if there is an invalid op-return', function () {
258
+ const script = defaultScript.replace('6a4c50', '6b4c50');
259
+ assert_1.default.throws(() => (0, coreDao_1.parseCoreDaoOpReturnOutputScript)(Buffer.from(script, 'hex')));
260
+ });
261
+ it('should fail if the length is incorrect', function () {
262
+ const script = defaultScript.replace('4c50', '4c51');
263
+ assert_1.default.throws(() => (0, coreDao_1.parseCoreDaoOpReturnOutputScript)(Buffer.from(script, 'hex')));
264
+ });
265
+ it('should fail if the satoshi+ identifier is incorrect', function () {
266
+ const script = defaultScript.replace('5341542b', '5341532b');
267
+ assert_1.default.throws(() => (0, coreDao_1.parseCoreDaoOpReturnOutputScript)(Buffer.from(script, 'hex')));
268
+ });
269
+ it('should fail if the chainId is incorrect', function () {
270
+ const script = defaultScript.replace('045b', '0454');
271
+ assert_1.default.throws(() => (0, coreDao_1.parseCoreDaoOpReturnOutputScript)(Buffer.from(script, 'hex')));
272
+ });
273
+ });
274
+ });
275
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BSZXR1cm4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZXN0L3VuaXQvY29yZURhby9vcFJldHVybi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9EQUE0QjtBQUU1QixtREFBZ0Q7QUFDaEQsNkRBQTREO0FBRTVELGtEQVE4QjtBQUU5QixRQUFRLENBQUMsV0FBVyxFQUFFO0lBQ3BCLE1BQU0sWUFBWSxHQUFHLENBQUMsQ0FBQztJQUN2QixNQUFNLFlBQVksR0FBRyxtQ0FBeUIsQ0FBQztJQUMvQyx5QkFBeUI7SUFDekIsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsbUJBQVEsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbEYsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsbUJBQVEsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDbEYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxnRUFBZ0UsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvRyxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUM7SUFDN0IsSUFBSSxhQUFxQixDQUFDO0lBRTFCLE1BQU0sQ0FBQyxLQUFLO1FBQ1YscUZBQXFGO1FBQ3JGLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBQSxxQkFBVSxFQUFDLGtEQUFrRCxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQy9GLElBQUEsZ0JBQU0sRUFBQyxPQUFPLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQztRQUNuQyxhQUFhLEdBQUcsTUFBTSxDQUFDO0lBQ3pCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLG1DQUFtQyxFQUFFO1FBQzVDLEVBQUUsQ0FBQywrQ0FBK0Ms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LENBQUM7UUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUU7WUFDakQsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDekQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBQSwwQ0FBZ0MsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEYsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsd0NBQXdDLEVBQUU7WUFDM0MsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDckQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBQSwwQ0FBZ0MsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEYsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMscURBQXFELEVBQUU7WUFDeEQsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDN0QsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBQSwwQ0FBZ0MsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEYsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseUNBQXlDLEVBQUU7WUFDNUMsTUFBTSxNQUFNLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDckQsZ0JBQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBQSwwQ0FBZ0MsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDcEYsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5pbXBvcnQgeyB0ZXN0dXRpbCB9IGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tbGliJztcbmltcG9ydCB7IGdldEZpeHR1cmUgfSBmcm9tICdAYml0Z28tYmV0YS91dHhvLWNvcmUvdGVzdHV0aWwnO1xuXG5pbXBvcnQge1xuICBDT1JFX0RBT19NQUlOTkVUX0NIQUlOX0lELFxuICBDT1JFX0RBT19TQVRPU0hJX1BMVVNfSURFTlRJRklFUixcbiAgY3JlYXRlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0LFxuICBkZWNvZGVUaW1lbG9jayxcbiAgZW5jb2RlVGltZWxvY2ssXG4gIHBhcnNlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0LFxuICB0b1N0cmluZyxcbn0gZnJvbSAnLi4vLi4vLi4vc3JjL2NvcmVEYW8nO1xuXG5kZXNjcmliZSgnT1BfUkVUVVJOJywgZnVuY3Rpb24gKCkge1xuICBjb25zdCB2YWxpZFZlcnNpb24gPSAyO1xuICBjb25zdCB2YWxpZENoYWluSWQgPSBDT1JFX0RBT19NQUlOTkVUX0NIQUlOX0lEO1xuICAvLyByYW5kb20gMjAgYnl0ZSBidWZmZXJzXG4gIGNvbnN0IHZhbGlkRGVsZWdhdG9yID0gQnVmZmVyLmFsbG9jKDIwLCB0ZXN0dXRpbC5nZXRLZXkoJ3dhc20tcG9zc3VtJykucHVibGljS2V5KTtcbiAgY29uc3QgdmFsaWRWYWxpZGF0b3IgPSBCdWZmZXIuYWxsb2MoMjAsIHRlc3R1dGlsLmdldEtleSgncG9zc3VtLXdhc20nKS5wdWJsaWNLZXkpO1xuICBjb25zdCB2YWxpZEZlZSA9IDE7XG4gIGNvbnN0IHZhbGlkUmVkZWVtU2NyaXB0ID0gQnVmZmVyLmZyb20oJzUyMjEwM2E4Mjk1NDUzNjYwZDVlMjEyZDU1NTU2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2JywgJ2hleCcpO1xuICBjb25zdCB2YWxpZFRpbWVsb2NrID0gODAwODAwO1xuICBsZXQgZGVmYXVsdFNjcmlwdDogc3RyaW5nO1xuXG4gIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgLy8gaHR0cHM6Ly9kb2NzLmNvcmVkYW8ub3JnL2RvY3MvTGVhcm4vcHJvZHVjdHMvYnRjLXN0YWtpbmcvZGVzaWduI29wX3JldHVybi1vdXRwdXQtMVxuICAgIGNvbnN0IHNjcmlwdCA9IGF3YWl0IGdldEZpeHR1cmUoJ3Rlc3QvZml4dHVyZXMvY29yZURhby9vcFJldHVybi9kb2N1bWVudGF0aW9uLnR4dCcsIHVuZGVmaW5lZCk7XG4gICAgYXNzZXJ0KHR5cGVvZiBzY3JpcHQgPT09ICdzdHJpbmcnKTtcbiAgICBkZWZhdWx0U2NyaXB0ID0gc2NyaXB0O1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0JywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgdGhyb3cgaWYgaW52YWxpZCBwYXJhbWV0ZXJzIGFyZSBwYXNzZWQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+XG4gICAgICAgIGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgICAgdmVyc2lvbjogMjkyLFxuICAgICAgICAgIGNoYWluSWQ6IHZhbGlkQ2hhaW5JZCxcbiAgICAgICAgICBkZWxlZ2F0b3I6IHZhbGlkRGVsZWdhdG9yLFxuICAgICAgICAgIHZhbGlkYXRvcjogdmFsaWRWYWxpZGF0b3IsXG4gICAgICAgICAgZmVlOiB2YWxpZEZlZSxcbiAgICAgICAgICB0aW1lbG9jazogdmFsaWRUaW1lbG9jayxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+XG4gICAgICAgIGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgICAgdmVyc2lvbjogdmFsaWRWZXJzaW9uLFxuICAgICAgICAgIGNoYWluSWQ6IEJ1ZmZlci5hbGxvYygzMiwgMCksXG4gICAgICAgICAgZGVsZWdhdG9yOiB2YWxpZERlbGVnYXRvcixcbiAgICAgICAgICB2YWxpZGF0b3I6IHZhbGlkVmFsaWRhdG9yLFxuICAgICAgICAgIGZlZTogdmFsaWRGZWUsXG4gICAgICAgICAgdGltZWxvY2s6IHZhbGlkVGltZWxvY2ssXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PlxuICAgICAgICBjcmVhdGVDb3JlRGFvT3BSZXR1cm5PdXRwdXRTY3JpcHQoe1xuICAgICAgICAgIHZlcnNpb246IHZhbGlkVmVyc2lvbixcbiAgICAgICAgICBjaGFpbklkOiB2YWxpZENoYWluSWQsXG4gICAgICAgICAgZGVsZWdhdG9yOiBCdWZmZXIuYWxsb2MoMTksIDApLFxuICAgICAgICAgIHZhbGlkYXRvcjogdmFsaWRWYWxpZGF0b3IsXG4gICAgICAgICAgZmVlOiB2YWxpZEZlZSxcbiAgICAgICAgICB0aW1lbG9jazogdmFsaWRUaW1lbG9jayxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+XG4gICAgICAgIGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgICAgdmVyc2lvbjogdmFsaWRWZXJzaW9uLFxuICAgICAgICAgIGNoYWluSWQ6IHZhbGlkQ2hhaW5JZCxcbiAgICAgICAgICBkZWxlZ2F0b3I6IHZhbGlkRGVsZWdhdG9yLFxuICAgICAgICAgIHZhbGlkYXRvcjogQnVmZmVyLmFsbG9jKDE5LCAwKSxcbiAgICAgICAgICBmZWU6IHZhbGlkRmVlLFxuICAgICAgICAgIHRpbWVsb2NrOiB2YWxpZFRpbWVsb2NrLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT5cbiAgICAgICAgY3JlYXRlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0KHtcbiAgICAgICAgICB2ZXJzaW9uOiB2YWxpZFZlcnNpb24sXG4gICAgICAgICAgY2hhaW5JZDogdmFsaWRDaGFpbklkLFxuICAgICAgICAgIGRlbGVnYXRvcjogdmFsaWREZWxlZ2F0b3IsXG4gICAgICAgICAgdmFsaWRhdG9yOiB2YWxpZFZhbGlkYXRvcixcbiAgICAgICAgICBmZWU6IDI1NixcbiAgICAgICAgICB0aW1lbG9jazogdmFsaWRUaW1lbG9jayxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+XG4gICAgICAgIGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgICAgdmVyc2lvbjogdmFsaWRWZXJzaW9uLFxuICAgICAgICAgIGNoYWluSWQ6IHZhbGlkQ2hhaW5JZCxcbiAgICAgICAgICBkZWxlZ2F0b3I6IHZhbGlkRGVsZWdhdG9yLFxuICAgICAgICAgIHZhbGlkYXRvcjogdmFsaWRWYWxpZGF0b3IsXG4gICAgICAgICAgZmVlOiB2YWxpZEZlZSxcbiAgICAgICAgICB0aW1lbG9jazogLTEsXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBpZiB0aGUgbGVuZ3RoIG9mIHRoZSBzY3JpcHQgaXMgdG9vIGxvbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+XG4gICAgICAgIGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgICAgdmVyc2lvbjogdmFsaWRWZXJzaW9uLFxuICAgICAgICAgIGNoYWluSWQ6IHZhbGlkQ2hhaW5JZCxcbiAgICAgICAgICBkZWxlZ2F0b3I6IHZhbGlkRGVsZWdhdG9yLFxuICAgICAgICAgIHZhbGlkYXRvcjogdmFsaWRWYWxpZGF0b3IsXG4gICAgICAgICAgZmVlOiB2YWxpZEZlZSxcbiAgICAgICAgICByZWRlZW1TY3JpcHQ6IEJ1ZmZlci5hbGxvYygxMDApLFxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGEgYnVmZmVyIHdpdGggdGhlIGNvcnJlY3QgbGVuZ3RoJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2NyaXB0ID0gY3JlYXRlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0KHtcbiAgICAgICAgdmVyc2lvbjogdmFsaWRWZXJzaW9uLFxuICAgICAgICBjaGFpbklkOiB2YWxpZENoYWluSWQsXG4gICAgICAgIGRlbGVnYXRvcjogdmFsaWREZWxlZ2F0b3IsXG4gICAgICAgIHZhbGlkYXRvcjogdmFsaWRWYWxpZGF0b3IsXG4gICAgICAgIGZlZTogdmFsaWRGZWUsXG4gICAgICAgIHRpbWVsb2NrOiB2YWxpZFRpbWVsb2NrLFxuICAgICAgfSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgZmlyc3QgYnl0ZSBpcyB0aGUgT1BfUkVUVVJOIG9wY29kZVxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNjcmlwdFswXSwgMHg2YSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgbGVuZ3RoIG9mIHRoZSBzY3JpcHQgbWF0Y2hlcyB3aGF0IGlzIGluIHRoZSBidWZmZXJcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgLy8gV2UgZG8gbm90IGNvdW50IHRoZSBPUF9SRVRVUk4gb3Bjb2RlIG9yIHRoZSBieXRlcyBmb3IgdGhlIGxlbmd0aFxuICAgICAgICBzY3JpcHQubGVuZ3RoIC0gMixcbiAgICAgICAgc2NyaXB0WzFdXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYXZlIHRoZSBjb3JyZWN0IHBsYWNlbWVudCBvZiB0aGUgdmFsdWVzIHByb3ZpZGVkIHdpdGggYSByZWRlZW0gc2NyaXB0JywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gVGhpcyBzaG91bGQgcHJvZHVjZSBhbiBPcF9SRVRVUk4gdGhhdCBuZWVkcyB0aGUgZXh0cmEgcHVzaCBieXRlcyBmb3IgdGhlIGxlbmd0aFxuICAgICAgY29uc3Qgc2NyaXB0ID0gY3JlYXRlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0KHtcbiAgICAgICAgdmVyc2lvbjogdmFsaWRWZXJzaW9uLFxuICAgICAgICBjaGFpbklkOiB2YWxpZENoYWluSWQsXG4gICAgICAgIGRlbGVnYXRvcjogdmFsaWREZWxlZ2F0b3IsXG4gICAgICAgIHZhbGlkYXRvcjogdmFsaWRWYWxpZGF0b3IsXG4gICAgICAgIGZlZTogdmFsaWRGZWUsXG4gICAgICAgIHJlZGVlbVNjcmlwdDogdmFsaWRSZWRlZW1TY3JpcHQsXG4gICAgICB9KTtcbiAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBmaXJzdCBieXRlIGlzIHRoZSBPUF9SRVRVUk4gb3Bjb2RlXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2NyaXB0WzBdLCAweDZhKTtcbiAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBsZW5ndGggb2YgdGhlIHNjcmlwdCBtYXRjaGVzIHdoYXQgaXMgaW4gdGhlIGJ1ZmZlclxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNjcmlwdFsxXSwgMHg0Yyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICAgIC8vIFdlIGRvIG5vdCBjb3VudCB0aGUgT1BfUkVUVVJOIG9wY29kZSBvciB0aGUgbGVuZ3RoICsgcHVzaGJ5dGVzXG4gICAgICAgIHNjcmlwdC5sZW5ndGggLSAzLFxuICAgICAgICBzY3JpcHRbMl1cbiAgICAgICk7XG4gICAgICAvLyBTYXRvc2hpIHBsdXMgaWRlbnRpZmllclxuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChzY3JpcHQuc3ViYXJyYXkoMywgNykudG9TdHJpbmcoJ2hleCcpLCBDT1JFX0RBT19TQVRPU0hJX1BMVVNfSURFTlRJRklFUi50b1N0cmluZygnaGV4JykpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIHZlcnNpb24gaXMgY29ycmVjdFxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNjcmlwdFs3XSwgdmFsaWRWZXJzaW9uKTtcbiAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBjaGFpbklkIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0LnN1YmFycmF5KDgsIDEwKS50b1N0cmluZygnaGV4JyksIHZhbGlkQ2hhaW5JZC50b1N0cmluZygnaGV4JykpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGRlbGVnYXRvciBpcyBjb3JyZWN0XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHNjcmlwdC5zdWJhcnJheSgxMCwgMzApLnRvU3RyaW5nKCdoZXgnKSwgdmFsaWREZWxlZ2F0b3IudG9TdHJpbmcoJ2hleCcpKTtcbiAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSB2YWxpZGF0b3IgaXMgY29ycmVjdFxuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChzY3JpcHQuc3ViYXJyYXkoMzAsIDUwKS50b1N0cmluZygnaGV4JyksIHZhbGlkVmFsaWRhdG9yLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgZmVlIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzY3JpcHRbNTBdLCB2YWxpZEZlZSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgcmVkZWVtU2NyaXB0IGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoXG4gICAgICAgIHNjcmlwdC5zdWJhcnJheSg1MSwgNTEgKyB2YWxpZFJlZGVlbVNjcmlwdC5sZW5ndGgpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgdmFsaWRSZWRlZW1TY3JpcHQudG9TdHJpbmcoJ2hleCcpXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBoYXZlIHRoZSBjb3JyZWN0IHBsYWNlbWVudCBvZiB0aGUgdmFsdWVzIHByb3ZpZGVkIHdpdGggYSBibG9ja2hlaWdodCB0aW1lbG9jaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFRoaXMgc2hvdWxkIHByb2R1Y2UgYW4gT3BfUkVUVVJOIHRoYXQgbmVlZHMgdGhlIGV4dHJhIHB1c2ggYnl0ZXMgZm9yIHRoZSBsZW5ndGhcbiAgICAgIGNvbnN0IHNjcmlwdCA9IGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgIHZlcnNpb246IHZhbGlkVmVyc2lvbixcbiAgICAgICAgY2hhaW5JZDogdmFsaWRDaGFpbklkLFxuICAgICAgICBkZWxlZ2F0b3I6IHZhbGlkRGVsZWdhdG9yLFxuICAgICAgICB2YWxpZGF0b3I6IHZhbGlkVmFsaWRhdG9yLFxuICAgICAgICBmZWU6IHZhbGlkRmVlLFxuICAgICAgICB0aW1lbG9jazogdmFsaWRUaW1lbG9jayxcbiAgICAgIH0pO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGZpcnN0IGJ5dGUgaXMgdGhlIE9QX1JFVFVSTiBvcGNvZGVcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzY3JpcHRbMF0sIDB4NmEpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGxlbmd0aCBvZiB0aGUgc2NyaXB0IG1hdGNoZXMgd2hhdCBpcyBpbiB0aGUgYnVmZmVyXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICAgIC8vIFdlIGRvIG5vdCBjb3VudCB0aGUgT1BfUkVUVVJOIG9wY29kZSBvciB0aGUgbGVuZ3RoXG4gICAgICAgIHNjcmlwdC5sZW5ndGggLSAyLFxuICAgICAgICBzY3JpcHRbMV1cbiAgICAgICk7XG4gICAgICAvLyBTYXRvc2hpIHBsdXMgaWRlbnRpZmllclxuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChzY3JpcHQuc3ViYXJyYXkoMiwgNikudG9TdHJpbmcoJ2hleCcpLCBDT1JFX0RBT19TQVRPU0hJX1BMVVNfSURFTlRJRklFUi50b1N0cmluZygnaGV4JykpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIHZlcnNpb24gaXMgY29ycmVjdFxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNjcmlwdFs2XSwgdmFsaWRWZXJzaW9uKTtcbiAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBjaGFpbklkIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0LnN1YmFycmF5KDcsIDkpLnRvU3RyaW5nKCdoZXgnKSwgdmFsaWRDaGFpbklkLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgZGVsZWdhdG9yIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0LnN1YmFycmF5KDksIDI5KS50b1N0cmluZygnaGV4JyksIHZhbGlkRGVsZWdhdG9yLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgdmFsaWRhdG9yIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0LnN1YmFycmF5KDI5LCA0OSkudG9TdHJpbmcoJ2hleCcpLCB2YWxpZFZhbGlkYXRvci50b1N0cmluZygnaGV4JykpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGZlZSBpcyBjb3JyZWN0XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2NyaXB0WzQ5XSwgdmFsaWRGZWUpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIHJlZGVlbVNjcmlwdCBpcyBjb3JyZWN0XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHNjcmlwdC5zdWJhcnJheSg1MCwgNTQpLnRvU3RyaW5nKCdoZXgnKSwgZW5jb2RlVGltZWxvY2sodmFsaWRUaW1lbG9jaykudG9TdHJpbmcoJ2hleCcpKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoZGVjb2RlVGltZWxvY2soc2NyaXB0LnN1YmFycmF5KDUwLCA1NCkpLCB2YWxpZFRpbWVsb2NrKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgaGF2ZSB0aGUgY29ycmVjdCBwbGFjZW1lbnQgb2YgdGhlIHZhbHVlcyBwcm92aWRlZCB3aXRoIGEgdGltZSB0aW1lbG9jaycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFRoaXMgc2hvdWxkIHByb2R1Y2UgYW4gT3BfUkVUVVJOIHRoYXQgbmVlZHMgdGhlIGV4dHJhIHB1c2ggYnl0ZXMgZm9yIHRoZSBsZW5ndGhcbiAgICAgIGNvbnN0IHRpbWVsb2NrID0gbmV3IERhdGUoJzIwMjItMDEtMDFUMDA6MDA6MDBaJykuZ2V0VGltZSgpIC8gMTAwMDtcbiAgICAgIGNvbnN0IHNjcmlwdCA9IGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgIHZlcnNpb246IHZhbGlkVmVyc2lvbixcbiAgICAgICAgY2hhaW5JZDogdmFsaWRDaGFpbklkLFxuICAgICAgICBkZWxlZ2F0b3I6IHZhbGlkRGVsZWdhdG9yLFxuICAgICAgICB2YWxpZGF0b3I6IHZhbGlkVmFsaWRhdG9yLFxuICAgICAgICBmZWU6IHZhbGlkRmVlLFxuICAgICAgICB0aW1lbG9jayxcbiAgICAgIH0pO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGZpcnN0IGJ5dGUgaXMgdGhlIE9QX1JFVFVSTiBvcGNvZGVcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChzY3JpcHRbMF0sIDB4NmEpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGxlbmd0aCBvZiB0aGUgc2NyaXB0IG1hdGNoZXMgd2hhdCBpcyBpbiB0aGUgYnVmZmVyXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICAgIC8vIFdlIGRvIG5vdCBjb3VudCB0aGUgT1BfUkVUVVJOIG9wY29kZSBvciB0aGUgbGVuZ3RoXG4gICAgICAgIHNjcmlwdC5sZW5ndGggLSAyLFxuICAgICAgICBzY3JpcHRbMV1cbiAgICAgICk7XG4gICAgICAvLyBTYXRvc2hpIHBsdXMgaWRlbnRpZmllclxuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChzY3JpcHQuc3ViYXJyYXkoMiwgNikudG9TdHJpbmcoJ2hleCcpLCBDT1JFX0RBT19TQVRPU0hJX1BMVVNfSURFTlRJRklFUi50b1N0cmluZygnaGV4JykpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIHZlcnNpb24gaXMgY29ycmVjdFxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNjcmlwdFs2XSwgdmFsaWRWZXJzaW9uKTtcbiAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSBjaGFpbklkIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0LnN1YmFycmF5KDcsIDkpLnRvU3RyaW5nKCdoZXgnKSwgdmFsaWRDaGFpbklkLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgZGVsZWdhdG9yIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0LnN1YmFycmF5KDksIDI5KS50b1N0cmluZygnaGV4JyksIHZhbGlkRGVsZWdhdG9yLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgdmFsaWRhdG9yIGlzIGNvcnJlY3RcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoc2NyaXB0LnN1YmFycmF5KDI5LCA0OSkudG9TdHJpbmcoJ2hleCcpLCB2YWxpZFZhbGlkYXRvci50b1N0cmluZygnaGV4JykpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIGZlZSBpcyBjb3JyZWN0XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2NyaXB0WzQ5XSwgdmFsaWRGZWUpO1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgdGhlIHJlZGVlbVNjcmlwdCBpcyBjb3JyZWN0XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHNjcmlwdC5zdWJhcnJheSg1MCwgNTQpLnRvU3RyaW5nKCdoZXgnKSwgZW5jb2RlVGltZWxvY2sodGltZWxvY2spLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGRlY29kZVRpbWVsb2NrKHNjcmlwdC5zdWJhcnJheSg1MCwgNTQpKSwgdGltZWxvY2spO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWNyZWF0ZSB0aGUgZXhhbXBsZSBPUF9SRVRVUk4gY29ycmVjdGx5JywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChcbiAgICAgICAgY3JlYXRlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0KHtcbiAgICAgICAgICB2ZXJzaW9uOiAxLFxuICAgICAgICAgIGNoYWluSWQ6IEJ1ZmZlci5mcm9tKCcwNDViJywgJ2hleCcpLFxuICAgICAgICAgIGRlbGVnYXRvcjogQnVmZmVyLmZyb20oJ2RlNjBiN2QwZTZiNzU4Y2E1ZGQ4YzYxZDM3N2EyYzVmMWFmNTFlYzEnLCAnaGV4JyksXG4gICAgICAgICAgdmFsaWRhdG9yOiBCdWZmZXIuZnJvbSgnYTllMjA5ZjVlYTAwMzZjOGMyZjQxMDc4YTNjZWJlZTU3ZDhhNDdkNScsICdoZXgnKSxcbiAgICAgICAgICBmZWU6IDEsXG4gICAgICAgICAgcmVkZWVtU2NyaXB0OiBCdWZmZXIuZnJvbSgnMDQxZjVlMGU2NmIxNzU3NmE5MTRjNGI4YWU5MjdmZjJiOWNlMjE4ZTIwYmYwNmQ0MjVkNmI2ODQyNGZkODhhYycsICdoZXgnKSxcbiAgICAgICAgfSkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICBkZWZhdWx0U2NyaXB0XG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncGFyc2VDb3JlRGFvT3BSZXR1cm5PdXRwdXRTY3JpcHQnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhIHZhbGlkIHNjcmlwdCB3aXRoIGEgdGltZWxvY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzY3JpcHQgPSBjcmVhdGVDb3JlRGFvT3BSZXR1cm5PdXRwdXRTY3JpcHQoe1xuICAgICAgICB2ZXJzaW9uOiB2YWxpZFZlcnNpb24sXG4gICAgICAgIGNoYWluSWQ6IHZhbGlkQ2hhaW5JZCxcbiAgICAgICAgZGVsZWdhdG9yOiB2YWxpZERlbGVnYXRvcixcbiAgICAgICAgdmFsaWRhdG9yOiB2YWxpZFZhbGlkYXRvcixcbiAgICAgICAgZmVlOiB2YWxpZEZlZSxcbiAgICAgICAgdGltZWxvY2s6IHZhbGlkVGltZWxvY2ssXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0KHNjcmlwdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnZlcnNpb24sIHZhbGlkVmVyc2lvbik7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZC5jaGFpbklkLCB2YWxpZENoYWluSWQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQuZGVsZWdhdG9yLCB2YWxpZERlbGVnYXRvcik7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZC52YWxpZGF0b3IsIHZhbGlkVmFsaWRhdG9yKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQuZmVlLCB2YWxpZEZlZSk7XG4gICAgICBhc3NlcnQoJ3RpbWVsb2NrJyBpbiBwYXJzZWQpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQudGltZWxvY2ssIHZhbGlkVGltZWxvY2spO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBwYXJzZSBhIHZhbGlkIHNjcmlwdCB3aXRoIGEgcmVkZWVtIHNjcmlwdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNjcmlwdCA9IGNyZWF0ZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdCh7XG4gICAgICAgIHZlcnNpb246IHZhbGlkVmVyc2lvbixcbiAgICAgICAgY2hhaW5JZDogdmFsaWRDaGFpbklkLFxuICAgICAgICBkZWxlZ2F0b3I6IHZhbGlkRGVsZWdhdG9yLFxuICAgICAgICB2YWxpZGF0b3I6IHZhbGlkVmFsaWRhdG9yLFxuICAgICAgICBmZWU6IHZhbGlkRmVlLFxuICAgICAgICByZWRlZW1TY3JpcHQ6IHZhbGlkUmVkZWVtU2NyaXB0LFxuICAgICAgfSk7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdChzY3JpcHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC52ZXJzaW9uLCB2YWxpZFZlcnNpb24pO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQuY2hhaW5JZCwgdmFsaWRDaGFpbklkKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocGFyc2VkLmRlbGVnYXRvciwgdmFsaWREZWxlZ2F0b3IpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChwYXJzZWQudmFsaWRhdG9yLCB2YWxpZFZhbGlkYXRvcik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLmZlZSwgdmFsaWRGZWUpO1xuICAgICAgYXNzZXJ0KCdyZWRlZW1TY3JpcHQnIGluIHBhcnNlZCk7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHBhcnNlZC5yZWRlZW1TY3JpcHQsIHZhbGlkUmVkZWVtU2NyaXB0KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcGFyc2UgdmFsaWQgb3ByZXR1cm4gc2NyaXB0IGZyb20gdGVzdG5ldCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFNvdXJjZTogaHR0cHM6Ly9tZW1wb29sLnNwYWNlL3Rlc3RuZXQvdHgvNjZlZDRjZWEyNmE0MTAyNDhhNmQ4N2YxNGIyYmNhNTE0ZjMzOTIwYzU0ZDRhZjYzZWQ0NmE5MDM3OTMxMTVkNVxuICAgICAgY29uc3QgYmFzZUZpeHR1cmVQYXRoID1cbiAgICAgICAgJ3Rlc3QvZml4dHVyZXMvY29yZURhby9vcFJldHVybi82NmVkNGNlYTI2YTQxMDI0OGE2ZDg3ZjE0YjJiY2E1MTRmMzM5MjBjNTRkNGFmNjNlZDQ2YTkwMzc5MzExNWQ1JztcbiAgICAgIGNvbnN0IG9wUmV0dXJuSGV4ID0gYXdhaXQgZ2V0Rml4dHVyZShiYXNlRml4dHVyZVBhdGggKyAnLnR4dCcsIHVuZGVmaW5lZCk7XG4gICAgICBhc3NlcnQodHlwZW9mIG9wUmV0dXJuSGV4ID09PSAnc3RyaW5nJyk7XG4gICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdChCdWZmZXIuZnJvbShvcFJldHVybkhleCwgJ2hleCcpKTtcbiAgICAgIGNvbnN0IHBhcnNlZEZpeHR1cmUgPSBhd2FpdCBnZXRGaXh0dXJlKGJhc2VGaXh0dXJlUGF0aCArICcuanNvbicsIEpTT04ucGFyc2UodG9TdHJpbmcocGFyc2VkKSkpO1xuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0b1N0cmluZyhwYXJzZWQpLCBKU09OLnN0cmluZ2lmeShwYXJzZWRGaXh0dXJlKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlcmUgaXMgYW4gaW52YWxpZCBvcC1yZXR1cm4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzY3JpcHQgPSBkZWZhdWx0U2NyaXB0LnJlcGxhY2UoJzZhNGM1MCcsICc2YjRjNTAnKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gcGFyc2VDb3JlRGFvT3BSZXR1cm5PdXRwdXRTY3JpcHQoQnVmZmVyLmZyb20oc2NyaXB0LCAnaGV4JykpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBpZiB0aGUgbGVuZ3RoIGlzIGluY29ycmVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNjcmlwdCA9IGRlZmF1bHRTY3JpcHQucmVwbGFjZSgnNGM1MCcsICc0YzUxJyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHBhcnNlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0KEJ1ZmZlci5mcm9tKHNjcmlwdCwgJ2hleCcpKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlIHNhdG9zaGkrIGlkZW50aWZpZXIgaXMgaW5jb3JyZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2NyaXB0ID0gZGVmYXVsdFNjcmlwdC5yZXBsYWNlKCc1MzQxNTQyYicsICc1MzQxNTMyYicpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBwYXJzZUNvcmVEYW9PcFJldHVybk91dHB1dFNjcmlwdChCdWZmZXIuZnJvbShzY3JpcHQsICdoZXgnKSkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGlmIHRoZSBjaGFpbklkIGlzIGluY29ycmVjdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNjcmlwdCA9IGRlZmF1bHRTY3JpcHQucmVwbGFjZSgnMDQ1YicsICcwNDU0Jyk7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHBhcnNlQ29yZURhb09wUmV0dXJuT3V0cHV0U2NyaXB0KEJ1ZmZlci5mcm9tKHNjcmlwdCwgJ2hleCcpKSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=