@bitgo-beta/abstract-substrate 1.0.1-beta.9 → 1.0.1-beta.90
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/CHANGELOG.md +41 -0
- package/dist/src/abstractSubstrateCoin.d.ts +20 -3
- package/dist/src/abstractSubstrateCoin.d.ts.map +1 -1
- package/dist/src/abstractSubstrateCoin.js +76 -14
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +16 -1
- package/dist/src/lib/constants.d.ts +2 -0
- package/dist/src/lib/constants.d.ts.map +1 -0
- package/dist/src/lib/constants.js +5 -0
- package/dist/src/lib/errors.d.ts +8 -0
- package/dist/src/lib/errors.d.ts.map +1 -0
- package/dist/src/lib/errors.js +19 -0
- package/dist/src/lib/iface.d.ts +140 -0
- package/dist/src/lib/iface.d.ts.map +1 -0
- package/dist/src/lib/iface.js +35 -0
- package/dist/src/lib/index.d.ts +12 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +61 -0
- package/dist/src/lib/keyPair.d.ts +24 -0
- package/dist/src/lib/keyPair.d.ts.map +1 -0
- package/dist/src/lib/keyPair.js +63 -0
- package/dist/src/lib/nativeTransferBuilder.d.ts +61 -0
- package/dist/src/lib/nativeTransferBuilder.d.ts.map +1 -0
- package/dist/src/lib/nativeTransferBuilder.js +147 -0
- package/dist/src/lib/singletonRegistry.d.ts +8 -0
- package/dist/src/lib/singletonRegistry.d.ts.map +1 -0
- package/dist/src/lib/singletonRegistry.js +20 -0
- package/dist/src/lib/transaction.d.ts +73 -0
- package/dist/src/lib/transaction.d.ts.map +1 -0
- package/dist/src/lib/transaction.js +424 -0
- package/dist/src/lib/transactionBuilder.d.ts +121 -0
- package/dist/src/lib/transactionBuilder.d.ts.map +1 -0
- package/dist/src/lib/transactionBuilder.js +334 -0
- package/dist/src/lib/transferBuilder.d.ts +6 -0
- package/dist/src/lib/transferBuilder.d.ts.map +1 -0
- package/dist/src/lib/transferBuilder.js +11 -0
- package/dist/src/lib/txnSchema.d.ts +9 -0
- package/dist/src/lib/txnSchema.d.ts.map +1 -0
- package/dist/src/lib/txnSchema.js +52 -0
- package/dist/src/lib/utils.d.ts +122 -0
- package/dist/src/lib/utils.d.ts.map +1 -0
- package/dist/src/lib/utils.js +227 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -5
|
@@ -0,0 +1,227 @@
|
|
|
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
|
+
exports.Utils = void 0;
|
|
7
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
8
|
+
const keyring_1 = require("@polkadot/keyring");
|
|
9
|
+
const decode_1 = require("@polkadot/keyring/pair/decode");
|
|
10
|
+
const Extrinsic_1 = require("@polkadot/types/extrinsic/v4/Extrinsic");
|
|
11
|
+
const util_1 = require("@polkadot/util");
|
|
12
|
+
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
13
|
+
const txwrapper_polkadot_1 = require("@substrate/txwrapper-polkadot");
|
|
14
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
15
|
+
const hi_base32_1 = __importDefault(require("hi-base32"));
|
|
16
|
+
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
17
|
+
const _1 = require(".");
|
|
18
|
+
class Utils {
|
|
19
|
+
/** @inheritdoc */
|
|
20
|
+
isValidAddress(address) {
|
|
21
|
+
try {
|
|
22
|
+
(0, keyring_1.encodeAddress)((0, util_1.isHex)(address) ? (0, util_1.hexToU8a)(address) : (0, keyring_1.decodeAddress)(address));
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** @inheritdoc */
|
|
30
|
+
isValidBlockId(hash) {
|
|
31
|
+
return (0, util_1.isHex)(hash, 256);
|
|
32
|
+
}
|
|
33
|
+
/** @inheritdoc */
|
|
34
|
+
isValidPrivateKey(key) {
|
|
35
|
+
try {
|
|
36
|
+
const decodedPrv = (0, util_1.hexToU8a)(key);
|
|
37
|
+
return decodedPrv.length === tweetnacl_1.default.sign.secretKeyLength / 2;
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** @inheritdoc */
|
|
44
|
+
isValidPublicKey(key) {
|
|
45
|
+
let pubKey = key;
|
|
46
|
+
// convert base58 pub key to hex format
|
|
47
|
+
// tss common pub is in base58 format and decodes to length of 32
|
|
48
|
+
if ((0, sdk_core_1.isBase58)(pubKey, 32)) {
|
|
49
|
+
const base58Decode = bs58_1.default.decode(pubKey);
|
|
50
|
+
pubKey = base58Decode.toString('hex');
|
|
51
|
+
}
|
|
52
|
+
return (0, sdk_core_1.isValidEd25519PublicKey)(pubKey);
|
|
53
|
+
}
|
|
54
|
+
/** @inheritdoc */
|
|
55
|
+
isValidSignature(signature) {
|
|
56
|
+
const signatureU8a = (0, util_1.u8aToU8a)(signature);
|
|
57
|
+
return [64, 65, 66].includes(signatureU8a.length);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Verifies the signature on a given message
|
|
61
|
+
*
|
|
62
|
+
* @param {string} signedMessage the signed message for the signature
|
|
63
|
+
* @param {string} signature the signature to verify
|
|
64
|
+
* @param {string} address the address of the signer
|
|
65
|
+
* @returns {boolean} whether the signature is valid or not
|
|
66
|
+
*/
|
|
67
|
+
verifySignature(signedMessage, signature, address) {
|
|
68
|
+
const publicKey = (0, keyring_1.decodeAddress)(address);
|
|
69
|
+
const hexPublicKey = (0, util_1.u8aToHex)(publicKey);
|
|
70
|
+
return (0, util_crypto_1.signatureVerify)(signedMessage, signature, hexPublicKey).isValid;
|
|
71
|
+
}
|
|
72
|
+
/** @inheritdoc */
|
|
73
|
+
isValidTransactionId(txId) {
|
|
74
|
+
return (0, util_1.isHex)(txId, 256);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* decodeSeed decodes a substrate seed
|
|
78
|
+
*
|
|
79
|
+
* @param {string} seed - the seed to be validated.
|
|
80
|
+
* @returns {Seed} - the object Seed
|
|
81
|
+
*/
|
|
82
|
+
decodeSeed(seed) {
|
|
83
|
+
const decoded = hi_base32_1.default.decode.asBytes(seed);
|
|
84
|
+
return {
|
|
85
|
+
seed: Buffer.from(decoded),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* keyPairFromSeed generates an object with secretKey and publicKey using the substrate sdk
|
|
90
|
+
* @param seed 32 bytes long seed
|
|
91
|
+
* @returns KeyPair
|
|
92
|
+
*/
|
|
93
|
+
keyPairFromSeed(seed) {
|
|
94
|
+
const keyring = new keyring_1.Keyring({ type: 'ed25519' });
|
|
95
|
+
const keyringPair = keyring.addFromSeed(seed);
|
|
96
|
+
const pairJson = keyringPair.toJson();
|
|
97
|
+
const decodedKeyPair = (0, decode_1.decodePair)('', (0, util_crypto_1.base64Decode)(pairJson.encoded), pairJson.encoding.type);
|
|
98
|
+
return new _1.KeyPair({ prv: Buffer.from(decodedKeyPair.secretKey).toString('hex') });
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Signing function. Implement this on the OFFLINE signing device.
|
|
102
|
+
*
|
|
103
|
+
* @param {KeyringPair} pair - The signing pair.
|
|
104
|
+
* @param {string} signingPayload - Payload to sign.
|
|
105
|
+
* @param {UnsignedTransaction} transaction - raw transaction to sign
|
|
106
|
+
* @param {Object} options
|
|
107
|
+
* @param {HexString} options.metadataRpc - metadata that is needed for substrate to sign
|
|
108
|
+
* @param {TypeRegistry} options.registry - metadata that is needed for substrate to sign
|
|
109
|
+
*/
|
|
110
|
+
createSignedTx(pair, signingPayload, transaction, options) {
|
|
111
|
+
const { registry, metadataRpc } = options;
|
|
112
|
+
const { signature } = registry
|
|
113
|
+
.createType('ExtrinsicPayload', signingPayload, {
|
|
114
|
+
version: Extrinsic_1.EXTRINSIC_VERSION,
|
|
115
|
+
})
|
|
116
|
+
.sign(pair);
|
|
117
|
+
// Serialize a signed transaction.
|
|
118
|
+
return this.serializeSignedTransaction(transaction, signature, metadataRpc, registry);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Serializes the signed transaction
|
|
122
|
+
*
|
|
123
|
+
* @param transaction Transaction to serialize
|
|
124
|
+
* @param signature Signature of the message
|
|
125
|
+
* @param metadataRpc Network metadata
|
|
126
|
+
* @param registry Transaction registry
|
|
127
|
+
* @returns string Serialized transaction
|
|
128
|
+
*/
|
|
129
|
+
serializeSignedTransaction(transaction, signature, metadataRpc, registry) {
|
|
130
|
+
return txwrapper_polkadot_1.construct.signedTx(transaction, signature, {
|
|
131
|
+
metadataRpc,
|
|
132
|
+
registry,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Decodes the substrate address from the given format
|
|
137
|
+
*
|
|
138
|
+
* @param {string} address
|
|
139
|
+
* @param {number} [ss58Format]
|
|
140
|
+
* @returns {string}
|
|
141
|
+
*/
|
|
142
|
+
decodeSubstrateAddress(address, ss58Format) {
|
|
143
|
+
const keypair = new _1.KeyPair({ pub: Buffer.from((0, keyring_1.decodeAddress)(address, undefined, ss58Format)).toString('hex') });
|
|
144
|
+
return keypair.getAddress(ss58Format);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Decodes the substrate address from the given format
|
|
148
|
+
*
|
|
149
|
+
* @param {string} address
|
|
150
|
+
* @param {number} [ss58Format]
|
|
151
|
+
* @returns {string}
|
|
152
|
+
*/
|
|
153
|
+
encodeSubstrateAddress(address, ss58Format) {
|
|
154
|
+
return (0, keyring_1.encodeAddress)(address, ss58Format);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Retrieves the txHash of a signed txHex
|
|
158
|
+
*
|
|
159
|
+
* @param txHex signed transaction hex
|
|
160
|
+
* @returns {string}
|
|
161
|
+
*/
|
|
162
|
+
getTxHash(txHex) {
|
|
163
|
+
return txwrapper_polkadot_1.construct.txHash(txHex);
|
|
164
|
+
}
|
|
165
|
+
isSigningPayload(payload) {
|
|
166
|
+
return payload.blockHash !== undefined;
|
|
167
|
+
}
|
|
168
|
+
isTransfer(arg) {
|
|
169
|
+
return arg.dest?.id !== undefined && arg.value !== undefined;
|
|
170
|
+
}
|
|
171
|
+
isTransferAll(arg) {
|
|
172
|
+
return arg.dest?.id !== undefined && arg.keepAlive !== undefined;
|
|
173
|
+
}
|
|
174
|
+
isAddStake(arg) {
|
|
175
|
+
return (arg.amountStaked !== undefined &&
|
|
176
|
+
arg.hotkey !== undefined &&
|
|
177
|
+
arg.netuid !== undefined);
|
|
178
|
+
}
|
|
179
|
+
isRemoveStake(arg) {
|
|
180
|
+
return (arg.amountUnstaked !== undefined &&
|
|
181
|
+
arg.hotkey !== undefined &&
|
|
182
|
+
arg.netuid !== undefined);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* extracts and returns the signature in hex format given a raw signed transaction
|
|
186
|
+
*
|
|
187
|
+
* @param {string} rawTx signed raw transaction
|
|
188
|
+
* @param options registry substrate registry used to retrieve the signature
|
|
189
|
+
*/
|
|
190
|
+
recoverSignatureFromRawTx(rawTx, options) {
|
|
191
|
+
const { registry } = options;
|
|
192
|
+
const methodCall = registry.createType('Extrinsic', rawTx, {
|
|
193
|
+
isSigned: true,
|
|
194
|
+
});
|
|
195
|
+
let signature = (0, util_1.u8aToHex)(methodCall.signature);
|
|
196
|
+
// remove 0x from the signature since this is how it's returned from TSS signing
|
|
197
|
+
if (signature.startsWith('0x')) {
|
|
198
|
+
signature = signature.substr(2);
|
|
199
|
+
}
|
|
200
|
+
return signature;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Decodes the dot address from the given format
|
|
204
|
+
*
|
|
205
|
+
* @param {string} address
|
|
206
|
+
* @param {number} [ss58Format]
|
|
207
|
+
* @returns {KeyPair}
|
|
208
|
+
*/
|
|
209
|
+
decodeSubstrateAddressToKeyPair(address, ss58Format) {
|
|
210
|
+
return new _1.KeyPair({ pub: Buffer.from((0, keyring_1.decodeAddress)(address, undefined, ss58Format)).toString('hex') });
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Checks whether the given input is a hex string with with 0 value
|
|
214
|
+
* used to check whether a given transaction is immortal or mortal
|
|
215
|
+
* @param hexValue
|
|
216
|
+
*/
|
|
217
|
+
isZeroHex(hexValue) {
|
|
218
|
+
return hexValue === '0x00';
|
|
219
|
+
}
|
|
220
|
+
getMaterial(networkType) {
|
|
221
|
+
throw new Error('Method not implemented.');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
exports.Utils = Utils;
|
|
225
|
+
const utils = new Utils();
|
|
226
|
+
exports.default = utils;
|
|
227
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG1EQUEwRjtBQUUxRiwrQ0FBMEU7QUFDMUUsMERBQTJEO0FBRTNELHNFQUEyRTtBQUMzRSx5Q0FBcUU7QUFDckUsdURBQXNFO0FBR3RFLHNFQUEwRDtBQUMxRCxnREFBd0I7QUFDeEIsMERBQStCO0FBQy9CLDBEQUE2QjtBQUM3Qix3QkFBNEI7QUFHNUIsTUFBYSxLQUFLO0lBQ2hCLGtCQUFrQjtJQUNsQixjQUFjLENBQUMsT0FBZTtRQUM1QixJQUFJLENBQUM7WUFDSCxJQUFBLHVCQUFhLEVBQUMsSUFBQSxZQUFLLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUEsZUFBUSxFQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFBLHVCQUFhLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUMzRSxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO0lBQ0gsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixjQUFjLENBQUMsSUFBWTtRQUN6QixPQUFPLElBQUEsWUFBSyxFQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGlCQUFpQixDQUFDLEdBQVc7UUFDM0IsSUFBSSxDQUFDO1lBQ0gsTUFBTSxVQUFVLEdBQUcsSUFBQSxlQUFRLEVBQUMsR0FBRyxDQUFDLENBQUM7WUFDakMsT0FBTyxVQUFVLENBQUMsTUFBTSxLQUFLLG1CQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxDQUFDLENBQUM7UUFDN0QsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFD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QUMsSUFBQSx1QkFBYSxFQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzFHLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsU0FBUyxDQUFDLFFBQWdCO1FBQ3hCLE9BQU8sUUFBUSxLQUFLLE1BQU0sQ0FBQztJQUM3QixDQUFDO0lBRUQsV0FBVyxDQUFDLFdBQXdCO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztJQUM3QyxDQUFDO0NBQ0Y7QUEvT0Qsc0JBK09DO0FBRUQsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztBQUUxQixrQkFBZSxLQUFLLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCYXNlVXRpbHMsIGlzQmFzZTU4LCBpc1ZhbGlkRWQyNTUxOVB1YmxpY0tleSwgU2VlZCB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7IE5ldHdvcmtUeXBlIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgeyBkZWNvZGVBZGRyZXNzLCBlbmNvZGVBZGRyZXNzLCBLZXlyaW5nIH0gZnJvbSAnQHBvbGthZG90L2tleXJpbmcnO1xuaW1wb3J0IHsgZGVjb2RlUGFpciB9IGZyb20gJ0Bwb2xrYWRvdC9rZXlyaW5nL3BhaXIvZGVjb2RlJztcbmltcG9ydCB7IEtleXJpbmdQYWlyIH0gZnJvbSAnQHBvbGthZG90L2tleXJpbmcvdHlwZXMnO1xuaW1wb3J0IHsgRVhUUklOU0lDX1ZFUlNJT04gfSBmcm9tICdAcG9sa2Fkb3QvdHlwZXMvZXh0cmluc2ljL3Y0L0V4dHJpbnNpYyc7XG5pbXBvcnQgeyBoZXhUb1U4YSwgaXNIZXgsIHU4YVRvSGV4LCB1OGFUb1U4YSB9IGZyb20gJ0Bwb2xrYWRvdC91dGlsJztcbmltcG9ydCB7IGJhc2U2NERlY29kZSwgc2lnbmF0dXJlVmVyaWZ5IH0gZnJvbSAnQHBvbGthZG90L3V0aWwtY3J5cHRvJztcbmltcG9ydCB7IFVuc2lnbmVkVHJhbnNhY3Rpb24gfSBmcm9tICdAc3Vic3RyYXRlL3R4d3JhcHBlci1jb3JlJztcbmltcG9ydCB7IERlY29kZWRTaWduZWRUeCwgRGVjb2RlZFNpZ25pbmdQYXlsb2FkLCBUeXBlUmVnaXN0cnkgfSBmcm9tICdAc3Vic3RyYXRlL3R4d3JhcHBlci1jb3JlL2xpYi90eXBlcyc7XG5pbXBvcnQgeyBjb25zdHJ1Y3QgfSBmcm9tICdAc3Vic3RyYXRlL3R4d3JhcHBlci1wb2xrYWRvdCc7XG5pbXBvcnQgYnM1OCBmcm9tICdiczU4JztcbmltcG9ydCBiYXNlMzIgZnJvbSAnaGktYmFzZTMyJztcbmltcG9ydCBuYWNsIGZyb20gJ3R3ZWV0bmFjbCc7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLic7XG5pbXBvcnQgeyBIZXhTdHJpbmcsIE1hdGVyaWFsLCBUcmFuc2ZlckFsbEFyZ3MsIFRyYW5zZmVyQXJncywgVHhNZXRob2QsIEFkZFN0YWtlQXJncywgUmVtb3ZlU3Rha2VBcmdzIH0gZnJvbSAnLi9pZmFjZSc7XG5cbmV4cG9ydCBjbGFzcyBVdGlscyBpbXBsZW1lbnRzIEJhc2VVdGlscyB7XG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgZW5jb2RlQWRkcmVzcyhpc0hleChhZGRyZXNzKSA/IGhleFRvVThhKGFkZHJlc3MpIDogZGVjb2RlQWRkcmVzcyhhZGRyZXNzKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkQmxvY2tJZChoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gaXNIZXgoaGFzaCwgMjU2KTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkUHJpdmF0ZUtleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZWNvZGVkUHJ2ID0gaGV4VG9VOGEoa2V5KTtcbiAgICAgIHJldHVybiBkZWNvZGVkUHJ2Lmxlbmd0aCA9PT0gbmFjbC5zaWduLnNlY3JldEtleUxlbmd0aCAvIDI7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkUHVibGljS2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgbGV0IHB1YktleSA9IGtleTtcblxuICAgIC8vIGNvbnZlcnQgYmFzZTU4IHB1YiBrZXkgdG8gaGV4IGZvcm1hdFxuICAgIC8vIHRzcyBjb21tb24gcHViIGlzIGluIGJhc2U1OCBmb3JtYXQgYW5kIGRlY29kZXMgdG8gbGVuZ3RoIG9mIDMyXG4gICAgaWYgKGlzQmFzZTU4KHB1YktleSwgMzIpKSB7XG4gICAgICBjb25zdCBiYXNlNThEZWNvZGUgPSBiczU4LmRlY29kZShwdWJLZXkpO1xuICAgICAgcHViS2V5ID0gYmFzZTU4RGVjb2RlLnRvU3RyaW5nKCdoZXgnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaXNWYWxpZEVkMjU1MTlQdWJsaWNLZXkocHViS2V5KTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBpc1ZhbGlkU2lnbmF0dXJlKHNpZ25hdHVyZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc2lnbmF0dXJlVThhID0gdThhVG9VOGEoc2lnbmF0dXJlKTtcbiAgICByZXR1cm4gWzY0LCA2NSwgNjZdLmluY2x1ZGVzKHNpZ25hdHVyZVU4YS5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIHRoZSBzaWduYXR1cmUgb24gYSBnaXZlbiBtZXNzYWdlXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzaWduZWRNZXNzYWdlIHRoZSBzaWduZWQgbWVzc2FnZSBmb3IgdGhlIHNpZ25hdHVyZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2lnbmF0dXJlIHRoZSBzaWduYXR1cmUgdG8gdmVyaWZ5XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzIHRoZSBhZGRyZXNzIG9mIHRoZSBzaWduZXJcbiAgICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgdGhlIHNpZ25hdHVyZSBpcyB2YWxpZCBvciBub3RcbiAgICovXG4gIHZlcmlmeVNpZ25hdHVyZShzaWduZWRNZXNzYWdlOiBzdHJpbmcsIHNpZ25hdHVyZTogc3RyaW5nLCBhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBwdWJsaWNLZXkgPSBkZWNvZGVBZGRyZXNzKGFkZHJlc3MpO1xuICAgIGNvbnN0IGhleFB1YmxpY0tleSA9IHU4YVRvSGV4KHB1YmxpY0tleSk7XG5cbiAgICByZXR1cm4gc2lnbmF0dXJlVmVyaWZ5KHNpZ25lZE1lc3NhZ2UsIHNpZ25hdHVyZSwgaGV4UHVibGljS2V5KS5pc1ZhbGlkO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGlzVmFsaWRUcmFuc2FjdGlvbklkKHR4SWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBpc0hleCh0eElkLCAyNTYpO1xuICB9XG5cbiAgLyoqXG4gICAqIGRlY29kZVNlZWQgZGVjb2RlcyBhIHN1YnN0cmF0ZSBzZWVkXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzZWVkIC0gdGhlIHNlZWQgdG8gYmUgdmFsaWRhdGVkLlxuICAgKiBAcmV0dXJucyB7U2VlZH0gLSB0aGUgb2JqZWN0IFNlZWRcbiAgICovXG4gIGRlY29kZVNlZWQoc2VlZDogc3RyaW5nKTogU2VlZCB7XG4gICAgY29uc3QgZGVjb2RlZCA9IGJhc2UzMi5kZWNvZGUuYXNCeXRlcyhzZWVkKTtcbiAgICByZXR1cm4ge1xuICAgICAgc2VlZDogQnVmZmVyLmZyb20oZGVjb2RlZCksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBrZXlQYWlyRnJvbVNlZWQgZ2VuZXJhdGVzIGFuIG9iamVjdCB3aXRoIHNlY3JldEtleSBhbmQgcHVibGljS2V5IHVzaW5nIHRoZSBzdWJzdHJhdGUgc2RrXG4gICAqIEBwYXJhbSBzZWVkIDMyIGJ5dGVzIGxvbmcgc2VlZFxuICAgKiBAcmV0dXJucyBLZXlQYWlyXG4gICAqL1xuICBrZXlQYWlyRnJvbVNlZWQoc2VlZDogVWludDhBcnJheSk6IEtleVBhaXIge1xuICAgIGNvbnN0IGtleXJpbmcgPSBuZXcgS2V5cmluZyh7IHR5cGU6ICdlZDI1NTE5JyB9KTtcbiAgICBjb25zdCBrZXlyaW5nUGFpciA9IGtleXJpbmcuYWRkRnJvbVNlZWQoc2VlZCk7XG4gICAgY29uc3QgcGFpckpzb24gPSBrZXlyaW5nUGFpci50b0pzb24oKTtcbiAgICBjb25zdCBkZWNvZGVkS2V5UGFpciA9IGRlY29kZVBhaXIoJycsIGJhc2U2NERlY29kZShwYWlySnNvbi5lbmNvZGVkKSwgcGFpckpzb24uZW5jb2RpbmcudHlwZSk7XG4gICAgcmV0dXJuIG5ldyBLZXlQYWlyKHsgcHJ2OiBCdWZmZXIuZnJvbShkZWNvZGVkS2V5UGFpci5zZWNyZXRLZXkpLnRvU3RyaW5nKCdoZXgnKSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduaW5nIGZ1bmN0aW9uLiBJbXBsZW1lbnQgdGhpcyBvbiB0aGUgT0ZGTElORSBzaWduaW5nIGRldmljZS5cbiAgICpcbiAgICogQHBhcmFtIHtLZXlyaW5nUGFpcn0gcGFpciAtIFRoZSBzaWduaW5nIHBhaXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzaWduaW5nUGF5bG9hZCAtIFBheWxvYWQgdG8gc2lnbi5cbiAgICogQHBhcmFtIHtVbnNpZ25lZFRyYW5zYWN0aW9ufSB0cmFuc2FjdGlvbiAtIHJhdyB0cmFuc2FjdGlvbiB0byBzaWduXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7SGV4U3RyaW5nfSBvcHRpb25zLm1ldGFkYXRhUnBjIC0gbWV0YWRhdGEgdGhhdCBpcyBuZWVkZWQgZm9yIHN1YnN0cmF0ZSB0byBzaWduXG4gICAqIEBwYXJhbSB7VHlwZVJlZ2lzdHJ5fSBvcHRpb25zLnJlZ2lzdHJ5IC0gbWV0YWRhdGEgdGhhdCBpcyBuZWVkZWQgZm9yIHN1YnN0cmF0ZSB0byBzaWduXG4gICAqL1xuICBjcmVhdGVTaWduZWRUeChcbiAgICBwYWlyOiBLZXlyaW5nUGFpcixcbiAgICBzaWduaW5nUGF5bG9hZDogc3RyaW5nLFxuICAgIHRyYW5zYWN0aW9uOiBVbnNpZ25lZFRyYW5zYWN0aW9uLFxuICAgIG9wdGlvbnM6IHsgbWV0YWRhdGFScGM6IEhleFN0cmluZzsgcmVnaXN0cnk6IFR5cGVSZWdpc3RyeSB9XG4gICk6IHN0cmluZyB7XG4gICAgY29uc3QgeyByZWdpc3RyeSwgbWV0YWRhdGFScGMgfSA9IG9wdGlvbnM7XG4gICAgY29uc3QgeyBzaWduYXR1cmUgfSA9IHJlZ2lzdHJ5XG4gICAgICAuY3JlYXRlVHlwZSgnRXh0cmluc2ljUGF5bG9hZCcsIHNpZ25pbmdQYXlsb2FkLCB7XG4gICAgICAgIHZlcnNpb246IEVYVFJJTlNJQ19WRVJTSU9OLFxuICAgICAgfSlcbiAgICAgIC5zaWduKHBhaXIpO1xuXG4gICAgLy8gU2VyaWFsaXplIGEgc2lnbmVkIHRyYW5zYWN0aW9uLlxuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZVNpZ25lZFRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uLCBzaWduYXR1cmUsIG1ldGFkYXRhUnBjLCByZWdpc3RyeSk7XG4gIH1cblxuICAvKipcbiAgICogU2VyaWFsaXplcyB0aGUgc2lnbmVkIHRyYW5zYWN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB0cmFuc2FjdGlvbiBUcmFuc2FjdGlvbiB0byBzZXJpYWxpemVcbiAgICogQHBhcmFtIHNpZ25hdHVyZSBTaWduYXR1cmUgb2YgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIG1ldGFkYXRhUnBjIE5ldHdvcmsgbWV0YWRhdGFcbiAgICogQHBhcmFtIHJlZ2lzdHJ5IFRyYW5zYWN0aW9uIHJlZ2lzdHJ5XG4gICAqIEByZXR1cm5zIHN0cmluZyBTZXJpYWxpemVkIHRyYW5zYWN0aW9uXG4gICAqL1xuICBzZXJpYWxpemVTaWduZWRUcmFuc2FjdGlvbih0cmFuc2FjdGlvbiwgc2lnbmF0dXJlLCBtZXRhZGF0YVJwYzogYDB4JHtzdHJpbmd9YCwgcmVnaXN0cnkpOiBzdHJpbmcge1xuICAgIHJldHVybiBjb25zdHJ1Y3Quc2lnbmVkVHgodHJhbnNhY3Rpb24sIHNpZ25hdHVyZSwge1xuICAgICAgbWV0YWRhdGFScGMsXG4gICAgICByZWdpc3RyeSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNvZGVzIHRoZSBzdWJzdHJhdGUgYWRkcmVzcyBmcm9tIHRoZSBnaXZlbiBmb3JtYXRcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFkZHJlc3NcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtzczU4Rm9ybWF0XVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgZGVjb2RlU3Vic3RyYXRlQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcsIHNzNThGb3JtYXQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3Qga2V5cGFpciA9IG5ldyBLZXlQYWlyKHsgcHViOiBCdWZmZXIuZnJvbShkZWNvZGVBZGRyZXNzKGFkZHJlc3MsIHVuZGVmaW5lZCwgc3M1OEZvcm1hdCkpLnRvU3RyaW5nKCdoZXgnKSB9KTtcbiAgICByZXR1cm4ga2V5cGFpci5nZXRBZGRyZXNzKHNzNThGb3JtYXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY29kZXMgdGhlIHN1YnN0cmF0ZSBhZGRyZXNzIGZyb20gdGhlIGdpdmVuIGZvcm1hdFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWRkcmVzc1xuICAgKiBAcGFyYW0ge251bWJlcn0gW3NzNThGb3JtYXRdXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICBlbmNvZGVTdWJzdHJhdGVBZGRyZXNzKGFkZHJlc3M6IHN0cmluZywgc3M1OEZvcm1hdD86IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIGVuY29kZUFkZHJlc3MoYWRkcmVzcywgc3M1OEZvcm1hdCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSB0eEhhc2ggb2YgYSBzaWduZWQgdHhIZXhcbiAgICpcbiAgICogQHBhcmFtIHR4SGV4IHNpZ25lZCB0cmFuc2FjdGlvbiBoZXhcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIGdldFR4SGFzaCh0eEhleDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY29uc3RydWN0LnR4SGFzaCh0eEhleCk7XG4gIH1cblxuICBpc1NpZ25pbmdQYXlsb2FkKHBheWxvYWQ6IERlY29kZWRTaWduaW5nUGF5bG9hZCB8IERlY29kZWRTaWduZWRUeCk6IHBheWxvYWQgaXMgRGVjb2RlZFNpZ25pbmdQYXlsb2FkIHtcbiAgICByZXR1cm4gKHBheWxvYWQgYXMgRGVjb2RlZFNpZ25pbmdQYXlsb2FkKS5ibG9ja0hhc2ggIT09IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlzVHJhbnNmZXIoYXJnOiBUeE1ldGhvZFsnYXJncyddKTogYXJnIGlzIFRyYW5zZmVyQXJncyB7XG4gICAgcmV0dXJuIChhcmcgYXMgVHJhbnNmZXJBcmdzKS5kZXN0Py5pZCAhPT0gdW5kZWZpbmVkICYmIChhcmcgYXMgVHJhbnNmZXJBcmdzKS52YWx1ZSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgaXNUcmFuc2ZlckFsbChhcmc6IFR4TWV0aG9kWydhcmdzJ10pOiBhcmcgaXMgVHJhbnNmZXJBbGxBcmdzIHtcbiAgICByZXR1cm4gKGFyZyBhcyBUcmFuc2ZlckFsbEFyZ3MpLmRlc3Q/LmlkICE9PSB1bmRlZmluZWQgJiYgKGFyZyBhcyBUcmFuc2ZlckFsbEFyZ3MpLmtlZXBBbGl2ZSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgaXNBZGRTdGFrZShhcmc6IFR4TWV0aG9kWydhcmdzJ10pOiBhcmcgaXMgQWRkU3Rha2VBcmdzIHtcbiAgICByZXR1cm4gKFxuICAgICAgKGFyZyBhcyBBZGRTdGFrZUFyZ3MpLmFtb3VudFN0YWtlZCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAoYXJnIGFzIEFkZFN0YWtlQXJncykuaG90a2V5ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIChhcmcgYXMgQWRkU3Rha2VBcmdzKS5uZXR1aWQgIT09IHVuZGVmaW5lZFxuICAgICk7XG4gIH1cblxuICBpc1JlbW92ZVN0YWtlKGFyZzogVHhNZXRob2RbJ2FyZ3MnXSk6IGFyZyBpcyBSZW1vdmVTdGFrZUFyZ3Mge1xuICAgIHJldHVybiAoXG4gICAgICAoYXJnIGFzIFJlbW92ZVN0YWtlQXJncykuYW1vdW50VW5zdGFrZWQgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKGFyZyBhcyBSZW1vdmVTdGFrZUFyZ3MpLmhvdGtleSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAoYXJnIGFzIFJlbW92ZVN0YWtlQXJncykubmV0dWlkICE9PSB1bmRlZmluZWRcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIGV4dHJhY3RzIGFuZCByZXR1cm5zIHRoZSBzaWduYXR1cmUgaW4gaGV4IGZvcm1hdCBnaXZlbiBhIHJhdyBzaWduZWQgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHJhd1R4IHNpZ25lZCByYXcgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIG9wdGlvbnMgcmVnaXN0cnkgc3Vic3RyYXRlIHJlZ2lzdHJ5IHVzZWQgdG8gcmV0cmlldmUgdGhlIHNpZ25hdHVyZVxuICAgKi9cbiAgcmVjb3ZlclNpZ25hdHVyZUZyb21SYXdUeChyYXdUeDogc3RyaW5nLCBvcHRpb25zOiB7IHJlZ2lzdHJ5OiBUeXBlUmVnaXN0cnkgfSk6IHN0cmluZyB7XG4gICAgY29uc3QgeyByZWdpc3RyeSB9ID0gb3B0aW9ucztcbiAgICBjb25zdCBtZXRob2RDYWxsID0gcmVnaXN0cnkuY3JlYXRlVHlwZSgnRXh0cmluc2ljJywgcmF3VHgsIHtcbiAgICAgIGlzU2lnbmVkOiB0cnVlLFxuICAgIH0pO1xuICAgIGxldCBzaWduYXR1cmUgPSB1OGFUb0hleChtZXRob2RDYWxsLnNpZ25hdHVyZSkgYXMgc3RyaW5nO1xuXG4gICAgLy8gcmVtb3ZlIDB4IGZyb20gdGhlIHNpZ25hdHVyZSBzaW5jZSB0aGlzIGlzIGhvdyBpdCdzIHJldHVybmVkIGZyb20gVFNTIHNpZ25pbmdcbiAgICBpZiAoc2lnbmF0dXJlLnN0YXJ0c1dpdGgoJzB4JykpIHtcbiAgICAgIHNpZ25hdHVyZSA9IHNpZ25hdHVyZS5zdWJzdHIoMik7XG4gICAgfVxuICAgIHJldHVybiBzaWduYXR1cmU7XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlcyB0aGUgZG90IGFkZHJlc3MgZnJvbSB0aGUgZ2l2ZW4gZm9ybWF0XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhZGRyZXNzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbc3M1OEZvcm1hdF1cbiAgICogQHJldHVybnMge0tleVBhaXJ9XG4gICAqL1xuICBkZWNvZGVTdWJzdHJhdGVBZGRyZXNzVG9LZXlQYWlyKGFkZHJlc3M6IHN0cmluZywgc3M1OEZvcm1hdD86IG51bWJlcik6IEtleVBhaXIge1xuICAgIHJldHVybiBuZXcgS2V5UGFpcih7IHB1YjogQnVmZmVyLmZyb20oZGVjb2RlQWRkcmVzcyhhZGRyZXNzLCB1bmRlZmluZWQsIHNzNThGb3JtYXQpKS50b1N0cmluZygnaGV4JykgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIGdpdmVuIGlucHV0IGlzIGEgaGV4IHN0cmluZyB3aXRoIHdpdGggMCB2YWx1ZVxuICAgKiB1c2VkIHRvIGNoZWNrIHdoZXRoZXIgYSBnaXZlbiB0cmFuc2FjdGlvbiBpcyBpbW1vcnRhbCBvciBtb3J0YWxcbiAgICogQHBhcmFtIGhleFZhbHVlXG4gICAqL1xuICBpc1plcm9IZXgoaGV4VmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBoZXhWYWx1ZSA9PT0gJzB4MDAnO1xuICB9XG5cbiAgZ2V0TWF0ZXJpYWwobmV0d29ya1R5cGU6IE5ldHdvcmtUeXBlKTogTWF0ZXJpYWwge1xuICAgIHRocm93IG5ldyBFcnJvcignTWV0aG9kIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxufVxuXG5jb25zdCB1dGlscyA9IG5ldyBVdGlscygpO1xuXG5leHBvcnQgZGVmYXVsdCB1dGlscztcbiJdfQ==
|