@bitgo/sdk-core 36.44.0 → 37.1.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.
- package/dist/src/account-lib/baseCoin/enum.d.ts +22 -15
- package/dist/src/account-lib/baseCoin/enum.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/enum.js +30 -16
- package/dist/src/api/types.d.ts +12 -0
- package/dist/src/api/types.d.ts.map +1 -1
- package/dist/src/api/types.js +1 -1
- package/dist/src/bitgo/baseCoin/baseCoin.d.ts +1 -0
- package/dist/src/bitgo/baseCoin/baseCoin.d.ts.map +1 -1
- package/dist/src/bitgo/baseCoin/baseCoin.js +4 -1
- package/dist/src/bitgo/baseCoin/iBaseCoin.d.ts +11 -0
- package/dist/src/bitgo/baseCoin/iBaseCoin.d.ts.map +1 -1
- package/dist/src/bitgo/baseCoin/iBaseCoin.js +1 -1
- package/dist/src/bitgo/bitgoBase.d.ts +3 -1
- package/dist/src/bitgo/bitgoBase.d.ts.map +1 -1
- package/dist/src/bitgo/bitgoBase.js +1 -1
- package/dist/src/bitgo/environments.d.ts +1 -0
- package/dist/src/bitgo/environments.d.ts.map +1 -1
- package/dist/src/bitgo/environments.js +9 -1
- package/dist/src/bitgo/keychain/decryptKeychain.d.ts +12 -1
- package/dist/src/bitgo/keychain/decryptKeychain.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/decryptKeychain.js +34 -2
- package/dist/src/bitgo/keychain/iKeychains.d.ts +7 -1
- package/dist/src/bitgo/keychain/iKeychains.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/iKeychains.js +1 -1
- package/dist/src/bitgo/keychain/keychains.d.ts +19 -2
- package/dist/src/bitgo/keychain/keychains.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/keychains.js +74 -8
- package/dist/src/bitgo/trading/iTradingAccount.d.ts +13 -1
- package/dist/src/bitgo/trading/iTradingAccount.d.ts.map +1 -1
- package/dist/src/bitgo/trading/iTradingAccount.js +1 -1
- package/dist/src/bitgo/trading/network/network.d.ts +1 -1
- package/dist/src/bitgo/trading/network/network.d.ts.map +1 -1
- package/dist/src/bitgo/trading/network/network.js +3 -5
- package/dist/src/bitgo/trading/network/types.d.ts +1 -1
- package/dist/src/bitgo/trading/network/types.d.ts.map +1 -1
- package/dist/src/bitgo/trading/network/types.js +1 -1
- package/dist/src/bitgo/trading/tradingAccount.d.ts +15 -1
- package/dist/src/bitgo/trading/tradingAccount.d.ts.map +1 -1
- package/dist/src/bitgo/trading/tradingAccount.js +55 -7
- package/dist/src/bitgo/tss/common.d.ts +2 -1
- package/dist/src/bitgo/tss/common.d.ts.map +1 -1
- package/dist/src/bitgo/tss/common.js +10 -1
- package/dist/src/bitgo/tss/eddsa/eddsaMPCv2.d.ts +37 -0
- package/dist/src/bitgo/tss/eddsa/eddsaMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/tss/eddsa/eddsaMPCv2.js +95 -0
- package/dist/src/bitgo/utils/mpcUtils.d.ts +2 -1
- package/dist/src/bitgo/utils/mpcUtils.d.ts.map +1 -1
- package/dist/src/bitgo/utils/mpcUtils.js +8 -1
- package/dist/src/bitgo/utils/tss/addressVerification.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/addressVerification.js +10 -3
- package/dist/src/bitgo/utils/tss/baseTSSUtils.d.ts +38 -4
- package/dist/src/bitgo/utils/tss/baseTSSUtils.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/baseTSSUtils.js +66 -1
- package/dist/src/bitgo/utils/tss/baseTypes.d.ts +95 -17
- package/dist/src/bitgo/utils/tss/baseTypes.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/baseTypes.js +26 -2
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.d.ts +10 -7
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.js +39 -11
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts +14 -21
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.js +170 -104
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.d.ts +9 -6
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.js +96 -38
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts +34 -2
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.js +184 -6
- package/dist/src/bitgo/utils/txRequest.d.ts.map +1 -1
- package/dist/src/bitgo/utils/txRequest.js +6 -4
- package/dist/src/bitgo/wallet/BuildParams.d.ts +20 -0
- package/dist/src/bitgo/wallet/BuildParams.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/BuildParams.js +12 -2
- package/dist/src/bitgo/wallet/iWallet.d.ts +60 -2
- package/dist/src/bitgo/wallet/iWallet.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/iWallet.js +1 -1
- package/dist/src/bitgo/wallet/iWallets.d.ts +20 -19
- package/dist/src/bitgo/wallet/iWallets.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/iWallets.js +16 -8
- package/dist/src/bitgo/wallet/wallet.d.ts +84 -3
- package/dist/src/bitgo/wallet/wallet.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/wallet.js +347 -14
- package/dist/src/bitgo/wallet/wallets.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/wallets.js +49 -23
- package/dist/src/coins/ofc.d.ts +15 -1
- package/dist/src/coins/ofc.d.ts.map +1 -1
- package/dist/src/coins/ofc.js +8 -1
- package/dist/src/coins/ofcToken.d.ts +14 -4
- package/dist/src/coins/ofcToken.d.ts.map +1 -1
- package/dist/src/coins/ofcToken.js +17 -4
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -2
- package/dist/test/unit/bitgo/trading/tradingAccount.d.ts +2 -0
- package/dist/test/unit/bitgo/trading/tradingAccount.d.ts.map +1 -0
- package/dist/test/unit/bitgo/trading/tradingAccount.js +192 -0
- package/dist/test/unit/bitgo/utils/tss/addressVerification.js +119 -1
- package/dist/test/unit/bitgo/utils/tss/baseTSSUtils.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/baseTSSUtils.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/baseTSSUtils.js +305 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/ecdsaMPCv2.js +354 -1
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.js +442 -0
- package/dist/test/unit/bitgo/utils/txRequest.js +75 -1
- package/dist/test/unit/bitgo/wallet/ofcWalletSignTransaction.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/ofcWalletSignTransaction.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/ofcWalletSignTransaction.js +185 -0
- package/dist/test/unit/bitgo/wallet/resourceManagement.d.ts +3 -0
- package/dist/test/unit/bitgo/wallet/resourceManagement.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/resourceManagement.js +441 -0
- package/dist/test/unit/bitgo/wallet/walletOptionsCodecs.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletOptionsCodecs.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletOptionsCodecs.js +43 -0
- package/dist/test/unit/bitgo/wallet/walletTssAddressVerification.js +45 -1
- package/dist/test/unit/bitgo/wallet/walletsWebauthn.js +5 -2
- package/dist/test/unit/coins/ofc.d.ts +2 -0
- package/dist/test/unit/coins/ofc.d.ts.map +1 -0
- package/dist/test/unit/coins/ofc.js +124 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
|
@@ -36,10 +36,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
const assert = __importStar(require("assert"));
|
|
37
37
|
require("should");
|
|
38
38
|
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
|
|
39
|
+
const mpc_1 = require("../../../../../src/account-lib/mpc");
|
|
39
40
|
function getAddressVerificationModule() {
|
|
40
41
|
return require('../../../../../src/bitgo/utils/tss/addressVerification');
|
|
41
42
|
}
|
|
42
43
|
const getExtractCommonKeychain = () => getAddressVerificationModule().extractCommonKeychain;
|
|
44
|
+
const getVerifyEddsaTssWalletAddress = () => getAddressVerificationModule().verifyEddsaTssWalletAddress;
|
|
45
|
+
const getVerifyMPCWalletAddress = () => getAddressVerificationModule().verifyMPCWalletAddress;
|
|
46
|
+
// RFC 8032 test vector: known valid Ed25519 public key + arbitrary chaincode = 128 hex chars.
|
|
47
|
+
const TEST_PK = 'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a';
|
|
48
|
+
const TEST_CHAINCODE = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
|
|
49
|
+
const TEST_KEYCHAIN = TEST_PK + TEST_CHAINCODE;
|
|
50
|
+
// secp256k1 generator point G (compressed, 33 bytes = 66 hex) + same chaincode = 130 hex chars.
|
|
51
|
+
const ECDSA_PK = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798';
|
|
52
|
+
const ECDSA_KEYCHAIN = ECDSA_PK + TEST_CHAINCODE;
|
|
43
53
|
describe('TSS Address Verification - Derivation Path with Prefix', function () {
|
|
44
54
|
const commonKeychain = '8ea32ecacfc83effbd2e2790ee44fa7c59b4d86c29a12f09fb613d8195f93f4e21875cad3b98adada40c040c54c3569467df41a020881a6184096378701862bd';
|
|
45
55
|
describe('extractCommonKeychain', function () {
|
|
@@ -82,4 +92,112 @@ describe('TSS Address Verification - Derivation Path with Prefix', function () {
|
|
|
82
92
|
});
|
|
83
93
|
});
|
|
84
94
|
});
|
|
85
|
-
|
|
95
|
+
describe('verifyEddsaTssWalletAddress', function () {
|
|
96
|
+
const keychains = [
|
|
97
|
+
{ commonKeychain: TEST_KEYCHAIN },
|
|
98
|
+
{ commonKeychain: TEST_KEYCHAIN },
|
|
99
|
+
{ commonKeychain: TEST_KEYCHAIN },
|
|
100
|
+
];
|
|
101
|
+
const isValidAddress = (addr) => addr.length === 64;
|
|
102
|
+
const getAddressFromPublicKey = (pk) => pk;
|
|
103
|
+
describe('MPCv2 wallets (Silence Labs / MPS formula)', function () {
|
|
104
|
+
it('verifies a correct address derived with deriveUnhardenedMps at index 0', async function () {
|
|
105
|
+
const verifyEddsaTssWalletAddress = getVerifyEddsaTssWalletAddress();
|
|
106
|
+
const expectedAddress = (0, sdk_lib_mpc_1.deriveUnhardenedMps)(TEST_KEYCHAIN, 'm/0').slice(0, 64);
|
|
107
|
+
const result = await verifyEddsaTssWalletAddress({ address: expectedAddress, keychains, index: 0, multisigTypeVersion: 'MPCv2' }, isValidAddress, getAddressFromPublicKey);
|
|
108
|
+
result.should.be.true();
|
|
109
|
+
});
|
|
110
|
+
it('verifies a correct address derived with deriveUnhardenedMps at index 1', async function () {
|
|
111
|
+
const verifyEddsaTssWalletAddress = getVerifyEddsaTssWalletAddress();
|
|
112
|
+
const expectedAddress = (0, sdk_lib_mpc_1.deriveUnhardenedMps)(TEST_KEYCHAIN, 'm/1').slice(0, 64);
|
|
113
|
+
const result = await verifyEddsaTssWalletAddress({ address: expectedAddress, keychains, index: 1, multisigTypeVersion: 'MPCv2' }, isValidAddress, getAddressFromPublicKey);
|
|
114
|
+
result.should.be.true();
|
|
115
|
+
});
|
|
116
|
+
it('rejects an address derived at a different index', async function () {
|
|
117
|
+
const verifyEddsaTssWalletAddress = getVerifyEddsaTssWalletAddress();
|
|
118
|
+
const addressFromIndex0 = (0, sdk_lib_mpc_1.deriveUnhardenedMps)(TEST_KEYCHAIN, 'm/0').slice(0, 64);
|
|
119
|
+
const result = await verifyEddsaTssWalletAddress({ address: addressFromIndex0, keychains, index: 1, multisigTypeVersion: 'MPCv2' }, isValidAddress, getAddressFromPublicKey);
|
|
120
|
+
result.should.be.false();
|
|
121
|
+
});
|
|
122
|
+
it('rejects a random address that was not derived from the keychain', async function () {
|
|
123
|
+
const verifyEddsaTssWalletAddress = getVerifyEddsaTssWalletAddress();
|
|
124
|
+
const randomAddress = 'ab'.repeat(32); // 64 hex chars, wrong address
|
|
125
|
+
const result = await verifyEddsaTssWalletAddress({ address: randomAddress, keychains, index: 0, multisigTypeVersion: 'MPCv2' }, isValidAddress, getAddressFromPublicKey);
|
|
126
|
+
result.should.be.false();
|
|
127
|
+
});
|
|
128
|
+
it('verifies a correct MPCv2 address for SMC wallet using derivedFromParentWithSeed', async function () {
|
|
129
|
+
const verifyEddsaTssWalletAddress = getVerifyEddsaTssWalletAddress();
|
|
130
|
+
const seed = 'smc-seed-123';
|
|
131
|
+
const prefix = (0, sdk_lib_mpc_1.getDerivationPath)(seed);
|
|
132
|
+
const expectedAddress = (0, sdk_lib_mpc_1.deriveUnhardenedMps)(TEST_KEYCHAIN, `${prefix}/0`).slice(0, 64);
|
|
133
|
+
const result = await verifyEddsaTssWalletAddress({
|
|
134
|
+
address: expectedAddress,
|
|
135
|
+
keychains,
|
|
136
|
+
index: 0,
|
|
137
|
+
multisigTypeVersion: 'MPCv2',
|
|
138
|
+
derivedFromParentWithSeed: seed,
|
|
139
|
+
}, isValidAddress, getAddressFromPublicKey);
|
|
140
|
+
result.should.be.true();
|
|
141
|
+
});
|
|
142
|
+
it('rejects an MPCv2 address derived at the wrong index when derivedFromParentWithSeed is set', async function () {
|
|
143
|
+
const verifyEddsaTssWalletAddress = getVerifyEddsaTssWalletAddress();
|
|
144
|
+
const seed = 'smc-seed-123';
|
|
145
|
+
const prefix = (0, sdk_lib_mpc_1.getDerivationPath)(seed);
|
|
146
|
+
const addressAtIndex1 = (0, sdk_lib_mpc_1.deriveUnhardenedMps)(TEST_KEYCHAIN, `${prefix}/1`).slice(0, 64);
|
|
147
|
+
const result = await verifyEddsaTssWalletAddress({
|
|
148
|
+
address: addressAtIndex1,
|
|
149
|
+
keychains,
|
|
150
|
+
index: 0,
|
|
151
|
+
multisigTypeVersion: 'MPCv2',
|
|
152
|
+
derivedFromParentWithSeed: seed,
|
|
153
|
+
}, isValidAddress, getAddressFromPublicKey);
|
|
154
|
+
result.should.be.false();
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
describe('non-MPCv2 wallets (MPCv1 formula)', function () {
|
|
158
|
+
it('rejects an MPCv2-derived address when multisigTypeVersion is not set', async function () {
|
|
159
|
+
const verifyEddsaTssWalletAddress = getVerifyEddsaTssWalletAddress();
|
|
160
|
+
// MPCv2 (Silence Labs) and MPCv1 formulas produce different addresses for the same keychain.
|
|
161
|
+
// Without multisigTypeVersion: 'MPCv2', the MPCv1 formula is used, so the MPCv2-derived
|
|
162
|
+
// address should not match.
|
|
163
|
+
const mpcv2Address = (0, sdk_lib_mpc_1.deriveUnhardenedMps)(TEST_KEYCHAIN, 'm/0').slice(0, 64);
|
|
164
|
+
const result = await verifyEddsaTssWalletAddress({ address: mpcv2Address, keychains, index: 0 }, isValidAddress, getAddressFromPublicKey);
|
|
165
|
+
result.should.be.false();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
describe('verifyMPCWalletAddress - ECDSA (secp256k1)', function () {
|
|
170
|
+
const ecdsaKeychains = [
|
|
171
|
+
{ commonKeychain: ECDSA_KEYCHAIN },
|
|
172
|
+
{ commonKeychain: ECDSA_KEYCHAIN },
|
|
173
|
+
{ commonKeychain: ECDSA_KEYCHAIN },
|
|
174
|
+
];
|
|
175
|
+
// secp256k1 compressed public key is 33 bytes = 66 hex chars
|
|
176
|
+
const isValidEcdsaAddress = (addr) => addr.length === 66;
|
|
177
|
+
const getAddressFromPublicKey = (pk) => pk;
|
|
178
|
+
it('ignores multisigTypeVersion MPCv2 and uses Ecdsa derivation for secp256k1 wallets', async function () {
|
|
179
|
+
const verifyMPCWalletAddress = getVerifyMPCWalletAddress();
|
|
180
|
+
const expectedAddress = new mpc_1.Ecdsa().deriveUnhardened(ECDSA_KEYCHAIN, 'm/0').slice(0, 66);
|
|
181
|
+
const result = await verifyMPCWalletAddress({
|
|
182
|
+
address: expectedAddress,
|
|
183
|
+
keychains: ecdsaKeychains,
|
|
184
|
+
index: 0,
|
|
185
|
+
multisigTypeVersion: 'MPCv2',
|
|
186
|
+
keyCurve: 'secp256k1',
|
|
187
|
+
}, isValidEcdsaAddress, getAddressFromPublicKey);
|
|
188
|
+
result.should.be.true();
|
|
189
|
+
});
|
|
190
|
+
it('verifies a correct secp256k1 address at index 1', async function () {
|
|
191
|
+
const verifyMPCWalletAddress = getVerifyMPCWalletAddress();
|
|
192
|
+
const expectedAddress = new mpc_1.Ecdsa().deriveUnhardened(ECDSA_KEYCHAIN, 'm/1').slice(0, 66);
|
|
193
|
+
const result = await verifyMPCWalletAddress({ address: expectedAddress, keychains: ecdsaKeychains, index: 1, keyCurve: 'secp256k1' }, isValidEcdsaAddress, getAddressFromPublicKey);
|
|
194
|
+
result.should.be.true();
|
|
195
|
+
});
|
|
196
|
+
it('rejects an address derived at a different index', async function () {
|
|
197
|
+
const verifyMPCWalletAddress = getVerifyMPCWalletAddress();
|
|
198
|
+
const addressAtIndex0 = new mpc_1.Ecdsa().deriveUnhardened(ECDSA_KEYCHAIN, 'm/0').slice(0, 66);
|
|
199
|
+
const result = await verifyMPCWalletAddress({ address: addressAtIndex0, keychains: ecdsaKeychains, index: 1, keyCurve: 'secp256k1' }, isValidEcdsaAddress, getAddressFromPublicKey);
|
|
200
|
+
result.should.be.false();
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRkcmVzc1ZlcmlmaWNhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9iaXRnby91dGlscy90c3MvYWRkcmVzc1ZlcmlmaWNhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtDQUFpQztBQUNqQyxrQkFBZ0I7QUFDaEIsb0RBQTRFO0FBQzVFLDREQUEyRDtBQUUzRCxTQUFTLDRCQUE0QjtJQUNuQyxPQUFPLE9BQU8sQ0FBQyx3REFBd0QsQ0FBQyxDQUFDO0FBQzNFLENBQUM7QUFFRCxNQUFNLHdCQUF3QixHQUFHLEdBQUcsRUFBRSxDQUFDLDRCQUE0QixFQUFFLENBQUMscUJBQXFCLENBQUM7QUFDNUYsTUFBTSw4QkFBOEIsR0FBRyxHQUFHLEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxDQUFDLDJCQUEyQixDQUFDO0FBQ3hHLE1BQU0seUJBQXlCLEdBQUcsR0FBRyxFQUFFLENBQUMsNEJBQTRCLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQztBQUU5Riw4RkFBOEY7QUFDOUYsTUFBTSxPQUFPLEdBQUcsa0VBQWtFLENBQUM7QUFDbkYsTUFBTSxjQUFjLEdBQUcsa0VBQWtFLENBQUM7QUFDMUYsTUFBTSxhQUFhLEdBQUcsT0FBTyxHQUFHLGNBQWMsQ0FBQztBQUUvQyxnR0FBZ0c7QUFDaEcsTUFBTSxRQUFRLEdBQUcsb0VBQW9FLENBQUM7QUFDdEYsTUFBTSxjQUFjLEdBQUcsUUFBUSxHQUFHLGNBQWMsQ0FBQztBQUVqRCxRQUFRLENBQUMsd0RBQXdELEVBQUU7SUFDakUsTUFBTSxjQUFjLEdBQ2xCLGtJQUFrSSxDQUFDO0lBRXJJLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRTtRQUNoQyxFQUFFLENBQUMsb0RBQW9ELEVBQUU7WUFDdkQsTUFBTSxxQkFBcUIsR0FBRyx3QkFBd0IsRUFBRSxDQUFDO1lBQ3pELE1BQU0sU0FBUyxH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RSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRXpGLE1BQU0sTUFBTSxHQUFHLE1BQU0sc0JBQXNCLENBQ3pDLEVBQUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxFQUN4RixtQkFBbUIsRUFDbkIsdUJBQXVCLENBQ3hCLENBQUM7UUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUMzQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgJ3Nob3VsZCc7XG5pbXBvcnQgeyBkZXJpdmVVbmhhcmRlbmVkTXBzLCBnZXREZXJpdmF0aW9uUGF0aCB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5pbXBvcnQgeyBFY2RzYSB9IGZyb20gJy4uLy4uLy4uLy4uLy4uL3NyYy9hY2NvdW50LWxpYi9tcGMnO1xuXG5mdW5jdGlvbiBnZXRBZGRyZXNzVmVyaWZpY2F0aW9uTW9kdWxlKCkge1xuICByZXR1cm4gcmVxdWlyZSgnLi4vLi4vLi4vLi4vLi4vc3JjL2JpdGdvL3V0aWxzL3Rzcy9hZGRyZXNzVmVyaWZpY2F0aW9uJyk7XG59XG5cbmNvbnN0IGdldEV4dHJhY3RDb21tb25LZXljaGFpbiA9ICgpID0+IGdldEFkZHJlc3NWZXJpZmljYXRpb25Nb2R1bGUoKS5leHRyYWN0Q29tbW9uS2V5Y2hhaW47XG5jb25zdCBnZXRWZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MgPSAoKSA9PiBnZXRBZGRyZXNzVmVyaWZpY2F0aW9uTW9kdWxlKCkudmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzO1xuY29uc3QgZ2V0VmVyaWZ5TVBDV2FsbGV0QWRkcmVzcyA9ICgpID0+IGdldEFkZHJlc3NWZXJpZmljYXRpb25Nb2R1bGUoKS52ZXJpZnlNUENXYWxsZXRBZGRyZXNzO1xuXG4vLyBSRkMgODAzMiB0ZXN0IHZlY3Rvcjoga25vd24gdmFsaWQgRWQyNTUxOSBwdWJsaWMga2V5ICsgYXJiaXRyYXJ5IGNoYWluY29kZSA9IDEyOCBoZXggY2hhcnMuXG5jb25zdCBURVNUX1BLID0gJ2Q3NWE5ODAxODJiMTBhYjdkNTRiZmVkM2M5NjQwNzNhMGVlMTcyZjNkYWE2MjMyNWFmMDIxYTY4ZjcwNzUxMWEnO1xuY29uc3QgVEVTVF9DSEFJTkNPREUgPSAnZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZic7XG5jb25zdCBURVNUX0tFWUNIQUlOID0gVEVTVF9QSyArIFRFU1RfQ0hBSU5DT0RFO1xuXG4vLyBzZWNwMjU2azEgZ2VuZXJhdG9yIHBvaW50IEcgKGNvbXByZXNzZWQsIDMzIGJ5dGVzID0gNjYgaGV4KSArIHNhbWUgY2hhaW5jb2RlID0gMTMwIGhleCBjaGFycy5cbmNvbnN0IEVDRFNBX1BLID0gJzAyNzliZTY2N2VmOWRjYmJhYzU1YTA2Mjk1Y2U4NzBiMDcwMjliZmNkYjJkY2UyOGQ5NTlmMjgxNWIxNmY4MTc5OCc7XG5jb25zdCBFQ0RTQV9LRVlDSEFJTiA9IEVDRFNBX1BLICsgVEVTVF9DSEFJTkNPREU7XG5cbmRlc2NyaWJlKCdUU1MgQWRkcmVzcyBWZXJpZmljYXRpb24gLSBEZXJpdmF0aW9uIFBhdGggd2l0aCBQcmVmaXgnLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGNvbW1vbktleWNoYWluID1cbiAgICAnOGVhMzJlY2FjZmM4M2VmZmJkMmUyNzkwZWU0NGZhN2M1OWI0ZDg2YzI5YTEyZjA5ZmI2MTNkODE5NWY5M2Y0ZTIxODc1Y2FkM2I5OGFkYWRhNDBjMDQwYzU0YzM1Njk0NjdkZjQxYTAyMDg4MWE2MTg0MDk2Mzc4NzAxODYyYmQnO1xuXG4gIGRlc2NyaWJlKCdleHRyYWN0Q29tbW9uS2V5Y2hhaW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBleHRyYWN0IGNvbW1vbktleWNoYWluIGZyb20ga2V5Y2hhaW5zIGFycmF5JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZXh0cmFjdENvbW1vbktleWNoYWluID0gZ2V0RXh0cmFjdENvbW1vbktleWNoYWluKCk7XG4gICAgICBjb25zdCBrZXljaGFpbnMgPSBbeyBjb21tb25LZXljaGFpbiB9LCB7IGNvbW1vbktleWNoYWluIH0sIHsgY29tbW9uS2V5Y2hhaW4gfV07XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGV4dHJhY3RDb21tb25LZXljaGFpbihrZXljaGFpbnMpO1xuICAgICAgcmVzdWx0LnNob3VsZC5lcXVhbChjb21tb25LZXljaGFpbik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGVycm9yIGlmIGtleWNoYWlucyBhcmUgbWlzc2luZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4dHJhY3RDb21tb25LZXljaGFpbiA9IGdldEV4dHJhY3RDb21tb25LZXljaGFpbigpO1xuICAgICAgYXNzZXJ0LnRocm93cygoKSA9PiBleHRyYWN0Q29tbW9uS2V5Y2hhaW4oW10pLCAvbWlzc2luZyByZXF1aXJlZCBwYXJhbSBrZXljaGFpbnMvKTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gZXh0cmFjdENvbW1vbktleWNoYWluKHVuZGVmaW5lZCBhcyBhbnkpLCAvbWlzc2luZyByZXF1aXJlZCBwYXJhbSBrZXljaGFpbnMvKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgaWYgY29tbW9uS2V5Y2hhaW4gaXMgbWlzc2luZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4dHJhY3RDb21tb25LZXljaGFpbiA9IGdldEV4dHJhY3RDb21tb25LZXljaGFpbigpO1xuICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW3sgaWQ6ICcxJyB9XTtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gZXh0cmFjdENvbW1vbktleWNoYWluKGtleWNoYWlucyBhcyBhbnkpLCAvbWlzc2luZyByZXF1aXJlZCBwYXJhbSBjb21tb25LZXljaGFpbi8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBlcnJvciBpZiBrZXljaGFpbnMgaGF2ZSBtaXNtYXRjaGVkIGNvbW1vbktleWNoYWlucycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGV4dHJhY3RDb21tb25LZXljaGFpbiA9IGdldEV4dHJhY3RDb21tb25LZXljaGFpbigpO1xuICAgICAgY29uc3Qga2V5Y2hhaW5zID0gW3sgY29tbW9uS2V5Y2hhaW4gfSwgeyBjb21tb25LZXljaGFpbjogJ2RpZmZlcmVudC1rZXljaGFpbicgfV07XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IGV4dHJhY3RDb21tb25LZXljaGFpbihrZXljaGFpbnMpLCAvYWxsIGtleWNoYWlucyBtdXN0IGhhdmUgdGhlIHNhbWUgY29tbW9uS2V5Y2hhaW4vKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0Rlcml2YXRpb24gUGF0aCBGb3JtYXQgVmFsaWRhdGlvbicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHByb2R1Y2UgY29ycmVjdCBkZXJpdmF0aW9uIHBhdGggZm9ybWF0JywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdGVzdFNlZWRzID0gWydzZWVkMScsICdzZWVkLTInLCAnMTIzNDUnLCAndGVzdF9zZWVkXzEyMyddO1xuXG4gICAgICB0ZXN0U2VlZHMuZm9yRWFjaCgoc2VlZCkgPT4ge1xuICAgICAgICBjb25zdCBwYXRoID0gZ2V0RGVyaXZhdGlvblBhdGgoc2VlZCk7XG5cbiAgICAgICAgLy8gRXhwZWN0ZWQgZm9ybWF0OiBcIm0vOTk5OTk5L3twYXJ0MX0ve3BhcnQyfVwiXG4gICAgICAgIHBhdGguc2hvdWxkLm1hdGNoKC9ebVxcLzk5OTk5OVxcL1xcZCtcXC9cXGQrJC8pO1xuXG4gICAgICAgIHBhdGguc2hvdWxkLnN0YXJ0V2l0aCgnbS8nKTtcblxuICAgICAgICAvLyBTaG91bGQgaGF2ZSBleGFjdGx5IDMgcGFydHNcbiAgICAgICAgY29uc3QgcGFydHMgPSBwYXRoLnNwbGl0KCcvJyk7XG4gICAgICAgIHBhcnRzLmxlbmd0aC5zaG91bGQuZXF1YWwoNCk7XG4gICAgICAgIHBhcnRzWzBdLnNob3VsZC5lcXVhbCgnbScpO1xuICAgICAgICBwYXJ0c1sxXS5zaG91bGQuZXF1YWwoJzk5OTk5OScpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCd2ZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGtleWNoYWlucyA9IFtcbiAgICB7IGNvbW1vbktleWNoYWluOiBURVNUX0tFWUNIQUlOIH0sXG4gICAgeyBjb21tb25LZXljaGFpbjogVEVTVF9LRVlDSEFJTiB9LFxuICAgIHsgY29tbW9uS2V5Y2hhaW46IFRFU1RfS0VZQ0hBSU4gfSxcbiAgXTtcbiAgY29uc3QgaXNWYWxpZEFkZHJlc3MgPSAoYWRkcjogc3RyaW5nKSA9PiBhZGRyLmxlbmd0aCA9PT0gNjQ7XG4gIGNvbnN0IGdldEFkZHJlc3NGcm9tUHVibGljS2V5ID0gKHBrOiBzdHJpbmcpID0+IHBrO1xuXG4gIGRlc2NyaWJlKCdNUEN2MiB3YWxsZXRzIChTaWxlbmNlIExhYnMgLyBNUFMgZm9ybXVsYSknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3ZlcmlmaWVzIGEgY29ycmVjdCBhZGRyZXNzIGRlcml2ZWQgd2l0aCBkZXJpdmVVbmhhcmRlbmVkTXBzIGF0IGluZGV4IDAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2ZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MgPSBnZXRWZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MoKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkQWRkcmVzcyA9IGRlcml2ZVVuaGFyZGVuZWRNcHMoVEVTVF9LRVlDSEFJTiwgJ20vMCcpLnNsaWNlKDAsIDY0KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzKFxuICAgICAgICB7IGFkZHJlc3M6IGV4cGVjdGVkQWRkcmVzcywga2V5Y2hhaW5zLCBpbmRleDogMCwgbXVsdGlzaWdUeXBlVmVyc2lvbjogJ01QQ3YyJyB9LFxuICAgICAgICBpc1ZhbGlkQWRkcmVzcyxcbiAgICAgICAgZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXlcbiAgICAgICk7XG4gICAgICByZXN1bHQuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCd2ZXJpZmllcyBhIGNvcnJlY3QgYWRkcmVzcyBkZXJpdmVkIHdpdGggZGVyaXZlVW5oYXJkZW5lZE1wcyBhdCBpbmRleCAxJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzID0gZ2V0VmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzKCk7XG4gICAgICBjb25zdCBleHBlY3RlZEFkZHJlc3MgPSBkZXJpdmVVbmhhcmRlbmVkTXBzKFRFU1RfS0VZQ0hBSU4sICdtLzEnKS5zbGljZSgwLCA2NCk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZlcmlmeUVkZHNhVHNzV2FsbGV0QWRkcmVzcyhcbiAgICAgICAgeyBhZGRyZXNzOiBleHBlY3RlZEFkZHJlc3MsIGtleWNoYWlucywgaW5kZXg6IDEsIG11bHRpc2lnVHlwZVZlcnNpb246ICdNUEN2MicgfSxcbiAgICAgICAgaXNWYWxpZEFkZHJlc3MsXG4gICAgICAgIGdldEFkZHJlc3NGcm9tUHVibGljS2V5XG4gICAgICApO1xuICAgICAgcmVzdWx0LnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyBhbiBhZGRyZXNzIGRlcml2ZWQgYXQgYSBkaWZmZXJlbnQgaW5kZXgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2ZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MgPSBnZXRWZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MoKTtcbiAgICAgIGNvbnN0IGFkZHJlc3NGcm9tSW5kZXgwID0gZGVyaXZlVW5oYXJkZW5lZE1wcyhURVNUX0tFWUNIQUlOLCAnbS8wJykuc2xpY2UoMCwgNjQpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB2ZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MoXG4gICAgICAgIHsgYWRkcmVzczogYWRkcmVzc0Zyb21JbmRleDAsIGtleWNoYWlucywgaW5kZXg6IDEsIG11bHRpc2lnVHlwZVZlcnNpb246ICdNUEN2MicgfSxcbiAgICAgICAgaXNWYWxpZEFkZHJlc3MsXG4gICAgICAgIGdldEFkZHJlc3NGcm9tUHVibGljS2V5XG4gICAgICApO1xuICAgICAgcmVzdWx0LnNob3VsZC5iZS5mYWxzZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JlamVjdHMgYSByYW5kb20gYWRkcmVzcyB0aGF0IHdhcyBub3QgZGVyaXZlZCBmcm9tIHRoZSBrZXljaGFpbicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHZlcmlmeUVkZHNhVHNzV2FsbGV0QWRkcmVzcyA9IGdldFZlcmlmeUVkZHNhVHNzV2FsbGV0QWRkcmVzcygpO1xuICAgICAgY29uc3QgcmFuZG9tQWRkcmVzcyA9ICdhYicucmVwZWF0KDMyKTsgLy8gNjQgaGV4IGNoYXJzLCB3cm9uZyBhZGRyZXNzXG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZlcmlmeUVkZHNhVHNzV2FsbGV0QWRkcmVzcyhcbiAgICAgICAgeyBhZGRyZXNzOiByYW5kb21BZGRyZXNzLCBrZXljaGFpbnMsIGluZGV4OiAwLCBtdWx0aXNpZ1R5cGVWZXJzaW9uOiAnTVBDdjInIH0sXG4gICAgICAgIGlzVmFsaWRBZGRyZXNzLFxuICAgICAgICBnZXRBZGRyZXNzRnJvbVB1YmxpY0tleVxuICAgICAgKTtcbiAgICAgIHJlc3VsdC5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcblxuICAgIGl0KCd2ZXJpZmllcyBhIGNvcnJlY3QgTVBDdjIgYWRkcmVzcyBmb3IgU01DIHdhbGxldCB1c2luZyBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzID0gZ2V0VmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzKCk7XG4gICAgICBjb25zdCBzZWVkID0gJ3NtYy1zZWVkLTEyMyc7XG4gICAgICBjb25zdCBwcmVmaXggPSBnZXREZXJpdmF0aW9uUGF0aChzZWVkKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkQWRkcmVzcyA9IGRlcml2ZVVuaGFyZGVuZWRNcHMoVEVTVF9LRVlDSEFJTiwgYCR7cHJlZml4fS8wYCkuc2xpY2UoMCwgNjQpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB2ZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MoXG4gICAgICAgIHtcbiAgICAgICAgICBhZGRyZXNzOiBleHBlY3RlZEFkZHJlc3MsXG4gICAgICAgICAga2V5Y2hhaW5zLFxuICAgICAgICAgIGluZGV4OiAwLFxuICAgICAgICAgIG11bHRpc2lnVHlwZVZlcnNpb246ICdNUEN2MicsXG4gICAgICAgICAgZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZDogc2VlZCxcbiAgICAgICAgfSxcbiAgICAgICAgaXNWYWxpZEFkZHJlc3MsXG4gICAgICAgIGdldEFkZHJlc3NGcm9tUHVibGljS2V5XG4gICAgICApO1xuICAgICAgcmVzdWx0LnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyBhbiBNUEN2MiBhZGRyZXNzIGRlcml2ZWQgYXQgdGhlIHdyb25nIGluZGV4IHdoZW4gZGVyaXZlZEZyb21QYXJlbnRXaXRoU2VlZCBpcyBzZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2ZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MgPSBnZXRWZXJpZnlFZGRzYVRzc1dhbGxldEFkZHJlc3MoKTtcbiAgICAgIGNvbnN0IHNlZWQgPSAnc21jLXNlZWQtMTIzJztcbiAgICAgIGNvbnN0IHByZWZpeCA9IGdldERlcml2YXRpb25QYXRoKHNlZWQpO1xuICAgICAgY29uc3QgYWRkcmVzc0F0SW5kZXgxID0gZGVyaXZlVW5oYXJkZW5lZE1wcyhURVNUX0tFWUNIQUlOLCBgJHtwcmVmaXh9LzFgKS5zbGljZSgwLCA2NCk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZlcmlmeUVkZHNhVHNzV2FsbGV0QWRkcmVzcyhcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IGFkZHJlc3NBdEluZGV4MSxcbiAgICAgICAgICBrZXljaGFpbnMsXG4gICAgICAgICAgaW5kZXg6IDAsXG4gICAgICAgICAgbXVsdGlzaWdUeXBlVmVyc2lvbjogJ01QQ3YyJyxcbiAgICAgICAgICBkZXJpdmVkRnJvbVBhcmVudFdpdGhTZWVkOiBzZWVkLFxuICAgICAgICB9LFxuICAgICAgICBpc1ZhbGlkQWRkcmVzcyxcbiAgICAgICAgZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXlcbiAgICAgICk7XG4gICAgICByZXN1bHQuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdub24tTVBDdjIgd2FsbGV0cyAoTVBDdjEgZm9ybXVsYSknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3JlamVjdHMgYW4gTVBDdjItZGVyaXZlZCBhZGRyZXNzIHdoZW4gbXVsdGlzaWdUeXBlVmVyc2lvbiBpcyBub3Qgc2V0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzID0gZ2V0VmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzKCk7XG4gICAgICAvLyBNUEN2MiAoU2lsZW5jZSBMYWJzKSBhbmQgTVBDdjEgZm9ybXVsYXMgcHJvZHVjZSBkaWZmZXJlbnQgYWRkcmVzc2VzIGZvciB0aGUgc2FtZSBrZXljaGFpbi5cbiAgICAgIC8vIFdpdGhvdXQgbXVsdGlzaWdUeXBlVmVyc2lvbjogJ01QQ3YyJywgdGhlIE1QQ3YxIGZvcm11bGEgaXMgdXNlZCwgc28gdGhlIE1QQ3YyLWRlcml2ZWRcbiAgICAgIC8vIGFkZHJlc3Mgc2hvdWxkIG5vdCBtYXRjaC5cbiAgICAgIGNvbnN0IG1wY3YyQWRkcmVzcyA9IGRlcml2ZVVuaGFyZGVuZWRNcHMoVEVTVF9LRVlDSEFJTiwgJ20vMCcpLnNsaWNlKDAsIDY0KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdmVyaWZ5RWRkc2FUc3NXYWxsZXRBZGRyZXNzKFxuICAgICAgICB7IGFkZHJlc3M6IG1wY3YyQWRkcmVzcywga2V5Y2hhaW5zLCBpbmRleDogMCB9LFxuICAgICAgICBpc1ZhbGlkQWRkcmVzcyxcbiAgICAgICAgZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXlcbiAgICAgICk7XG5cbiAgICAgIHJlc3VsdC5zaG91bGQuYmUuZmFsc2UoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ3ZlcmlmeU1QQ1dhbGxldEFkZHJlc3MgLSBFQ0RTQSAoc2VjcDI1NmsxKScsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgZWNkc2FLZXljaGFpbnMgPSBbXG4gICAgeyBjb21tb25LZXljaGFpbjogRUNEU0FfS0VZQ0hBSU4gfSxcbiAgICB7IGNvbW1vbktleWNoYWluOiBFQ0RTQV9LRVlDSEFJTiB9LFxuICAgIHsgY29tbW9uS2V5Y2hhaW46IEVDRFNBX0tFWUNIQUlOIH0sXG4gIF07XG4gIC8vIHNlY3AyNTZrMSBjb21wcmVzc2VkIHB1YmxpYyBrZXkgaXMgMzMgYnl0ZXMgPSA2NiBoZXggY2hhcnNcbiAgY29uc3QgaXNWYWxpZEVjZHNhQWRkcmVzcyA9IChhZGRyOiBzdHJpbmcpID0+IGFkZHIubGVuZ3RoID09PSA2NjtcbiAgY29uc3QgZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkgPSAocGs6IHN0cmluZykgPT4gcGs7XG5cbiAgaXQoJ2lnbm9yZXMgbXVsdGlzaWdUeXBlVmVyc2lvbiBNUEN2MiBhbmQgdXNlcyBFY2RzYSBkZXJpdmF0aW9uIGZvciBzZWNwMjU2azEgd2FsbGV0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB2ZXJpZnlNUENXYWxsZXRBZGRyZXNzID0gZ2V0VmVyaWZ5TVBDV2FsbGV0QWRkcmVzcygpO1xuICAgIGNvbnN0IGV4cGVjdGVkQWRkcmVzcyA9IG5ldyBFY2RzYSgpLmRlcml2ZVVuaGFyZGVuZWQoRUNEU0FfS0VZQ0hBSU4sICdtLzAnKS5zbGljZSgwLCA2Nik7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB2ZXJpZnlNUENXYWxsZXRBZGRyZXNzKFxuICAgICAge1xuICAgICAgICBhZGRyZXNzOiBleHBlY3RlZEFkZHJlc3MsXG4gICAgICAgIGtleWNoYWluczogZWNkc2FLZXljaGFpbnMsXG4gICAgICAgIGluZGV4OiAwLFxuICAgICAgICBtdWx0aXNpZ1R5cGVWZXJzaW9uOiAnTVBDdjInLFxuICAgICAgICBrZXlDdXJ2ZTogJ3NlY3AyNTZrMScsXG4gICAgICB9LFxuICAgICAgaXNWYWxpZEVjZHNhQWRkcmVzcyxcbiAgICAgIGdldEFkZHJlc3NGcm9tUHVibGljS2V5XG4gICAgKTtcbiAgICByZXN1bHQuc2hvdWxkLmJlLnRydWUoKTtcbiAgfSk7XG5cbiAgaXQoJ3ZlcmlmaWVzIGEgY29ycmVjdCBzZWNwMjU2azEgYWRkcmVzcyBhdCBpbmRleCAxJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHZlcmlmeU1QQ1dhbGxldEFkZHJlc3MgPSBnZXRWZXJpZnlNUENXYWxsZXRBZGRyZXNzKCk7XG4gICAgY29uc3QgZXhwZWN0ZWRBZGRyZXNzID0gbmV3IEVjZHNhKCkuZGVyaXZlVW5oYXJkZW5lZChFQ0RTQV9LRVlDSEFJTiwgJ20vMScpLnNsaWNlKDAsIDY2KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZlcmlmeU1QQ1dhbGxldEFkZHJlc3MoXG4gICAgICB7IGFkZHJlc3M6IGV4cGVjdGVkQWRkcmVzcywga2V5Y2hhaW5zOiBlY2RzYUtleWNoYWlucywgaW5kZXg6IDEsIGtleUN1cnZlOiAnc2VjcDI1NmsxJyB9LFxuICAgICAgaXNWYWxpZEVjZHNhQWRkcmVzcyxcbiAgICAgIGdldEFkZHJlc3NGcm9tUHVibGljS2V5XG4gICAgKTtcbiAgICByZXN1bHQuc2hvdWxkLmJlLnRydWUoKTtcbiAgfSk7XG5cbiAgaXQoJ3JlamVjdHMgYW4gYWRkcmVzcyBkZXJpdmVkIGF0IGEgZGlmZmVyZW50IGluZGV4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHZlcmlmeU1QQ1dhbGxldEFkZHJlc3MgPSBnZXRWZXJpZnlNUENXYWxsZXRBZGRyZXNzKCk7XG4gICAgY29uc3QgYWRkcmVzc0F0SW5kZXgwID0gbmV3IEVjZHNhKCkuZGVyaXZlVW5oYXJkZW5lZChFQ0RTQV9LRVlDSEFJTiwgJ20vMCcpLnNsaWNlKDAsIDY2KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZlcmlmeU1QQ1dhbGxldEFkZHJlc3MoXG4gICAgICB7IGFkZHJlc3M6IGFkZHJlc3NBdEluZGV4MCwga2V5Y2hhaW5zOiBlY2RzYUtleWNoYWlucywgaW5kZXg6IDEsIGtleUN1cnZlOiAnc2VjcDI1NmsxJyB9LFxuICAgICAgaXNWYWxpZEVjZHNhQWRkcmVzcyxcbiAgICAgIGdldEFkZHJlc3NGcm9tUHVibGljS2V5XG4gICAgKTtcbiAgICByZXN1bHQuc2hvdWxkLmJlLmZhbHNlKCk7XG4gIH0pO1xufSk7XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseTSSUtils.d.ts","sourceRoot":"","sources":["../../../../../../test/unit/bitgo/utils/tss/baseTSSUtils.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,305 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const assert = __importStar(require("assert"));
|
|
40
|
+
const crypto_1 = require("crypto");
|
|
41
|
+
const keccak_1 = __importDefault(require("keccak"));
|
|
42
|
+
const openpgp = __importStar(require("openpgp"));
|
|
43
|
+
const sinon = __importStar(require("sinon"));
|
|
44
|
+
const sjcl = __importStar(require("@bitgo/sjcl"));
|
|
45
|
+
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
|
|
46
|
+
const src_1 = require("../../../../../src");
|
|
47
|
+
const baseTSSUtils_1 = __importDefault(require("../../../../../src/bitgo/utils/tss/baseTSSUtils"));
|
|
48
|
+
class TestBaseTssUtils extends baseTSSUtils_1.default {
|
|
49
|
+
getSignableHexAndDerivationPathForTest(txRequest, missingTransactionsMessage) {
|
|
50
|
+
return this.getSignableHexAndDerivationPath(txRequest, missingTransactionsMessage);
|
|
51
|
+
}
|
|
52
|
+
validateAdataForTest(adata, cyphertext, roundDomainSeparator) {
|
|
53
|
+
this.validateAdata(adata, cyphertext, roundDomainSeparator);
|
|
54
|
+
}
|
|
55
|
+
getBitgoAndUserGpgKeysForTest(bitgoPublicGpgKey, encryptedUserGpgPrvKey, walletPassphrase, adata, userGpgKeyDomainSeparator) {
|
|
56
|
+
return this.getBitgoAndUserGpgKeys(bitgoPublicGpgKey, encryptedUserGpgPrvKey, walletPassphrase, adata, userGpgKeyDomainSeparator);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
describe('Base TSS Utils', function () {
|
|
60
|
+
const walletPassphrase = 'test-password';
|
|
61
|
+
const signingUserGpgKeyDomainSeparator = 'MPS_DSG_SIGNING_USER_GPG_KEY';
|
|
62
|
+
const roundOneDomainSeparator = 'MPS_DSG_SIGNING_ROUND1_STATE';
|
|
63
|
+
let baseTssUtils;
|
|
64
|
+
let ecdsaMPCv2Utils;
|
|
65
|
+
let mockBitgo;
|
|
66
|
+
let decryptAsyncStub;
|
|
67
|
+
let bitgoGpgKeyPair;
|
|
68
|
+
let userGpgKeyPair;
|
|
69
|
+
let userShare;
|
|
70
|
+
before(async function () {
|
|
71
|
+
openpgp.config.rejectCurves = new Set();
|
|
72
|
+
bitgoGpgKeyPair = await openpgp.generateKey({
|
|
73
|
+
userIDs: [{ name: 'bitgo', email: 'bitgo@test.com' }],
|
|
74
|
+
curve: 'ed25519',
|
|
75
|
+
format: 'armored',
|
|
76
|
+
});
|
|
77
|
+
userGpgKeyPair = await openpgp.generateKey({
|
|
78
|
+
userIDs: [{ name: 'user', email: 'user@test.com' }],
|
|
79
|
+
curve: 'ed25519',
|
|
80
|
+
format: 'armored',
|
|
81
|
+
});
|
|
82
|
+
const [userDkgSession] = await sdk_lib_mpc_1.DklsUtils.generateDKGKeyShares();
|
|
83
|
+
userShare = userDkgSession.getKeyShare();
|
|
84
|
+
});
|
|
85
|
+
beforeEach(function () {
|
|
86
|
+
decryptAsyncStub = sinon.stub().callsFake(({ input }) =>
|
|
87
|
+
// Fake v2 envelope: resolve the plaintext embedded in the JSON.
|
|
88
|
+
Promise.resolve(JSON.parse(input).plaintext));
|
|
89
|
+
const mockBg = {};
|
|
90
|
+
mockBg.getEnv = sinon.stub().returns('test');
|
|
91
|
+
mockBg.encrypt = sinon
|
|
92
|
+
.stub()
|
|
93
|
+
.callsFake((params) => encryptWithSjcl(params.password ?? '', params.input, params.adata));
|
|
94
|
+
mockBg.decrypt = sinon.stub().callsFake((params) => sjcl.decrypt(params.password ?? '', params.input));
|
|
95
|
+
mockBg.decryptAsync = decryptAsyncStub;
|
|
96
|
+
mockBitgo = mockBg;
|
|
97
|
+
const mockCoin = {};
|
|
98
|
+
mockCoin.getHashFunction = sinon.stub().callsFake(() => (0, keccak_1.default)('keccak256'));
|
|
99
|
+
baseTssUtils = new TestBaseTssUtils(mockBitgo, mockCoin);
|
|
100
|
+
ecdsaMPCv2Utils = new src_1.EcdsaMPCv2Utils(mockBitgo, mockCoin);
|
|
101
|
+
});
|
|
102
|
+
describe('getSignableHexAndDerivationPath', function () {
|
|
103
|
+
it('extracts signableHex and derivationPath from a valid txRequest', function () {
|
|
104
|
+
const txRequest = buildTxRequest({
|
|
105
|
+
transactions: [
|
|
106
|
+
buildTransaction({
|
|
107
|
+
unsignedTx: buildUnsignedTransaction({ signableHex: 'deadbeef', derivationPath: 'm/0/0' }),
|
|
108
|
+
}),
|
|
109
|
+
],
|
|
110
|
+
});
|
|
111
|
+
const result = baseTssUtils.getSignableHexAndDerivationPathForTest(txRequest);
|
|
112
|
+
assert.equal(result.signableHex, 'deadbeef');
|
|
113
|
+
assert.equal(result.derivationPath, 'm/0/0');
|
|
114
|
+
});
|
|
115
|
+
it('throws when transactions field is missing', function () {
|
|
116
|
+
assert.throws(() => baseTssUtils.getSignableHexAndDerivationPathForTest(buildTxRequestWithoutTransactions()), /createOfflineShare requires exactly one transaction in txRequest/);
|
|
117
|
+
});
|
|
118
|
+
it('throws when transactions array is empty', function () {
|
|
119
|
+
assert.throws(() => baseTssUtils.getSignableHexAndDerivationPathForTest(buildTxRequest({ transactions: [] })), /createOfflineShare requires exactly one transaction in txRequest/);
|
|
120
|
+
});
|
|
121
|
+
it('throws when transactions array has more than one element', function () {
|
|
122
|
+
assert.throws(() => baseTssUtils.getSignableHexAndDerivationPathForTest(buildTxRequest({
|
|
123
|
+
transactions: [
|
|
124
|
+
buildTransaction({
|
|
125
|
+
unsignedTx: buildUnsignedTransaction({ signableHex: 'aaa', derivationPath: 'm/0' }),
|
|
126
|
+
}),
|
|
127
|
+
buildTransaction({
|
|
128
|
+
unsignedTx: buildUnsignedTransaction({ signableHex: 'bbb', derivationPath: 'm/1' }),
|
|
129
|
+
}),
|
|
130
|
+
],
|
|
131
|
+
})), /createOfflineShare requires exactly one transaction in txRequest/);
|
|
132
|
+
});
|
|
133
|
+
it('throws when unsignedTx is missing', function () {
|
|
134
|
+
// @ts-expect-error Intentionally malformed to exercise the runtime guard.
|
|
135
|
+
const noUnsignedTx = { state: 'pendingSignature', signatureShares: [] };
|
|
136
|
+
assert.throws(() => baseTssUtils.getSignableHexAndDerivationPathForTest(buildTxRequest({ transactions: [noUnsignedTx] })), /Missing unsignedTx in transactions/);
|
|
137
|
+
});
|
|
138
|
+
it('throws when signableHex is missing', function () {
|
|
139
|
+
// @ts-expect-error Intentionally malformed to exercise the runtime guard.
|
|
140
|
+
const noSignableHex = { serializedTxHex: 'aabbccdd', derivationPath: 'm/0' };
|
|
141
|
+
assert.throws(() => baseTssUtils.getSignableHexAndDerivationPathForTest(buildTxRequest({ transactions: [buildTransaction({ unsignedTx: noSignableHex })] })), /Missing signableHex in unsignedTx/);
|
|
142
|
+
});
|
|
143
|
+
it('throws when derivationPath is missing', function () {
|
|
144
|
+
// @ts-expect-error Intentionally malformed to exercise the runtime guard.
|
|
145
|
+
const noDerivationPath = { serializedTxHex: 'aabbccdd', signableHex: 'deadbeef' };
|
|
146
|
+
assert.throws(() => baseTssUtils.getSignableHexAndDerivationPathForTest(buildTxRequest({ transactions: [buildTransaction({ unsignedTx: noDerivationPath })] })), /Missing derivationPath in unsignedTx/);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe('validateAdata', function () {
|
|
150
|
+
it('passes when adata matches with domain separator', function () {
|
|
151
|
+
const adata = 'test-value';
|
|
152
|
+
const cyphertext = mockBitgo.encrypt({
|
|
153
|
+
input: 'secret',
|
|
154
|
+
password: walletPassphrase,
|
|
155
|
+
adata: `${roundOneDomainSeparator}:${adata}`,
|
|
156
|
+
});
|
|
157
|
+
assert.doesNotThrow(() => baseTssUtils.validateAdataForTest(adata, cyphertext, roundOneDomainSeparator));
|
|
158
|
+
});
|
|
159
|
+
it('passes when adata matches without domain separator', function () {
|
|
160
|
+
const adata = 'test-value';
|
|
161
|
+
const cyphertext = mockBitgo.encrypt({ input: 'secret', password: walletPassphrase, adata });
|
|
162
|
+
assert.doesNotThrow(() => baseTssUtils.validateAdataForTest(adata, cyphertext, roundOneDomainSeparator));
|
|
163
|
+
});
|
|
164
|
+
it('throws when adata does not match', function () {
|
|
165
|
+
const cyphertext = mockBitgo.encrypt({
|
|
166
|
+
input: 'secret',
|
|
167
|
+
password: walletPassphrase,
|
|
168
|
+
adata: `${roundOneDomainSeparator}:correct`,
|
|
169
|
+
});
|
|
170
|
+
assert.throws(() => baseTssUtils.validateAdataForTest('wrong', cyphertext, roundOneDomainSeparator), /Adata does not match cyphertext adata/);
|
|
171
|
+
});
|
|
172
|
+
it('throws when cyphertext is not valid JSON', function () {
|
|
173
|
+
assert.throws(() => baseTssUtils.validateAdataForTest('adata', 'not-json', roundOneDomainSeparator), /Failed to parse cyphertext to JSON/);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('getBitgoAndUserGpgKeys', function () {
|
|
177
|
+
it('decrypts v1 SJCL envelope without adata and skips validation', async function () {
|
|
178
|
+
const encryptedUserGpgPrvKey = mockBitgo.encrypt({
|
|
179
|
+
input: userGpgKeyPair.privateKey,
|
|
180
|
+
password: walletPassphrase,
|
|
181
|
+
});
|
|
182
|
+
const result = await baseTssUtils.getBitgoAndUserGpgKeysForTest(bitgoGpgKeyPair.publicKey, encryptedUserGpgPrvKey, walletPassphrase, '', signingUserGpgKeyDomainSeparator);
|
|
183
|
+
assert.ok(result.bitgoGpgKey);
|
|
184
|
+
assert.equal(result.userGpgPrvKey.isPrivate(), true);
|
|
185
|
+
});
|
|
186
|
+
it('decrypts v1 SJCL envelope with matching adata', async function () {
|
|
187
|
+
const adata = 'test-adata';
|
|
188
|
+
const encryptedUserGpgPrvKey = mockBitgo.encrypt({
|
|
189
|
+
input: userGpgKeyPair.privateKey,
|
|
190
|
+
password: walletPassphrase,
|
|
191
|
+
adata: `${signingUserGpgKeyDomainSeparator}:${adata}`,
|
|
192
|
+
});
|
|
193
|
+
const result = await baseTssUtils.getBitgoAndUserGpgKeysForTest(bitgoGpgKeyPair.publicKey, encryptedUserGpgPrvKey, walletPassphrase, adata, signingUserGpgKeyDomainSeparator);
|
|
194
|
+
assert.ok(result.bitgoGpgKey);
|
|
195
|
+
assert.equal(result.userGpgPrvKey.isPrivate(), true);
|
|
196
|
+
});
|
|
197
|
+
it('decrypts v2 envelope and returns GPG keys', async function () {
|
|
198
|
+
const adata = 'test-adata';
|
|
199
|
+
// Fake v2 envelope: JSON with v:2 triggers isV2Envelope; decryptAsync stub returns plaintext directly.
|
|
200
|
+
const encryptedUserGpgPrvKey = JSON.stringify({
|
|
201
|
+
v: 2,
|
|
202
|
+
adata: `${signingUserGpgKeyDomainSeparator}:${adata}`,
|
|
203
|
+
plaintext: userGpgKeyPair.privateKey,
|
|
204
|
+
});
|
|
205
|
+
const result = await baseTssUtils.getBitgoAndUserGpgKeysForTest(bitgoGpgKeyPair.publicKey, encryptedUserGpgPrvKey, walletPassphrase, adata, signingUserGpgKeyDomainSeparator);
|
|
206
|
+
sinon.assert.calledOnce(decryptAsyncStub);
|
|
207
|
+
assert.ok(result.bitgoGpgKey);
|
|
208
|
+
assert.equal(result.userGpgPrvKey.isPrivate(), true);
|
|
209
|
+
});
|
|
210
|
+
it('throws when adata does not match', async function () {
|
|
211
|
+
const encryptedUserGpgPrvKey = mockBitgo.encrypt({
|
|
212
|
+
input: userGpgKeyPair.privateKey,
|
|
213
|
+
password: walletPassphrase,
|
|
214
|
+
adata: `${signingUserGpgKeyDomainSeparator}:correct-adata`,
|
|
215
|
+
});
|
|
216
|
+
await assert.rejects(baseTssUtils.getBitgoAndUserGpgKeysForTest(bitgoGpgKeyPair.publicKey, encryptedUserGpgPrvKey, walletPassphrase, 'wrong-adata', signingUserGpgKeyDomainSeparator), /Adata does not match cyphertext adata/);
|
|
217
|
+
});
|
|
218
|
+
it('throws when cyphertext is not valid JSON', async function () {
|
|
219
|
+
await assert.rejects(baseTssUtils.getBitgoAndUserGpgKeysForTest(bitgoGpgKeyPair.publicKey, 'not-valid-json', walletPassphrase, 'test-adata', signingUserGpgKeyDomainSeparator), /json decode|Failed to parse cyphertext to JSON/);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
describe('ECDSA MPC v2 delegated txRequest parsing', function () {
|
|
223
|
+
it('getHashStringAndDerivationPath produces the correct hashBuffer and derivationPath', async function () {
|
|
224
|
+
const signableHex = 'deadbeef';
|
|
225
|
+
const derivationPath = 'm/0';
|
|
226
|
+
const txRequest = buildTxRequest({
|
|
227
|
+
transactions: [buildTransaction({ unsignedTx: buildUnsignedTransaction({ signableHex, derivationPath }) })],
|
|
228
|
+
});
|
|
229
|
+
const expectedHashBuffer = (0, keccak_1.default)('keccak256').update(Buffer.from(signableHex, 'hex')).digest();
|
|
230
|
+
const { encryptedRound1Session } = await ecdsaMPCv2Utils.createOfflineRound1Share({
|
|
231
|
+
txRequest,
|
|
232
|
+
prv: userShare.toString('base64'),
|
|
233
|
+
walletPassphrase,
|
|
234
|
+
});
|
|
235
|
+
// The round-1 session is encrypted with adata = "DKLS23_SIGNING_ROUND1_STATE:<hash>:<derivationPath>",
|
|
236
|
+
// which proves getHashStringAndDerivationPath produced the right values after the delegation refactor.
|
|
237
|
+
const { adata } = JSON.parse(encryptedRound1Session);
|
|
238
|
+
assert.equal(adata === undefined ? adata : decodeURIComponent(adata), `DKLS23_SIGNING_ROUND1_STATE:${expectedHashBuffer.toString('hex')}:${derivationPath}`);
|
|
239
|
+
});
|
|
240
|
+
it('propagates the base unsignedTx guard through the ECDSA route', async function () {
|
|
241
|
+
// @ts-expect-error Intentionally malformed to exercise the runtime guard.
|
|
242
|
+
const noUnsignedTx = { state: 'pendingSignature', signatureShares: [] };
|
|
243
|
+
await assert.rejects(ecdsaMPCv2Utils.createOfflineRound1Share({
|
|
244
|
+
txRequest: buildTxRequest({ transactions: [noUnsignedTx] }),
|
|
245
|
+
prv: 'unused',
|
|
246
|
+
walletPassphrase,
|
|
247
|
+
}), /Missing unsignedTx in transactions/);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Fixture builders
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
function buildTxRequest(overrides = {}) {
|
|
255
|
+
return {
|
|
256
|
+
txRequestId: 'tx-request-id',
|
|
257
|
+
walletId: 'wallet-id',
|
|
258
|
+
walletType: 'hot',
|
|
259
|
+
version: 1,
|
|
260
|
+
state: 'initialized',
|
|
261
|
+
date: new Date(0).toISOString(),
|
|
262
|
+
userId: 'user-id',
|
|
263
|
+
intent: {},
|
|
264
|
+
policiesChecked: true,
|
|
265
|
+
unsignedTxs: [],
|
|
266
|
+
transactions: [buildTransaction()],
|
|
267
|
+
latest: true,
|
|
268
|
+
...overrides,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function buildTxRequestWithoutTransactions() {
|
|
272
|
+
const txRequest = buildTxRequest();
|
|
273
|
+
delete txRequest.transactions;
|
|
274
|
+
return txRequest;
|
|
275
|
+
}
|
|
276
|
+
function buildTransaction(overrides = {}) {
|
|
277
|
+
return { state: 'pendingSignature', unsignedTx: buildUnsignedTransaction(), signatureShares: [], ...overrides };
|
|
278
|
+
}
|
|
279
|
+
function buildUnsignedTransaction(overrides = {}) {
|
|
280
|
+
return { serializedTxHex: 'aabbccdd', signableHex: 'deadbeef', derivationPath: 'm/0', ...overrides };
|
|
281
|
+
}
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
// Encryption helpers (mirrors the ecdsaMPCv2 test pattern)
|
|
284
|
+
// ---------------------------------------------------------------------------
|
|
285
|
+
function encryptWithSjcl(password, input, adata) {
|
|
286
|
+
const salt = (0, crypto_1.randomBytes)(8);
|
|
287
|
+
const iv = (0, crypto_1.randomBytes)(16);
|
|
288
|
+
return sjcl.encrypt(password, input, {
|
|
289
|
+
salt: [bytesToWord(salt.subarray(0, 4)), bytesToWord(salt.subarray(4))],
|
|
290
|
+
iv: [
|
|
291
|
+
bytesToWord(iv.subarray(0, 4)),
|
|
292
|
+
bytesToWord(iv.subarray(4, 8)),
|
|
293
|
+
bytesToWord(iv.subarray(8, 12)),
|
|
294
|
+
bytesToWord(iv.subarray(12, 16)),
|
|
295
|
+
],
|
|
296
|
+
...(adata !== undefined ? { adata } : {}),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function bytesToWord(bytes) {
|
|
300
|
+
if (bytes.length !== 4) {
|
|
301
|
+
throw new Error('bytes must have length 4');
|
|
302
|
+
}
|
|
303
|
+
return bytes.reduce((num, byte) => num * 0x100 + byte, 0);
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZVRTU1V0aWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGVzdC91bml0L2JpdGdvL3V0aWxzL3Rzcy9iYXNlVFNTVXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBaUM7QUFDakMsbUNBQTJDO0FBQzNDLG9EQUFzQztBQUN0QyxpREFBbUM7QUFDbkMsNkNBQStCO0FBQy9CLGtEQUFvQztBQUNwQyxvREFBK0M7QUFFL0MsNENBQXNGO0FBQ3RGLG1HQUEyRTtBQVkzRSxNQUFNLGdCQUFpQixTQUFRLHNCQUFvQjtJQUNqRCxzQ0FBc0MsQ0FDcEMsU0FBb0IsRUFDcEIsMEJBQW1DO1FBRW5DLE9BQU8sSUFBSSxDQUFDLCtCQUErQixDQUFDLFNBQVMsRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO0lBQ3JGLENBQUM7SUFFRCxvQkFBb0IsQ0FBQyxLQUFhLEVBQUUsVUFBa0IsRUFBRSxvQkFBNEI7UUFDbEYsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLG9CQUFvQixDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVELDZCQUE2QixDQUMzQixpQkFBeUIsRUFDekIsc0JBQThCLEVBQzlCLGdCQUF3QixFQUN4QixLQUFhLEVBQ2IseUJBQWlDO1FBRWpDLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUNoQyxpQkFBaUIsRUFDakIsc0JBQXNCLEVBQ3RCLGdCQUFnQixFQUNoQixLQUFLLEVBQ0wseUJBQXlCLENBQzFCLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUFFRCxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7SUFDekIsTUFBTSxnQkFBZ0IsR0FBRyxlQUFlLENBQUM7SUFDekMsTUFBTSxnQ0FBZ0MsR0FBRyw4QkFBOEIsQ0FBQztJQUN4RSxNQUFNLHVCQUF1QixHQUFHLDhCQUE4QixDQUFDO0lBRS9ELElBQUksWUFBOEIs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QUFFLENBQUMsR0FBRyxHQUFHLEtBQUssR0FBRyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDNUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgSGFzaCwgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IGNyZWF0ZUtlY2Nha0hhc2ggZnJvbSAna2VjY2FrJztcbmltcG9ydCAqIGFzIG9wZW5wZ3AgZnJvbSAnb3BlbnBncCc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgKiBhcyBzamNsIGZyb20gJ0BiaXRnby9zamNsJztcbmltcG9ydCB7IERrbHNVdGlscyB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5cbmltcG9ydCB7IEJpdEdvQmFzZSwgRWNkc2FNUEN2MlV0aWxzLCBJQmFzZUNvaW4sIFR4UmVxdWVzdCB9IGZyb20gJy4uLy4uLy4uLy4uLy4uL3NyYyc7XG5pbXBvcnQgQmFzZVRzc1V0aWxzIGZyb20gJy4uLy4uLy4uLy4uLy4uL3NyYy9iaXRnby91dGlscy90c3MvYmFzZVRTU1V0aWxzJztcblxudHlwZSBCaXRnb0dwZ0tleVBhaXIgPSBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz4gJiB7IHJldm9jYXRpb25DZXJ0aWZpY2F0ZTogc3RyaW5nIH07XG50eXBlIFR4UmVxdWVzdFRyYW5zYWN0aW9uID0gTm9uTnVsbGFibGU8VHhSZXF1ZXN0Wyd0cmFuc2FjdGlvbnMnXT5bbnVtYmVyXTtcbnR5cGUgVW5zaWduZWRUcmFuc2FjdGlvbiA9IFR4UmVxdWVzdFRyYW5zYWN0aW9uWyd1bnNpZ25lZFR4J107XG50eXBlIFNpZ25hYmxlSGV4QW5kRGVyaXZhdGlvblBhdGggPSB7XG4gIHNpZ25hYmxlSGV4OiBzdHJpbmc7XG4gIGRlcml2YXRpb25QYXRoOiBzdHJpbmc7XG4gIHNlcmlhbGl6ZWRUeEhleDogc3RyaW5nIHwgdW5kZWZpbmVkO1xufTtcbnR5cGUgRGVjcnlwdGVkR3BnS2V5cyA9IHsgYml0Z29HcGdLZXk6IG9wZW5wZ3AuS2V5OyB1c2VyR3BnUHJ2S2V5OiBvcGVucGdwLlByaXZhdGVLZXkgfTtcblxuY2xhc3MgVGVzdEJhc2VUc3NVdGlscyBleHRlbmRzIEJhc2VUc3NVdGlsczxCdWZmZXI+IHtcbiAgZ2V0U2lnbmFibGVIZXhBbmREZXJpdmF0aW9uUGF0aEZvclRlc3QoXG4gICAgdHhSZXF1ZXN0OiBUeFJlcXVlc3QsXG4gICAgbWlzc2luZ1RyYW5zYWN0aW9uc01lc3NhZ2U/OiBzdHJpbmdcbiAgKTogU2lnbmFibGVIZXhBbmREZXJpdmF0aW9uUGF0aCB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0U2lnbmFibGVIZXhBbmREZXJpdmF0aW9uUGF0aCh0eFJlcXVlc3QsIG1pc3NpbmdUcmFuc2FjdGlvbnNNZXNzYWdlKTtcbiAgfVxuXG4gIHZhbGlkYXRlQWRhdGFGb3JUZXN0KGFkYXRhOiBzdHJpbmcsIGN5cGhlcnRleHQ6IHN0cmluZywgcm91bmREb21haW5TZXBhcmF0b3I6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudmFsaWRhdGVBZGF0YShhZGF0YSwgY3lwaGVydGV4dCwgcm91bmREb21haW5TZXBhcmF0b3IpO1xuICB9XG5cbiAgZ2V0Qml0Z29BbmRVc2VyR3BnS2V5c0ZvclRlc3QoXG4gICAgYml0Z29QdWJsaWNHcGdLZXk6IHN0cmluZyxcbiAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiBzdHJpbmcsXG4gICAgd2FsbGV0UGFzc3BocmFzZTogc3RyaW5nLFxuICAgIGFkYXRhOiBzdHJpbmcsXG4gICAgdXNlckdwZ0tleURvbWFpblNlcGFyYXRvcjogc3RyaW5nXG4gICk6IFByb21pc2U8RGVjcnlwdGVkR3BnS2V5cz4ge1xuICAgIHJldHVybiB0aGlzLmdldEJpdGdvQW5kVXNlckdwZ0tleXMoXG4gICAgICBiaXRnb1B1YmxpY0dwZ0tleSxcbiAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgYWRhdGEsXG4gICAgICB1c2VyR3BnS2V5RG9tYWluU2VwYXJhdG9yXG4gICAgKTtcbiAgfVxufVxuXG5kZXNjcmliZSgnQmFzZSBUU1MgVXRpbHMnLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdC1wYXNzd29yZCc7XG4gIGNvbnN0IHNpZ25pbmdVc2VyR3BnS2V5RG9tYWluU2VwYXJhdG9yID0gJ01QU19EU0dfU0lHTklOR19VU0VSX0dQR19LRVknO1xuICBjb25zdCByb3VuZE9uZURvbWFpblNlcGFyYXRvciA9ICdNUFNfRFNHX1NJR05JTkdfUk9VTkQxX1NUQVRFJztcblxuICBsZXQgYmFzZVRzc1V0aWxzOiBUZXN0QmFzZVRzc1V0aWxzO1xuICBsZXQgZWNkc2FNUEN2MlV0aWxzOiBFY2RzYU1QQ3YyVXRpbHM7XG4gIGxldCBtb2NrQml0Z286IEJpdEdvQmFzZTtcbiAgbGV0IGRlY3J5cHRBc3luY1N0dWI6IHNpbm9uLlNpbm9uU3R1YjtcbiAgbGV0IGJpdGdvR3BnS2V5UGFpcjogQml0Z29HcGdLZXlQYWlyO1xuICBsZXQgdXNlckdwZ0tleVBhaXI6IEJpdGdvR3BnS2V5UGFpcjtcbiAgbGV0IHVzZXJTaGFyZTogQnVmZmVyO1xuXG4gIGJlZm9yZShhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgb3BlbnBncC5jb25maWcucmVqZWN0Q3VydmVzID0gbmV3IFNldCgpO1xuICAgIGJpdGdvR3BnS2V5UGFpciA9IGF3YWl0IG9wZW5wZ3AuZ2VuZXJhdGVLZXkoe1xuICAgICAgdXNlcklEczogW3sgbmFtZTogJ2JpdGdvJywgZW1haWw6ICdiaXRnb0B0ZXN0LmNvbScgfV0sXG4gICAgICBjdXJ2ZTogJ2VkMjU1MTknLFxuICAgICAgZm9ybWF0OiAnYXJtb3JlZCcsXG4gICAgfSk7XG4gICAgdXNlckdwZ0tleVBhaXIgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgIHVzZXJJRHM6IFt7IG5hbWU6ICd1c2VyJywgZW1haWw6ICd1c2VyQHRlc3QuY29tJyB9XSxcbiAgICAgIGN1cnZlOiAnZWQyNTUxOScsXG4gICAgICBmb3JtYXQ6ICdhcm1vcmVkJyxcbiAgICB9KTtcblxuICAgIGNvbnN0IFt1c2VyRGtnU2Vzc2lvbl0gPSBhd2FpdCBEa2xzVXRpbHMuZ2VuZXJhdGVES0dLZXlTaGFyZXMoKTtcbiAgICB1c2VyU2hhcmUgPSB1c2VyRGtnU2Vzc2lvbi5nZXRLZXlTaGFyZSgpO1xuICB9KTtcblxuICBiZWZvcmVFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBkZWNyeXB0QXN5bmNTdHViID0gc2lub24uc3R1YigpLmNhbGxzRmFrZSgoeyBpbnB1dCB9OiBQYXJhbWV0ZXJzPEJpdEdvQmFzZVsnZGVjcnlwdEFzeW5jJ10+WzBdKSA9PlxuICAgICAgLy8gRmFrZSB2MiBlbnZlbG9wZTogcmVzb2x2ZSB0aGUgcGxhaW50ZXh0IGVtYmVkZGVkIGluIHRoZSBKU09OLlxuICAgICAgUHJvbWlzZS5yZXNvbHZlKChKU09OLnBhcnNlKGlucHV0KSBhcyB7IHBsYWludGV4dDogc3RyaW5nIH0pLnBsYWludGV4dClcbiAgICApO1xuXG4gICAgY29uc3QgbW9ja0JnID0ge30gYXMgQml0R29CYXNlO1xuICAgIG1vY2tCZy5nZXRFbnYgPSBzaW5vbi5zdHViKCkucmV0dXJucygndGVzdCcpO1xuICAgIG1vY2tCZy5lbmNyeXB0ID0gc2lub25cbiAgICAgIC5zdHViKClcbiAgICAgIC5jYWxsc0Zha2UoKHBhcmFtcykgPT4gZW5jcnlwdFdpdGhTamNsKHBhcmFtcy5wYXNzd29yZCA/PyAnJywgcGFyYW1zLmlucHV0LCBwYXJhbXMuYWRhdGEpKTtcbiAgICBtb2NrQmcuZGVjcnlwdCA9IHNpbm9uLnN0dWIoKS5jYWxsc0Zha2UoKHBhcmFtcykgPT4gc2pjbC5kZWNyeXB0KHBhcmFtcy5wYXNzd29yZCA/PyAnJywgcGFyYW1zLmlucHV0KSk7XG4gICAgbW9ja0JnLmRlY3J5cHRBc3luYyA9IGRlY3J5cHRBc3luY1N0dWI7XG4gICAgbW9ja0JpdGdvID0gbW9ja0JnO1xuXG4gICAgY29uc3QgbW9ja0NvaW4gPSB7fSBhcyBJQmFzZUNvaW47XG4gICAgbW9ja0NvaW4uZ2V0SGFzaEZ1bmN0aW9uID0gc2lub24uc3R1YigpLmNhbGxzRmFrZSgoKSA9PiBjcmVhdGVLZWNjYWtIYXNoKCdrZWNjYWsyNTYnKSBhcyBIYXNoKTtcblxuICAgIGJhc2VUc3NVdGlscyA9IG5ldyBUZXN0QmFzZVRzc1V0aWxzKG1vY2tCaXRnbywgbW9ja0NvaW4pO1xuICAgIGVjZHNhTVBDdjJVdGlscyA9IG5ldyBFY2RzYU1QQ3YyVXRpbHMobW9ja0JpdGdvLCBtb2NrQ29pbik7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZXRTaWduYWJsZUhleEFuZERlcml2YXRpb25QYXRoJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdleHRyYWN0cyBzaWduYWJsZUhleCBhbmQgZGVyaXZhdGlvblBhdGggZnJvbSBhIHZhbGlkIHR4UmVxdWVzdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdCA9IGJ1aWxkVHhSZXF1ZXN0KHtcbiAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgYnVpbGRUcmFuc2FjdGlvbih7XG4gICAgICAgICAgICB1bnNpZ25lZFR4OiBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oeyBzaWduYWJsZUhleDogJ2RlYWRiZWVmJywgZGVyaXZhdGlvblBhdGg6ICdtLzAvMCcgfSksXG4gICAgICAgICAgfSksXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYmFzZVRzc1V0aWxzLmdldFNpZ25hYmxlSGV4QW5kRGVyaXZhdGlvblBhdGhGb3JUZXN0KHR4UmVxdWVzdCk7XG4gICAgICBhc3NlcnQuZXF1YWwocmVzdWx0LnNpZ25hYmxlSGV4LCAnZGVhZGJlZWYnKTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXN1bHQuZGVyaXZhdGlvblBhdGgsICdtLzAvMCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyB3aGVuIHRyYW5zYWN0aW9ucyBmaWVsZCBpcyBtaXNzaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gYmFzZVRzc1V0aWxzLmdldFNpZ25hYmxlSGV4QW5kRGVyaXZhdGlvblBhdGhGb3JUZXN0KGJ1aWxkVHhSZXF1ZXN0V2l0aG91dFRyYW5zYWN0aW9ucygpKSxcbiAgICAgICAgL2NyZWF0ZU9mZmxpbmVTaGFyZSByZXF1aXJlcyBleGFjdGx5IG9uZSB0cmFuc2FjdGlvbiBpbiB0eFJlcXVlc3QvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyB3aGVuIHRyYW5zYWN0aW9ucyBhcnJheSBpcyBlbXB0eScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+IGJhc2VUc3NVdGlscy5nZXRTaWduYWJsZUhleEFuZERlcml2YXRpb25QYXRoRm9yVGVzdChidWlsZFR4UmVxdWVzdCh7IHRyYW5zYWN0aW9uczogW10gfSkpLFxuICAgICAgICAvY3JlYXRlT2ZmbGluZVNoYXJlIHJlcXVpcmVzIGV4YWN0bHkgb25lIHRyYW5zYWN0aW9uIGluIHR4UmVxdWVzdC9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIHdoZW4gdHJhbnNhY3Rpb25zIGFycmF5IGhhcyBtb3JlIHRoYW4gb25lIGVsZW1lbnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgICAoKSA9PlxuICAgICAgICAgIGJhc2VUc3NVdGlscy5nZXRTaWduYWJsZUhleEFuZERlcml2YXRpb25QYXRoRm9yVGVzdChcbiAgICAgICAgICAgIGJ1aWxkVHhSZXF1ZXN0KHtcbiAgICAgICAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgICAgICAgYnVpbGRUcmFuc2FjdGlvbih7XG4gICAgICAgICAgICAgICAgICB1bnNpZ25lZFR4OiBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oeyBzaWduYWJsZUhleDogJ2FhYScsIGRlcml2YXRpb25QYXRoOiAnbS8wJyB9KSxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBidWlsZFRyYW5zYWN0aW9uKHtcbiAgICAgICAgICAgICAgICAgIHVuc2lnbmVkVHg6IGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbih7IHNpZ25hYmxlSGV4OiAnYmJiJywgZGVyaXZhdGlvblBhdGg6ICdtLzEnIH0pLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICApLFxuICAgICAgICAvY3JlYXRlT2ZmbGluZVNoYXJlIHJlcXVpcmVzIGV4YWN0bHkgb25lIHRyYW5zYWN0aW9uIGluIHR4UmVxdWVzdC9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIHdoZW4gdW5zaWduZWRUeCBpcyBtaXNzaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBJbnRlbnRpb25hbGx5IG1hbGZvcm1lZCB0byBleGVyY2lzZSB0aGUgcnVudGltZSBndWFyZC5cbiAgICAgIGNvbnN0IG5vVW5zaWduZWRUeDogVHhSZXF1ZXN0VHJhbnNhY3Rpb24gPSB7IHN0YXRlOiAncGVuZGluZ1NpZ25hdHVyZScsIHNpZ25hdHVyZVNoYXJlczogW10gfTtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+IGJhc2VUc3NVdGlscy5nZXRTaWduYWJsZUhleEFuZERlcml2YXRpb25QYXRoRm9yVGVzdChidWlsZFR4UmVxdWVzdCh7IHRyYW5zYWN0aW9uczogW25vVW5zaWduZWRUeF0gfSkpLFxuICAgICAgICAvTWlzc2luZyB1bnNpZ25lZFR4IGluIHRyYW5zYWN0aW9ucy9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIHdoZW4gc2lnbmFibGVIZXggaXMgbWlzc2luZycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgSW50ZW50aW9uYWxseSBtYWxmb3JtZWQgdG8gZXhlcmNpc2UgdGhlIHJ1bnRpbWUgZ3VhcmQuXG4gICAgICBjb25zdCBub1NpZ25hYmxlSGV4OiBVbnNpZ25lZFRyYW5zYWN0aW9uID0geyBzZXJpYWxpemVkVHhIZXg6ICdhYWJiY2NkZCcsIGRlcml2YXRpb25QYXRoOiAnbS8wJyB9O1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBiYXNlVHNzVXRpbHMuZ2V0U2lnbmFibGVIZXhBbmREZXJpdmF0aW9uUGF0aEZvclRlc3QoXG4gICAgICAgICAgICBidWlsZFR4UmVxdWVzdCh7IHRyYW5zYWN0aW9uczogW2J1aWxkVHJhbnNhY3Rpb24oeyB1bnNpZ25lZFR4OiBub1NpZ25hYmxlSGV4IH0pXSB9KVxuICAgICAgICAgICksXG4gICAgICAgIC9NaXNzaW5nIHNpZ25hYmxlSGV4IGluIHVuc2lnbmVkVHgvXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyB3aGVuIGRlcml2YXRpb25QYXRoIGlzIG1pc3NpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIEludGVudGlvbmFsbHkgbWFsZm9ybWVkIHRvIGV4ZXJjaXNlIHRoZSBydW50aW1lIGd1YXJkLlxuICAgICAgY29uc3Qgbm9EZXJpdmF0aW9uUGF0aDogVW5zaWduZWRUcmFuc2FjdGlvbiA9IHsgc2VyaWFsaXplZFR4SGV4OiAnYWFiYmNjZGQnLCBzaWduYWJsZUhleDogJ2RlYWRiZWVmJyB9O1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT5cbiAgICAgICAgICBiYXNlVHNzVXRpbHMuZ2V0U2lnbmFibGVIZXhBbmREZXJpdmF0aW9uUGF0aEZvclRlc3QoXG4gICAgICAgICAgICBidWlsZFR4UmVxdWVzdCh7IHRyYW5zYWN0aW9uczogW2J1aWxkVHJhbnNhY3Rpb24oeyB1bnNpZ25lZFR4OiBub0Rlcml2YXRpb25QYXRoIH0pXSB9KVxuICAgICAgICAgICksXG4gICAgICAgIC9NaXNzaW5nIGRlcml2YXRpb25QYXRoIGluIHVuc2lnbmVkVHgvXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndmFsaWRhdGVBZGF0YScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgncGFzc2VzIHdoZW4gYWRhdGEgbWF0Y2hlcyB3aXRoIGRvbWFpbiBzZXBhcmF0b3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGF0YSA9ICd0ZXN0LXZhbHVlJztcbiAgICAgIGNvbnN0IGN5cGhlcnRleHQgPSBtb2NrQml0Z28uZW5jcnlwdCh7XG4gICAgICAgIGlucHV0OiAnc2VjcmV0JyxcbiAgICAgICAgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIGFkYXRhOiBgJHtyb3VuZE9uZURvbWFpblNlcGFyYXRvcn06JHthZGF0YX1gLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQuZG9lc05vdFRocm93KCgpID0+IGJhc2VUc3NVdGlscy52YWxpZGF0ZUFkYXRhRm9yVGVzdChhZGF0YSwgY3lwaGVydGV4dCwgcm91bmRPbmVEb21haW5TZXBhcmF0b3IpKTtcbiAgICB9KTtcblxuICAgIGl0KCdwYXNzZXMgd2hlbiBhZGF0YSBtYXRjaGVzIHdpdGhvdXQgZG9tYWluIHNlcGFyYXRvcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkYXRhID0gJ3Rlc3QtdmFsdWUnO1xuICAgICAgY29uc3QgY3lwaGVydGV4dCA9IG1vY2tCaXRnby5lbmNyeXB0KHsgaW5wdXQ6ICdzZWNyZXQnLCBwYXNzd29yZDogd2FsbGV0UGFzc3BocmFzZSwgYWRhdGEgfSk7XG4gICAgICBhc3NlcnQuZG9lc05vdFRocm93KCgpID0+IGJhc2VUc3NVdGlscy52YWxpZGF0ZUFkYXRhRm9yVGVzdChhZGF0YSwgY3lwaGVydGV4dCwgcm91bmRPbmVEb21haW5TZXBhcmF0b3IpKTtcbiAgICB9KTtcblxuICAgIGl0KCd0aHJvd3Mgd2hlbiBhZGF0YSBkb2VzIG5vdCBtYXRjaCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGN5cGhlcnRleHQgPSBtb2NrQml0Z28uZW5jcnlwdCh7XG4gICAgICAgIGlucHV0OiAnc2VjcmV0JyxcbiAgICAgICAgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIGFkYXRhOiBgJHtyb3VuZE9uZURvbWFpblNlcGFyYXRvcn06Y29ycmVjdGAsXG4gICAgICB9KTtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+IGJhc2VUc3NVdGlscy52YWxpZGF0ZUFkYXRhRm9yVGVzdCgnd3JvbmcnLCBjeXBoZXJ0ZXh0LCByb3VuZE9uZURvbWFpblNlcGFyYXRvciksXG4gICAgICAgIC9BZGF0YSBkb2VzIG5vdCBtYXRjaCBjeXBoZXJ0ZXh0IGFkYXRhL1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCd0aHJvd3Mgd2hlbiBjeXBoZXJ0ZXh0IGlzIG5vdCB2YWxpZCBKU09OJywgZnVuY3Rpb24gKCkge1xuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gYmFzZVRzc1V0aWxzLnZhbGlkYXRlQWRhdGFGb3JUZXN0KCdhZGF0YScsICdub3QtanNvbicsIHJvdW5kT25lRG9tYWluU2VwYXJhdG9yKSxcbiAgICAgICAgL0ZhaWxlZCB0byBwYXJzZSBjeXBoZXJ0ZXh0IHRvIEpTT04vXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZ2V0Qml0Z29BbmRVc2VyR3BnS2V5cycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnZGVjcnlwdHMgdjEgU0pDTCBlbnZlbG9wZSB3aXRob3V0IGFkYXRhIGFuZCBza2lwcyB2YWxpZGF0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZW5jcnlwdGVkVXNlckdwZ1BydktleSA9IG1vY2tCaXRnby5lbmNyeXB0KHtcbiAgICAgICAgaW5wdXQ6IHVzZXJHcGdLZXlQYWlyLnByaXZhdGVLZXksXG4gICAgICAgIHBhc3N3b3JkOiB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2VUc3NVdGlscy5nZXRCaXRnb0FuZFVzZXJHcGdLZXlzRm9yVGVzdChcbiAgICAgICAgYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgJycsXG4gICAgICAgIHNpZ25pbmdVc2VyR3BnS2V5RG9tYWluU2VwYXJhdG9yXG4gICAgICApO1xuXG4gICAgICBhc3NlcnQub2socmVzdWx0LmJpdGdvR3BnS2V5KTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXN1bHQudXNlckdwZ1BydktleS5pc1ByaXZhdGUoKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGVjcnlwdHMgdjEgU0pDTCBlbnZlbG9wZSB3aXRoIG1hdGNoaW5nIGFkYXRhJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRhdGEgPSAndGVzdC1hZGF0YSc7XG4gICAgICBjb25zdCBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5ID0gbW9ja0JpdGdvLmVuY3J5cHQoe1xuICAgICAgICBpbnB1dDogdXNlckdwZ0tleVBhaXIucHJpdmF0ZUtleSxcbiAgICAgICAgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIGFkYXRhOiBgJHtzaWduaW5nVXNlckdwZ0tleURvbWFpblNlcGFyYXRvcn06JHthZGF0YX1gLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJhc2VUc3NVdGlscy5nZXRCaXRnb0FuZFVzZXJHcGdLZXlzRm9yVGVzdChcbiAgICAgICAgYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgYWRhdGEsXG4gICAgICAgIHNpZ25pbmdVc2VyR3BnS2V5RG9tYWluU2VwYXJhdG9yXG4gICAgICApO1xuXG4gICAgICBhc3NlcnQub2socmVzdWx0LmJpdGdvR3BnS2V5KTtcbiAgICAgIGFzc2VydC5lcXVhbChyZXN1bHQudXNlckdwZ1BydktleS5pc1ByaXZhdGUoKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGVjcnlwdHMgdjIgZW52ZWxvcGUgYW5kIHJldHVybnMgR1BHIGtleXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBhZGF0YSA9ICd0ZXN0LWFkYXRhJztcbiAgICAgIC8vIEZha2UgdjIgZW52ZWxvcGU6IEpTT04gd2l0aCB2OjIgdHJpZ2dlcnMgaXNWMkVudmVsb3BlOyBkZWNyeXB0QXN5bmMgc3R1YiByZXR1cm5zIHBsYWludGV4dCBkaXJlY3RseS5cbiAgICAgIGNvbnN0IGVuY3J5cHRlZFVzZXJHcGdQcnZLZXkgPSBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIHY6IDIsXG4gICAgICAgIGFkYXRhOiBgJHtzaWduaW5nVXNlckdwZ0tleURvbWFpblNlcGFyYXRvcn06JHthZGF0YX1gLFxuICAgICAgICBwbGFpbnRleHQ6IHVzZXJHcGdLZXlQYWlyLnByaXZhdGVLZXksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgYmFzZVRzc1V0aWxzLmdldEJpdGdvQW5kVXNlckdwZ0tleXNGb3JUZXN0KFxuICAgICAgICBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICBhZGF0YSxcbiAgICAgICAgc2lnbmluZ1VzZXJHcGdLZXlEb21haW5TZXBhcmF0b3JcbiAgICAgICk7XG5cbiAgICAgIHNpbm9uLmFzc2VydC5jYWxsZWRPbmNlKGRlY3J5cHRBc3luY1N0dWIpO1xuICAgICAgYXNzZXJ0Lm9rKHJlc3VsdC5iaXRnb0dwZ0tleSk7XG4gICAgICBhc3NlcnQuZXF1YWwocmVzdWx0LnVzZXJHcGdQcnZLZXkuaXNQcml2YXRlKCksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyB3aGVuIGFkYXRhIGRvZXMgbm90IG1hdGNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZW5jcnlwdGVkVXNlckdwZ1BydktleSA9IG1vY2tCaXRnby5lbmNyeXB0KHtcbiAgICAgICAgaW5wdXQ6IHVzZXJHcGdLZXlQYWlyLnByaXZhdGVLZXksXG4gICAgICAgIHBhc3N3b3JkOiB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICBhZGF0YTogYCR7c2lnbmluZ1VzZXJHcGdLZXlEb21haW5TZXBhcmF0b3J9OmNvcnJlY3QtYWRhdGFgLFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBiYXNlVHNzVXRpbHMuZ2V0Qml0Z29BbmRVc2VyR3BnS2V5c0ZvclRlc3QoXG4gICAgICAgICAgYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgJ3dyb25nLWFkYXRhJyxcbiAgICAgICAgICBzaWduaW5nVXNlckdwZ0tleURvbWFpblNlcGFyYXRvclxuICAgICAgICApLFxuICAgICAgICAvQWRhdGEgZG9lcyBub3QgbWF0Y2ggY3lwaGVydGV4dCBhZGF0YS9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIHdoZW4gY3lwaGVydGV4dCBpcyBub3QgdmFsaWQgSlNPTicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBiYXNlVHNzVXRpbHMuZ2V0Qml0Z29BbmRVc2VyR3BnS2V5c0ZvclRlc3QoXG4gICAgICAgICAgYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICAnbm90LXZhbGlkLWpzb24nLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgJ3Rlc3QtYWRhdGEnLFxuICAgICAgICAgIHNpZ25pbmdVc2VyR3BnS2V5RG9tYWluU2VwYXJhdG9yXG4gICAgICAgICksXG4gICAgICAgIC9qc29uIGRlY29kZXxGYWlsZWQgdG8gcGFyc2UgY3lwaGVydGV4dCB0byBKU09OL1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0VDRFNBIE1QQyB2MiBkZWxlZ2F0ZWQgdHhSZXF1ZXN0IHBhcnNpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2dldEhhc2hTdHJpbmdBbmREZXJpdmF0aW9uUGF0aCBwcm9kdWNlcyB0aGUgY29ycmVjdCBoYXNoQnVmZmVyIGFuZCBkZXJpdmF0aW9uUGF0aCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25hYmxlSGV4ID0gJ2RlYWRiZWVmJztcbiAgICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gJ20vMCc7XG4gICAgICBjb25zdCB0eFJlcXVlc3QgPSBidWlsZFR4UmVxdWVzdCh7XG4gICAgICAgIHRyYW5zYWN0aW9uczogW2J1aWxkVHJhbnNhY3Rpb24oeyB1bnNpZ25lZFR4OiBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oeyBzaWduYWJsZUhleCwgZGVyaXZhdGlvblBhdGggfSkgfSldLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBleHBlY3RlZEhhc2hCdWZmZXIgPSBjcmVhdGVLZWNjYWtIYXNoKCdrZWNjYWsyNTYnKS51cGRhdGUoQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKSkuZGlnZXN0KCk7XG5cbiAgICAgIGNvbnN0IHsgZW5jcnlwdGVkUm91bmQxU2Vzc2lvbiB9ID0gYXdhaXQgZWNkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDFTaGFyZSh7XG4gICAgICAgIHR4UmVxdWVzdCxcbiAgICAgICAgcHJ2OiB1c2VyU2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFRoZSByb3VuZC0xIHNlc3Npb24gaXMgZW5jcnlwdGVkIHdpdGggYWRhdGEgPSBcIkRLTFMyM19TSUdOSU5HX1JPVU5EMV9TVEFURTo8aGFzaD46PGRlcml2YXRpb25QYXRoPlwiLFxuICAgICAgLy8gd2hpY2ggcHJvdmVzIGdldEhhc2hTdHJpbmdBbmREZXJpdmF0aW9uUGF0aCBwcm9kdWNlZCB0aGUgcmlnaHQgdmFsdWVzIGFmdGVyIHRoZSBkZWxlZ2F0aW9uIHJlZmFjdG9yLlxuICAgICAgY29uc3QgeyBhZGF0YSB9ID0gSlNPTi5wYXJzZShlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uKSBhcyB7IGFkYXRhPzogc3RyaW5nIH07XG4gICAgICBhc3NlcnQuZXF1YWwoXG4gICAgICAgIGFkYXRhID09PSB1bmRlZmluZWQgPyBhZGF0YSA6IGRlY29kZVVSSUNvbXBvbmVudChhZGF0YSksXG4gICAgICAgIGBES0xTMjNfU0lHTklOR19ST1VORDFfU1RBVEU6JHtleHBlY3RlZEhhc2hCdWZmZXIudG9TdHJpbmcoJ2hleCcpfToke2Rlcml2YXRpb25QYXRofWBcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgncHJvcGFnYXRlcyB0aGUgYmFzZSB1bnNpZ25lZFR4IGd1YXJkIHRocm91Z2ggdGhlIEVDRFNBIHJvdXRlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBJbnRlbnRpb25hbGx5IG1hbGZvcm1lZCB0byBleGVyY2lzZSB0aGUgcnVudGltZSBndWFyZC5cbiAgICAgIGNvbnN0IG5vVW5zaWduZWRUeDogVHhSZXF1ZXN0VHJhbnNhY3Rpb24gPSB7IHN0YXRlOiAncGVuZGluZ1NpZ25hdHVyZScsIHNpZ25hdHVyZVNoYXJlczogW10gfTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgICBlY2RzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kMVNoYXJlKHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IGJ1aWxkVHhSZXF1ZXN0KHsgdHJhbnNhY3Rpb25zOiBbbm9VbnNpZ25lZFR4XSB9KSxcbiAgICAgICAgICBwcnY6ICd1bnVzZWQnLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIH0pLFxuICAgICAgICAvTWlzc2luZyB1bnNpZ25lZFR4IGluIHRyYW5zYWN0aW9ucy9cbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gRml4dHVyZSBidWlsZGVyc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmZ1bmN0aW9uIGJ1aWxkVHhSZXF1ZXN0KG92ZXJyaWRlczogUGFydGlhbDxUeFJlcXVlc3Q+ID0ge30pOiBUeFJlcXVlc3Qge1xuICByZXR1cm4ge1xuICAgIHR4UmVxdWVzdElkOiAndHgtcmVxdWVzdC1pZCcsXG4gICAgd2FsbGV0SWQ6ICd3YWxsZXQtaWQnLFxuICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgIHZlcnNpb246IDEsXG4gICAgc3RhdGU6ICdpbml0aWFsaXplZCcsXG4gICAgZGF0ZTogbmV3IERhdGUoMCkudG9JU09TdHJpbmcoKSxcbiAgICB1c2VySWQ6ICd1c2VyLWlkJyxcbiAgICBpbnRlbnQ6IHt9LFxuICAgIHBvbGljaWVzQ2hlY2tlZDogdHJ1ZSxcbiAgICB1bnNpZ25lZFR4czogW10sXG4gICAgdHJhbnNhY3Rpb25zOiBbYnVpbGRUcmFuc2FjdGlvbigpXSxcbiAgICBsYXRlc3Q6IHRydWUsXG4gICAgLi4ub3ZlcnJpZGVzLFxuICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZFR4UmVxdWVzdFdpdGhvdXRUcmFuc2FjdGlvbnMoKTogVHhSZXF1ZXN0IHtcbiAgY29uc3QgdHhSZXF1ZXN0ID0gYnVpbGRUeFJlcXVlc3QoKTtcbiAgZGVsZXRlIHR4UmVxdWVzdC50cmFuc2FjdGlvbnM7XG4gIHJldHVybiB0eFJlcXVlc3Q7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkVHJhbnNhY3Rpb24ob3ZlcnJpZGVzOiBQYXJ0aWFsPFR4UmVxdWVzdFRyYW5zYWN0aW9uPiA9IHt9KTogVHhSZXF1ZXN0VHJhbnNhY3Rpb24ge1xuICByZXR1cm4geyBzdGF0ZTogJ3BlbmRpbmdTaWduYXR1cmUnLCB1bnNpZ25lZFR4OiBidWlsZFVuc2lnbmVkVHJhbnNhY3Rpb24oKSwgc2lnbmF0dXJlU2hhcmVzOiBbXSwgLi4ub3ZlcnJpZGVzIH07XG59XG5cbmZ1bmN0aW9uIGJ1aWxkVW5zaWduZWRUcmFuc2FjdGlvbihvdmVycmlkZXM6IFBhcnRpYWw8VW5zaWduZWRUcmFuc2FjdGlvbj4gPSB7fSk6IFVuc2lnbmVkVHJhbnNhY3Rpb24ge1xuICByZXR1cm4geyBzZXJpYWxpemVkVHhIZXg6ICdhYWJiY2NkZCcsIHNpZ25hYmxlSGV4OiAnZGVhZGJlZWYnLCBkZXJpdmF0aW9uUGF0aDogJ20vMCcsIC4uLm92ZXJyaWRlcyB9O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIEVuY3J5cHRpb24gaGVscGVycyAobWlycm9ycyB0aGUgZWNkc2FNUEN2MiB0ZXN0IHBhdHRlcm4pXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZnVuY3Rpb24gZW5jcnlwdFdpdGhTamNsKHBhc3N3b3JkOiBzdHJpbmcsIGlucHV0OiBzdHJpbmcsIGFkYXRhPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc2FsdCA9IHJhbmRvbUJ5dGVzKDgpO1xuICBjb25zdCBpdiA9IHJhbmRvbUJ5dGVzKDE2KTtcbiAgcmV0dXJuIHNqY2wuZW5jcnlwdChwYXNzd29yZCwgaW5wdXQsIHtcbiAgICBzYWx0OiBbYnl0ZXNUb1dvcmQoc2FsdC5zdWJhcnJheSgwLCA0KSksIGJ5dGVzVG9Xb3JkKHNhbHQuc3ViYXJyYXkoNCkpXSxcbiAgICBpdjogW1xuICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoMCwgNCkpLFxuICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoNCwgOCkpLFxuICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoOCwgMTIpKSxcbiAgICAgIGJ5dGVzVG9Xb3JkKGl2LnN1YmFycmF5KDEyLCAxNikpLFxuICAgIF0sXG4gICAgLi4uKGFkYXRhICE9PSB1bmRlZmluZWQgPyB7IGFkYXRhIH0gOiB7fSksXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBieXRlc1RvV29yZChieXRlczogVWludDhBcnJheSk6IG51bWJlciB7XG4gIGlmIChieXRlcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2J5dGVzIG11c3QgaGF2ZSBsZW5ndGggNCcpO1xuICB9XG4gIHJldHVybiBieXRlcy5yZWR1Y2UoKG51bSwgYnl0ZSkgPT4gbnVtICogMHgxMDAgKyBieXRlLCAwKTtcbn1cbiJdfQ==
|