@bitgo-beta/sdk-core 8.2.1-beta.209 → 8.2.1-beta.2091
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/baseTransaction.d.ts +0 -1
- package/dist/src/account-lib/baseCoin/baseTransaction.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/baseTransactionBuilder.d.ts +3 -3
- package/dist/src/account-lib/baseCoin/baseTransactionBuilder.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/baseTransactionBuilder.js +4 -3
- package/dist/src/account-lib/baseCoin/ed25519KeyPair.d.ts +1 -0
- package/dist/src/account-lib/baseCoin/ed25519KeyPair.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/ed25519KeyPair.js +43 -31
- package/dist/src/account-lib/baseCoin/enum.d.ts +59 -5
- package/dist/src/account-lib/baseCoin/enum.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/enum.js +112 -10
- package/dist/src/account-lib/baseCoin/errors.d.ts +3 -0
- package/dist/src/account-lib/baseCoin/errors.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/errors.js +8 -2
- package/dist/src/account-lib/baseCoin/iface.d.ts +19 -35
- package/dist/src/account-lib/baseCoin/iface.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/iface.js +26 -18
- package/dist/src/account-lib/baseCoin/index.d.ts +1 -1
- package/dist/src/account-lib/baseCoin/index.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/index.js +8 -5
- package/dist/src/account-lib/baseCoin/messages/baseMessage.d.ts +88 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessage.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessage.js +154 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessageBuilder.d.ts +67 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessageBuilder.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessageBuilder.js +144 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessageBuilderFactory.d.ts +33 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessageBuilderFactory.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/baseMessageBuilderFactory.js +45 -0
- package/dist/src/account-lib/baseCoin/messages/iface.d.ts +164 -0
- package/dist/src/account-lib/baseCoin/messages/iface.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/iface.js +3 -0
- package/dist/src/account-lib/baseCoin/messages/index.d.ts +6 -0
- package/dist/src/account-lib/baseCoin/messages/index.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/index.js +22 -0
- package/dist/src/account-lib/baseCoin/messages/simple/index.d.ts +3 -0
- package/dist/src/account-lib/baseCoin/messages/simple/index.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/simple/index.js +19 -0
- package/dist/src/account-lib/baseCoin/messages/simple/simpleMessage.d.ts +13 -0
- package/dist/src/account-lib/baseCoin/messages/simple/simpleMessage.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/simple/simpleMessage.js +28 -0
- package/dist/src/account-lib/baseCoin/messages/simple/simpleMessageBuilder.d.ts +21 -0
- package/dist/src/account-lib/baseCoin/messages/simple/simpleMessageBuilder.d.ts.map +1 -0
- package/dist/src/account-lib/baseCoin/messages/simple/simpleMessageBuilder.js +28 -0
- package/dist/src/account-lib/baseCoin/secp256k1ExtendedKeyPair.d.ts +1 -2
- package/dist/src/account-lib/baseCoin/secp256k1ExtendedKeyPair.d.ts.map +1 -1
- package/dist/src/account-lib/baseCoin/secp256k1ExtendedKeyPair.js +38 -26
- package/dist/src/account-lib/index.d.ts +0 -1
- package/dist/src/account-lib/index.d.ts.map +1 -1
- package/dist/src/account-lib/index.js +23 -10
- package/dist/src/account-lib/mpc/index.d.ts +1 -1
- package/dist/src/account-lib/mpc/index.d.ts.map +1 -1
- package/dist/src/account-lib/mpc/index.js +6 -2
- package/dist/src/account-lib/mpc/tss/ecdsa/ecdsa.d.ts +2 -3
- package/dist/src/account-lib/mpc/tss/ecdsa/ecdsa.d.ts.map +1 -1
- package/dist/src/account-lib/mpc/tss/ecdsa/ecdsa.js +376 -354
- package/dist/src/account-lib/mpc/tss/ecdsa/index.js +23 -9
- package/dist/src/account-lib/mpc/tss/ecdsa/rangeproof.d.ts +2 -2
- package/dist/src/account-lib/mpc/tss/ecdsa/rangeproof.d.ts.map +1 -1
- package/dist/src/account-lib/mpc/tss/ecdsa/rangeproof.js +3 -3
- package/dist/src/account-lib/mpc/tss/ecdsa/types.d.ts +46 -53
- package/dist/src/account-lib/mpc/tss/ecdsa/types.d.ts.map +1 -1
- package/dist/src/account-lib/mpc/tss/ecdsa/types.js +1 -1
- package/dist/src/account-lib/mpc/tss/eddsa/eddsa.d.ts +0 -1
- package/dist/src/account-lib/mpc/tss/eddsa/eddsa.d.ts.map +1 -1
- package/dist/src/account-lib/mpc/tss/eddsa/eddsa.js +66 -69
- package/dist/src/account-lib/mpc/tss/eddsa/index.js +23 -9
- package/dist/src/account-lib/mpc/tss/eddsa/types.d.ts +1 -1
- package/dist/src/account-lib/mpc/tss/eddsa/types.d.ts.map +1 -1
- package/dist/src/account-lib/mpc/tss/eddsa/types.js +1 -1
- package/dist/src/account-lib/mpc/tss/index.js +23 -9
- package/dist/src/account-lib/mpc/util.d.ts +7 -1
- package/dist/src/account-lib/mpc/util.d.ts.map +1 -1
- package/dist/src/account-lib/mpc/util.js +24 -1
- package/dist/src/account-lib/staking/index.js +6 -2
- package/dist/src/account-lib/staking/utils.js +3 -3
- package/dist/src/account-lib/util/crypto.d.ts +8 -2
- package/dist/src/account-lib/util/crypto.d.ts.map +1 -1
- package/dist/src/account-lib/util/crypto.js +69 -38
- package/dist/src/api/bip32path.js +2 -3
- package/dist/src/api/index.js +6 -2
- package/dist/src/api/types.d.ts +37 -0
- package/dist/src/api/types.d.ts.map +1 -1
- package/dist/src/api/types.js +8 -1
- package/dist/src/bitgo/address-book/address-book.d.ts.map +1 -1
- package/dist/src/bitgo/address-book/address-book.js +20 -12
- package/dist/src/bitgo/address-book/index.js +6 -2
- package/dist/src/bitgo/address-book/types.d.ts +36 -36
- package/dist/src/bitgo/address-book/types.d.ts.map +1 -1
- package/dist/src/bitgo/baseCoin/baseCoin.d.ts +123 -13
- package/dist/src/bitgo/baseCoin/baseCoin.d.ts.map +1 -1
- package/dist/src/bitgo/baseCoin/baseCoin.js +200 -16
- package/dist/src/bitgo/baseCoin/iBaseCoin.d.ts +301 -31
- package/dist/src/bitgo/baseCoin/iBaseCoin.d.ts.map +1 -1
- package/dist/src/bitgo/baseCoin/iBaseCoin.js +14 -3
- package/dist/src/bitgo/baseCoin/index.js +6 -2
- package/dist/src/bitgo/bip32util.d.ts +3 -16
- package/dist/src/bitgo/bip32util.d.ts.map +1 -1
- package/dist/src/bitgo/bip32util.js +4 -56
- package/dist/src/bitgo/bitcoin.d.ts +0 -1
- package/dist/src/bitgo/bitcoin.d.ts.map +1 -1
- package/dist/src/bitgo/bitcoin.js +26 -13
- package/dist/src/bitgo/bitgoBase.d.ts +17 -4
- package/dist/src/bitgo/bitgoBase.d.ts.map +1 -1
- package/dist/src/bitgo/bitgoBase.js +1 -1
- package/dist/src/bitgo/coinFactory.d.ts +24 -3
- package/dist/src/bitgo/coinFactory.d.ts.map +1 -1
- package/dist/src/bitgo/coinFactory.js +35 -3
- package/dist/src/bitgo/config.d.ts +3 -101
- package/dist/src/bitgo/config.d.ts.map +1 -1
- package/dist/src/bitgo/config.js +26 -15
- package/dist/src/bitgo/defi/defiVault.d.ts +171 -0
- package/dist/src/bitgo/defi/defiVault.d.ts.map +1 -0
- package/dist/src/bitgo/defi/defiVault.js +445 -0
- package/dist/src/bitgo/defi/iDefiVault.d.ts +101 -0
- package/dist/src/bitgo/defi/iDefiVault.d.ts.map +1 -0
- package/dist/src/bitgo/defi/iDefiVault.js +6 -0
- package/dist/src/bitgo/defi/index.d.ts +3 -0
- package/dist/src/bitgo/defi/index.d.ts.map +1 -0
- package/dist/src/bitgo/defi/index.js +22 -0
- package/dist/src/bitgo/ecdh.d.ts +0 -1
- package/dist/src/bitgo/ecdh.d.ts.map +1 -1
- package/dist/src/bitgo/ecdh.js +26 -13
- package/dist/src/bitgo/enterprise/enterprise.d.ts +9 -4
- package/dist/src/bitgo/enterprise/enterprise.d.ts.map +1 -1
- package/dist/src/bitgo/enterprise/enterprise.js +47 -21
- package/dist/src/bitgo/enterprise/enterprises.js +27 -13
- package/dist/src/bitgo/enterprise/iEnterprise.d.ts +5 -3
- package/dist/src/bitgo/enterprise/iEnterprise.d.ts.map +1 -1
- package/dist/src/bitgo/enterprise/iEnterprise.js +1 -1
- package/dist/src/bitgo/enterprise/index.js +6 -2
- package/dist/src/bitgo/environments.d.ts +73 -3
- package/dist/src/bitgo/environments.d.ts.map +1 -1
- package/dist/src/bitgo/environments.js +415 -34
- package/dist/src/bitgo/errors.d.ts +183 -1
- package/dist/src/bitgo/errors.d.ts.map +1 -1
- package/dist/src/bitgo/errors.js +178 -3
- package/dist/src/bitgo/evm/evmUtils.d.ts +26 -0
- package/dist/src/bitgo/evm/evmUtils.d.ts.map +1 -0
- package/dist/src/bitgo/evm/evmUtils.js +50 -0
- package/dist/src/bitgo/index.d.ts +6 -1
- package/dist/src/bitgo/index.d.ts.map +1 -1
- package/dist/src/bitgo/index.js +32 -11
- package/dist/src/bitgo/inscriptionBuilder/iInscriptionBuilder.d.ts +3 -3
- package/dist/src/bitgo/inscriptionBuilder/iInscriptionBuilder.d.ts.map +1 -1
- package/dist/src/bitgo/inscriptionBuilder/iInscriptionBuilder.js +1 -1
- package/dist/src/bitgo/inscriptionBuilder/index.js +6 -2
- package/dist/src/bitgo/internal/index.js +6 -2
- package/dist/src/bitgo/internal/internal.js +5 -6
- package/dist/src/bitgo/internal/keycard.d.ts +13 -8
- package/dist/src/bitgo/internal/keycard.d.ts.map +1 -1
- package/dist/src/bitgo/internal/keycard.js +63 -48
- package/dist/src/bitgo/keychain/decryptKeychain.d.ts +14 -0
- package/dist/src/bitgo/keychain/decryptKeychain.d.ts.map +1 -0
- package/dist/src/bitgo/keychain/decryptKeychain.js +36 -0
- package/dist/src/bitgo/keychain/iKeychains.d.ts +160 -11
- package/dist/src/bitgo/keychain/iKeychains.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/iKeychains.js +2 -2
- package/dist/src/bitgo/keychain/index.d.ts +1 -0
- package/dist/src/bitgo/keychain/index.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/index.js +7 -2
- package/dist/src/bitgo/keychain/keychains.d.ts +106 -13
- package/dist/src/bitgo/keychain/keychains.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/keychains.js +393 -72
- package/dist/src/bitgo/keychain/ovcJsonCodec.d.ts +3 -3
- package/dist/src/bitgo/keychain/ovcJsonCodec.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/ovcJsonCodec.js +23 -9
- package/dist/src/bitgo/legacyBitcoin.d.ts +0 -1
- package/dist/src/bitgo/legacyBitcoin.d.ts.map +1 -1
- package/dist/src/bitgo/legacyBitcoin.js +27 -13
- package/dist/src/bitgo/lightning/lightningWalletUtil.d.ts +7 -0
- package/dist/src/bitgo/lightning/lightningWalletUtil.d.ts.map +1 -0
- package/dist/src/bitgo/lightning/lightningWalletUtil.js +25 -0
- package/dist/src/bitgo/market/iMarkets.d.ts +2 -2
- package/dist/src/bitgo/market/iMarkets.d.ts.map +1 -1
- package/dist/src/bitgo/market/index.js +6 -2
- package/dist/src/bitgo/market/markets.js +23 -9
- package/dist/src/bitgo/pendingApproval/iPendingApproval.d.ts +5 -1
- package/dist/src/bitgo/pendingApproval/iPendingApproval.d.ts.map +1 -1
- package/dist/src/bitgo/pendingApproval/iPendingApproval.js +4 -4
- package/dist/src/bitgo/pendingApproval/index.js +6 -2
- package/dist/src/bitgo/pendingApproval/pendingApproval.d.ts +20 -8
- package/dist/src/bitgo/pendingApproval/pendingApproval.d.ts.map +1 -1
- package/dist/src/bitgo/pendingApproval/pendingApproval.js +246 -111
- package/dist/src/bitgo/pendingApproval/pendingApprovals.js +23 -9
- package/dist/src/bitgo/proofs/WalletProofs.d.ts +19 -0
- package/dist/src/bitgo/proofs/WalletProofs.d.ts.map +1 -0
- package/dist/src/bitgo/proofs/WalletProofs.js +37 -0
- package/dist/src/bitgo/proofs/index.d.ts +2 -0
- package/dist/src/bitgo/proofs/index.d.ts.map +1 -0
- package/dist/src/bitgo/proofs/index.js +6 -0
- package/dist/src/bitgo/proofs/types.d.ts +80 -0
- package/dist/src/bitgo/proofs/types.d.ts.map +1 -0
- package/dist/src/bitgo/proofs/types.js +80 -0
- package/dist/src/bitgo/recovery/index.js +6 -2
- package/dist/src/bitgo/recovery/initiate.d.ts +13 -3
- package/dist/src/bitgo/recovery/initiate.d.ts.map +1 -1
- package/dist/src/bitgo/recovery/initiate.js +49 -41
- package/dist/src/bitgo/safe/derivableEd25519Pub.d.ts +13 -0
- package/dist/src/bitgo/safe/derivableEd25519Pub.d.ts.map +1 -0
- package/dist/src/bitgo/safe/derivableEd25519Pub.js +35 -0
- package/dist/src/bitgo/safe/iSafe.d.ts +124 -0
- package/dist/src/bitgo/safe/iSafe.d.ts.map +1 -0
- package/dist/src/bitgo/safe/iSafe.js +3 -0
- package/dist/src/bitgo/safe/iSafes.d.ts +94 -0
- package/dist/src/bitgo/safe/iSafes.d.ts.map +1 -0
- package/dist/src/bitgo/safe/iSafes.js +3 -0
- package/dist/src/bitgo/safe/index.d.ts +8 -0
- package/dist/src/bitgo/safe/index.d.ts.map +1 -0
- package/dist/src/bitgo/safe/index.js +24 -0
- package/dist/src/bitgo/safe/recovery.d.ts +82 -0
- package/dist/src/bitgo/safe/recovery.d.ts.map +1 -0
- package/dist/src/bitgo/safe/recovery.js +133 -0
- package/dist/src/bitgo/safe/rootCoin.d.ts +15 -0
- package/dist/src/bitgo/safe/rootCoin.d.ts.map +1 -0
- package/dist/src/bitgo/safe/rootCoin.js +47 -0
- package/dist/src/bitgo/safe/safe.d.ts +88 -0
- package/dist/src/bitgo/safe/safe.d.ts.map +1 -0
- package/dist/src/bitgo/safe/safe.js +409 -0
- package/dist/src/bitgo/safe/safes.d.ts +102 -0
- package/dist/src/bitgo/safe/safes.d.ts.map +1 -0
- package/dist/src/bitgo/safe/safes.js +281 -0
- package/dist/src/bitgo/staking/goStakingInterfaces.d.ts +136 -0
- package/dist/src/bitgo/staking/goStakingInterfaces.d.ts.map +1 -0
- package/dist/src/bitgo/staking/goStakingInterfaces.js +3 -0
- package/dist/src/bitgo/staking/goStakingWallet.d.ts +62 -0
- package/dist/src/bitgo/staking/goStakingWallet.d.ts.map +1 -0
- package/dist/src/bitgo/staking/goStakingWallet.js +141 -0
- package/dist/src/bitgo/staking/iGoStakingWallet.d.ts +17 -0
- package/dist/src/bitgo/staking/iGoStakingWallet.d.ts.map +1 -0
- package/dist/src/bitgo/staking/iGoStakingWallet.js +3 -0
- package/dist/src/bitgo/staking/iStakingWallet.d.ts +165 -8
- package/dist/src/bitgo/staking/iStakingWallet.d.ts.map +1 -1
- package/dist/src/bitgo/staking/iStakingWallet.js +2 -2
- package/dist/src/bitgo/staking/index.d.ts +3 -0
- package/dist/src/bitgo/staking/index.d.ts.map +1 -1
- package/dist/src/bitgo/staking/index.js +9 -2
- package/dist/src/bitgo/staking/stakingWallet.d.ts +21 -8
- package/dist/src/bitgo/staking/stakingWallet.d.ts.map +1 -1
- package/dist/src/bitgo/staking/stakingWallet.js +153 -7
- 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/index.d.ts +1 -0
- package/dist/src/bitgo/trading/index.d.ts.map +1 -1
- package/dist/src/bitgo/trading/index.js +7 -2
- package/dist/src/bitgo/trading/network/decrypt-aes-gcm.d.ts +8 -0
- package/dist/src/bitgo/trading/network/decrypt-aes-gcm.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/decrypt-aes-gcm.js +31 -0
- package/dist/src/bitgo/trading/network/decrypt-rsa.d.ts +8 -0
- package/dist/src/bitgo/trading/network/decrypt-rsa.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/decrypt-rsa.js +23 -0
- package/dist/src/bitgo/trading/network/decrypt.d.ts +14 -0
- package/dist/src/bitgo/trading/network/decrypt.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/decrypt.js +23 -0
- package/dist/src/bitgo/trading/network/encrypt-aes-gcm.d.ts +8 -0
- package/dist/src/bitgo/trading/network/encrypt-aes-gcm.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/encrypt-aes-gcm.js +25 -0
- package/dist/src/bitgo/trading/network/encrypt-rsa-browser.d.ts +8 -0
- package/dist/src/bitgo/trading/network/encrypt-rsa-browser.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/encrypt-rsa-browser.js +65 -0
- package/dist/src/bitgo/trading/network/encrypt-rsa.d.ts +8 -0
- package/dist/src/bitgo/trading/network/encrypt-rsa.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/encrypt-rsa.js +23 -0
- package/dist/src/bitgo/trading/network/encrypt.d.ts +37 -0
- package/dist/src/bitgo/trading/network/encrypt.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/encrypt.js +58 -0
- package/dist/src/bitgo/trading/network/index.d.ts +2 -0
- package/dist/src/bitgo/trading/network/index.d.ts.map +1 -1
- package/dist/src/bitgo/trading/network/index.js +8 -2
- package/dist/src/bitgo/trading/network/network.d.ts +4 -3
- package/dist/src/bitgo/trading/network/network.d.ts.map +1 -1
- package/dist/src/bitgo/trading/network/network.js +24 -27
- package/dist/src/bitgo/trading/network/types.d.ts +79 -46
- 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/network/utils.d.ts +20 -0
- package/dist/src/bitgo/trading/network/utils.d.ts.map +1 -0
- package/dist/src/bitgo/trading/network/utils.js +54 -0
- 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/bitgoPubKeys.d.ts +49 -0
- package/dist/src/bitgo/tss/bitgoPubKeys.d.ts.map +1 -0
- package/dist/src/bitgo/tss/bitgoPubKeys.js +92 -0
- package/dist/src/bitgo/tss/common.d.ts +41 -6
- package/dist/src/bitgo/tss/common.d.ts.map +1 -1
- package/dist/src/bitgo/tss/common.js +127 -17
- package/dist/src/bitgo/tss/ecdsa/ecdsa.d.ts +6 -4
- package/dist/src/bitgo/tss/ecdsa/ecdsa.d.ts.map +1 -1
- package/dist/src/bitgo/tss/ecdsa/ecdsa.js +78 -66
- package/dist/src/bitgo/tss/ecdsa/ecdsaMPCv2.d.ts +15 -0
- package/dist/src/bitgo/tss/ecdsa/ecdsaMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/tss/ecdsa/ecdsaMPCv2.js +167 -0
- package/dist/src/bitgo/tss/ecdsa/index.d.ts +1 -0
- package/dist/src/bitgo/tss/ecdsa/index.d.ts.map +1 -1
- package/dist/src/bitgo/tss/ecdsa/index.js +25 -10
- package/dist/src/bitgo/tss/ecdsa/types.d.ts +27 -27
- package/dist/src/bitgo/tss/ecdsa/types.d.ts.map +1 -1
- package/dist/src/bitgo/tss/ecdsa/types.js +3 -3
- package/dist/src/bitgo/tss/eddsa/eddsa.d.ts +15 -6
- package/dist/src/bitgo/tss/eddsa/eddsa.d.ts.map +1 -1
- package/dist/src/bitgo/tss/eddsa/eddsa.js +47 -40
- package/dist/src/bitgo/tss/eddsa/eddsaMPCv2.d.ts +42 -0
- package/dist/src/bitgo/tss/eddsa/eddsaMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/tss/eddsa/eddsaMPCv2.js +104 -0
- package/dist/src/bitgo/tss/eddsa/index.js +23 -9
- package/dist/src/bitgo/tss/eddsa/types.d.ts +4 -4
- package/dist/src/bitgo/tss/eddsa/types.d.ts.map +1 -1
- package/dist/src/bitgo/tss/index.d.ts +3 -2
- package/dist/src/bitgo/tss/index.d.ts.map +1 -1
- package/dist/src/bitgo/tss/index.js +26 -10
- package/dist/src/bitgo/tss/redpallas/redpallasMPCv2.d.ts +79 -0
- package/dist/src/bitgo/tss/redpallas/redpallasMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/tss/redpallas/redpallasMPCv2.js +179 -0
- package/dist/src/bitgo/tss/types.d.ts +3 -3
- package/dist/src/bitgo/tss/types.d.ts.map +1 -1
- package/dist/src/bitgo/tss/types.js +2 -2
- package/dist/src/bitgo/types.d.ts +3 -3
- package/dist/src/bitgo/types.d.ts.map +1 -1
- package/dist/src/bitgo/utils/abstractUtxoCoinUtil.d.ts +10 -0
- package/dist/src/bitgo/utils/abstractUtxoCoinUtil.d.ts.map +1 -1
- package/dist/src/bitgo/utils/abstractUtxoCoinUtil.js +76 -14
- package/dist/src/bitgo/utils/codecProps.js +24 -11
- package/dist/src/bitgo/utils/codecs.d.ts +11 -0
- package/dist/src/bitgo/utils/codecs.d.ts.map +1 -0
- package/dist/src/bitgo/utils/codecs.js +59 -0
- package/dist/src/bitgo/utils/decode.d.ts.map +1 -1
- package/dist/src/bitgo/utils/decode.js +30 -16
- package/dist/src/bitgo/utils/index.d.ts +5 -2
- package/dist/src/bitgo/utils/index.d.ts.map +1 -1
- package/dist/src/bitgo/utils/index.js +28 -11
- package/dist/src/bitgo/utils/messageTypes.d.ts +46 -0
- package/dist/src/bitgo/utils/messageTypes.d.ts.map +1 -0
- package/dist/src/bitgo/utils/messageTypes.js +23 -0
- package/dist/src/bitgo/utils/mpcUtils.d.ts +4 -4
- package/dist/src/bitgo/utils/mpcUtils.d.ts.map +1 -1
- package/dist/src/bitgo/utils/mpcUtils.js +208 -14
- package/dist/src/bitgo/utils/notEmpty.d.ts +2 -0
- package/dist/src/bitgo/utils/notEmpty.d.ts.map +1 -0
- package/dist/src/bitgo/utils/notEmpty.js +7 -0
- package/dist/src/bitgo/utils/opengpgUtils.d.ts +11 -7
- package/dist/src/bitgo/utils/opengpgUtils.d.ts.map +1 -1
- package/dist/src/bitgo/utils/opengpgUtils.js +79 -62
- package/dist/src/bitgo/utils/postWithCodec.d.ts.map +1 -1
- package/dist/src/bitgo/utils/postWithCodec.js +4 -38
- package/dist/src/bitgo/utils/promise-utils.d.ts +1 -1
- package/dist/src/bitgo/utils/promise-utils.d.ts.map +1 -1
- package/dist/src/bitgo/utils/promise-utils.js +2 -3
- package/dist/src/bitgo/utils/siws.d.ts +17 -0
- package/dist/src/bitgo/utils/siws.d.ts.map +1 -0
- package/dist/src/bitgo/utils/siws.js +171 -0
- package/dist/src/bitgo/utils/transactionUtils.d.ts +9 -0
- package/dist/src/bitgo/utils/transactionUtils.d.ts.map +1 -0
- package/dist/src/bitgo/utils/transactionUtils.js +29 -0
- package/dist/src/bitgo/utils/triple.d.ts +1 -1
- package/dist/src/bitgo/utils/triple.d.ts.map +1 -1
- package/dist/src/bitgo/utils/triple.js +2 -3
- package/dist/src/bitgo/utils/tss/addressVerification.d.ts +62 -0
- package/dist/src/bitgo/utils/tss/addressVerification.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/addressVerification.js +93 -0
- package/dist/src/bitgo/utils/tss/baseTSSUtils.d.ts +99 -17
- package/dist/src/bitgo/utils/tss/baseTSSUtils.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/baseTSSUtils.js +321 -45
- package/dist/src/bitgo/utils/tss/baseTypes.d.ts +456 -55
- package/dist/src/bitgo/utils/tss/baseTypes.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/baseTypes.js +47 -22
- package/dist/src/bitgo/utils/tss/ecdsa/SMC/utils.d.ts +23 -0
- package/dist/src/bitgo/utils/tss/ecdsa/SMC/utils.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/ecdsa/SMC/utils.js +157 -0
- package/dist/src/bitgo/utils/tss/ecdsa/base.d.ts +28 -0
- package/dist/src/bitgo/utils/tss/ecdsa/base.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/ecdsa/base.js +53 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.d.ts +25 -51
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.js +173 -246
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts +240 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.js +1076 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2KeyGenSender.d.ts +16 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2KeyGenSender.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2KeyGenSender.js +37 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaVrfMPCv2.d.ts +69 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaVrfMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaVrfMPCv2.js +442 -0
- package/dist/src/bitgo/utils/tss/ecdsa/index.d.ts +5 -0
- package/dist/src/bitgo/utils/tss/ecdsa/index.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/index.js +11 -2
- package/dist/src/bitgo/utils/tss/ecdsa/types.d.ts +7 -10
- package/dist/src/bitgo/utils/tss/ecdsa/types.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/types.js +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/typesMPCv2.d.ts +125 -0
- package/dist/src/bitgo/utils/tss/ecdsa/typesMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/ecdsa/typesMPCv2.js +55 -0
- package/dist/src/bitgo/utils/tss/eddsa/SMC/utils.d.ts +21 -0
- package/dist/src/bitgo/utils/tss/eddsa/SMC/utils.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/eddsa/SMC/utils.js +119 -0
- package/dist/src/bitgo/utils/tss/eddsa/base.d.ts +18 -0
- package/dist/src/bitgo/utils/tss/eddsa/base.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/eddsa/base.js +64 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.d.ts +43 -11
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.js +261 -96
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts +233 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.js +905 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2KeyGenSender.d.ts +11 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2KeyGenSender.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2KeyGenSender.js +26 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaVrfMPCv2.d.ts +44 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaVrfMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/eddsa/eddsaVrfMPCv2.js +295 -0
- package/dist/src/bitgo/utils/tss/eddsa/index.d.ts +5 -0
- package/dist/src/bitgo/utils/tss/eddsa/index.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/index.js +30 -8
- package/dist/src/bitgo/utils/tss/eddsa/types.d.ts +15 -7
- package/dist/src/bitgo/utils/tss/eddsa/types.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/types.js +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/typesEddsaMPCv2.d.ts +56 -0
- package/dist/src/bitgo/utils/tss/eddsa/typesEddsaMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/eddsa/typesEddsaMPCv2.js +55 -0
- package/dist/src/bitgo/utils/tss/index.d.ts +7 -0
- package/dist/src/bitgo/utils/tss/index.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/index.js +31 -10
- package/dist/src/bitgo/utils/tss/keyShareEnvelope.d.ts +40 -0
- package/dist/src/bitgo/utils/tss/keyShareEnvelope.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/keyShareEnvelope.js +103 -0
- package/dist/src/bitgo/utils/tss/keyVerification.d.ts +45 -0
- package/dist/src/bitgo/utils/tss/keyVerification.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/keyVerification.js +192 -0
- package/dist/src/bitgo/utils/tss/preHashedSignable.d.ts +23 -0
- package/dist/src/bitgo/utils/tss/preHashedSignable.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/preHashedSignable.js +26 -0
- package/dist/src/bitgo/utils/tss/recipientUtils.d.ts +42 -0
- package/dist/src/bitgo/utils/tss/recipientUtils.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/recipientUtils.js +168 -0
- package/dist/src/bitgo/utils/tss/redpallas/SMC/utils.d.ts +29 -0
- package/dist/src/bitgo/utils/tss/redpallas/SMC/utils.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/redpallas/SMC/utils.js +126 -0
- package/dist/src/bitgo/utils/tss/redpallas/index.d.ts +4 -0
- package/dist/src/bitgo/utils/tss/redpallas/index.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/redpallas/index.js +20 -0
- package/dist/src/bitgo/utils/tss/redpallas/redpallasMPCv2.d.ts +27 -0
- package/dist/src/bitgo/utils/tss/redpallas/redpallasMPCv2.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/redpallas/redpallasMPCv2.js +43 -0
- package/dist/src/bitgo/utils/tss/redpallas/redpallasMPCv2KeyGenSender.d.ts +45 -0
- package/dist/src/bitgo/utils/tss/redpallas/redpallasMPCv2KeyGenSender.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/redpallas/redpallasMPCv2KeyGenSender.js +55 -0
- package/dist/src/bitgo/utils/tss/serializedTxHexVerify.d.ts +8 -0
- package/dist/src/bitgo/utils/tss/serializedTxHexVerify.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/serializedTxHexVerify.js +13 -0
- package/dist/src/bitgo/utils/tss/signableConsistency.d.ts +12 -0
- package/dist/src/bitgo/utils/tss/signableConsistency.d.ts.map +1 -0
- package/dist/src/bitgo/utils/tss/signableConsistency.js +9 -0
- package/dist/src/bitgo/utils/txRequest.d.ts +10 -0
- package/dist/src/bitgo/utils/txRequest.d.ts.map +1 -0
- package/dist/src/bitgo/utils/txRequest.js +49 -0
- package/dist/src/bitgo/utils/util.js +24 -10
- package/dist/src/bitgo/utils/wallet.d.ts +7 -0
- package/dist/src/bitgo/utils/wallet.d.ts.map +1 -0
- package/dist/src/bitgo/utils/wallet.js +48 -0
- package/dist/src/bitgo/v1Wallets.d.ts +170 -0
- package/dist/src/bitgo/v1Wallets.d.ts.map +1 -0
- package/dist/src/bitgo/v1Wallets.js +3 -0
- package/dist/src/bitgo/wallet/BuildParams.d.ts +90 -1
- package/dist/src/bitgo/wallet/BuildParams.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/BuildParams.js +92 -11
- package/dist/src/bitgo/wallet/iWallet.d.ts +623 -33
- 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 +310 -16
- package/dist/src/bitgo/wallet/iWallets.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/iWallets.js +84 -3
- package/dist/src/bitgo/wallet/index.d.ts +1 -0
- package/dist/src/bitgo/wallet/index.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/index.js +7 -2
- package/dist/src/bitgo/wallet/safeKeychain.d.ts +75 -0
- package/dist/src/bitgo/wallet/safeKeychain.d.ts.map +1 -0
- package/dist/src/bitgo/wallet/safeKeychain.js +151 -0
- package/dist/src/bitgo/wallet/wallet.d.ts +379 -27
- package/dist/src/bitgo/wallet/wallet.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/wallet.js +2323 -442
- package/dist/src/bitgo/wallet/wallets.d.ts +99 -4
- package/dist/src/bitgo/wallet/wallets.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/wallets.js +1242 -156
- package/dist/src/bitgo/walletUtil/iMessageProvider.d.ts +12 -0
- package/dist/src/bitgo/walletUtil/iMessageProvider.d.ts.map +1 -0
- package/dist/src/bitgo/walletUtil/iMessageProvider.js +3 -0
- package/dist/src/bitgo/walletUtil/index.d.ts +3 -0
- package/dist/src/bitgo/walletUtil/index.d.ts.map +1 -0
- package/dist/src/bitgo/walletUtil/index.js +19 -0
- package/dist/src/bitgo/walletUtil/midnightMessageProvider.d.ts +22 -0
- package/dist/src/bitgo/walletUtil/midnightMessageProvider.d.ts.map +1 -0
- package/dist/src/bitgo/walletUtil/midnightMessageProvider.js +95 -0
- package/dist/src/bitgo/walletUtil/signAccountBasedMidnightClaimMessages.d.ts +9 -0
- package/dist/src/bitgo/walletUtil/signAccountBasedMidnightClaimMessages.d.ts.map +1 -0
- package/dist/src/bitgo/walletUtil/signAccountBasedMidnightClaimMessages.js +72 -0
- package/dist/src/bitgo/walletUtil/utxoMessageProof.d.ts +15 -0
- package/dist/src/bitgo/walletUtil/utxoMessageProof.d.ts.map +1 -0
- package/dist/src/bitgo/walletUtil/utxoMessageProof.js +40 -0
- package/dist/src/bitgo/webauthn/base64url.d.ts +16 -0
- package/dist/src/bitgo/webauthn/base64url.d.ts.map +1 -0
- package/dist/src/bitgo/webauthn/base64url.js +27 -0
- package/dist/src/bitgo/webauthn/deriveEnterpriseSalt.d.ts +18 -0
- package/dist/src/bitgo/webauthn/deriveEnterpriseSalt.d.ts.map +1 -0
- package/dist/src/bitgo/webauthn/deriveEnterpriseSalt.js +26 -0
- package/dist/src/bitgo/webauthn/derivePassword.d.ts +11 -0
- package/dist/src/bitgo/webauthn/derivePassword.d.ts.map +1 -0
- package/dist/src/bitgo/webauthn/derivePassword.js +16 -0
- package/dist/src/bitgo/webauthn/index.d.ts +5 -0
- package/dist/src/bitgo/webauthn/index.d.ts.map +1 -0
- package/dist/src/bitgo/webauthn/index.js +21 -0
- package/dist/src/bitgo/webauthn/types.d.ts +18 -0
- package/dist/src/bitgo/webauthn/types.d.ts.map +1 -0
- package/dist/src/bitgo/webauthn/types.js +3 -0
- package/dist/src/bitgo/webhook/index.js +6 -2
- package/dist/src/bitgo/webhook/webhooks.js +23 -9
- package/dist/src/coins/fiat.d.ts +45 -0
- package/dist/src/coins/fiat.d.ts.map +1 -0
- package/dist/src/coins/fiat.js +94 -0
- package/dist/src/coins/index.d.ts +1 -6
- package/dist/src/coins/index.d.ts.map +1 -1
- package/dist/src/coins/index.js +7 -8
- package/dist/src/coins/ofc.d.ts +21 -2
- package/dist/src/coins/ofc.d.ts.map +1 -1
- package/dist/src/coins/ofc.js +29 -3
- package/dist/src/coins/ofcToken.d.ts +15 -4
- package/dist/src/coins/ofcToken.d.ts.map +1 -1
- package/dist/src/coins/ofcToken.js +43 -5
- package/dist/src/coins/susd.d.ts +3 -2
- package/dist/src/coins/susd.d.ts.map +1 -1
- package/dist/src/coins/susd.js +5 -1
- package/dist/src/common.js +27 -13
- package/dist/src/index.d.ts +9 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +40 -11
- package/dist/src/lightning.d.ts +20 -0
- package/dist/src/lightning.d.ts.map +1 -0
- package/dist/src/lightning.js +13 -0
- package/dist/src/units.js +5 -6
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessage.d.ts +2 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessage.d.ts.map +1 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessage.js +207 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessageBuilder.d.ts +2 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessageBuilder.d.ts.map +1 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessageBuilder.js +174 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessageBuilderFactory.d.ts +2 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessageBuilderFactory.d.ts.map +1 -0
- package/dist/test/unit/account-lib/baseCoin/messages/baseMessageBuilderFactory.js +108 -0
- package/dist/test/unit/account-lib/baseCoin/messages/fixtures.d.ts +46 -0
- package/dist/test/unit/account-lib/baseCoin/messages/fixtures.d.ts.map +1 -0
- package/dist/test/unit/account-lib/baseCoin/messages/fixtures.js +69 -0
- package/dist/test/unit/account-lib/mpc/tss/ecdsa/ecdsa.js +91 -29
- package/dist/test/unit/account-lib/mpc/util.d.ts +2 -0
- package/dist/test/unit/account-lib/mpc/util.d.ts.map +1 -0
- package/dist/test/unit/account-lib/mpc/util.js +53 -0
- package/dist/test/unit/bitgo/address-book/address-book.d.ts +2 -0
- package/dist/test/unit/bitgo/address-book/address-book.d.ts.map +1 -0
- package/dist/test/unit/bitgo/address-book/address-book.js +159 -0
- package/dist/test/unit/bitgo/defi/defiVault.d.ts +2 -0
- package/dist/test/unit/bitgo/defi/defiVault.d.ts.map +1 -0
- package/dist/test/unit/bitgo/defi/defiVault.js +863 -0
- package/dist/test/unit/bitgo/environment.d.ts +2 -0
- package/dist/test/unit/bitgo/environment.d.ts.map +1 -0
- package/dist/test/unit/bitgo/environment.js +38 -0
- package/dist/test/unit/bitgo/errors.d.ts +2 -0
- package/dist/test/unit/bitgo/errors.d.ts.map +1 -0
- package/dist/test/unit/bitgo/errors.js +262 -0
- package/dist/test/unit/bitgo/keychain/keychains.d.ts +2 -0
- package/dist/test/unit/bitgo/keychain/keychains.d.ts.map +1 -0
- package/dist/test/unit/bitgo/keychain/keychains.js +426 -0
- package/dist/test/unit/bitgo/recovery/initiate.d.ts +2 -0
- package/dist/test/unit/bitgo/recovery/initiate.d.ts.map +1 -0
- package/dist/test/unit/bitgo/recovery/initiate.js +159 -0
- package/dist/test/unit/bitgo/safe/derivableEd25519Pub.d.ts +2 -0
- package/dist/test/unit/bitgo/safe/derivableEd25519Pub.d.ts.map +1 -0
- package/dist/test/unit/bitgo/safe/derivableEd25519Pub.js +133 -0
- package/dist/test/unit/bitgo/safe/fixtures/derivableEd25519Pub.json +72 -0
- package/dist/test/unit/bitgo/safe/recovery.d.ts +2 -0
- package/dist/test/unit/bitgo/safe/recovery.d.ts.map +1 -0
- package/dist/test/unit/bitgo/safe/recovery.js +253 -0
- package/dist/test/unit/bitgo/safe/rootCoin.d.ts +2 -0
- package/dist/test/unit/bitgo/safe/rootCoin.d.ts.map +1 -0
- package/dist/test/unit/bitgo/safe/rootCoin.js +13 -0
- package/dist/test/unit/bitgo/safe/safe.d.ts +2 -0
- package/dist/test/unit/bitgo/safe/safe.d.ts.map +1 -0
- package/dist/test/unit/bitgo/safe/safe.js +585 -0
- package/dist/test/unit/bitgo/safe/safeDerivation.d.ts +2 -0
- package/dist/test/unit/bitgo/safe/safeDerivation.d.ts.map +1 -0
- package/dist/test/unit/bitgo/safe/safeDerivation.js +75 -0
- package/dist/test/unit/bitgo/safe/safes.d.ts +2 -0
- package/dist/test/unit/bitgo/safe/safes.d.ts.map +1 -0
- package/dist/test/unit/bitgo/safe/safes.js +376 -0
- package/dist/test/unit/bitgo/trading/network/encrypt.d.ts +2 -0
- package/dist/test/unit/bitgo/trading/network/encrypt.d.ts.map +1 -0
- package/dist/test/unit/bitgo/trading/network/encrypt.js +71 -0
- package/dist/test/unit/bitgo/trading/network/network.test.d.ts +2 -0
- package/dist/test/unit/bitgo/trading/network/network.test.d.ts.map +1 -0
- package/dist/test/unit/bitgo/trading/network/network.test.js +136 -0
- 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/tss/bitgoPubKeys.d.ts +2 -0
- package/dist/test/unit/bitgo/tss/bitgoPubKeys.d.ts.map +1 -0
- package/dist/test/unit/bitgo/tss/bitgoPubKeys.js +66 -0
- package/dist/test/unit/bitgo/tss/common.d.ts +2 -0
- package/dist/test/unit/bitgo/tss/common.d.ts.map +1 -0
- package/dist/test/unit/bitgo/tss/common.js +77 -0
- package/dist/test/unit/bitgo/tss/redpallas/redpallasMPCv2.d.ts +2 -0
- package/dist/test/unit/bitgo/tss/redpallas/redpallasMPCv2.d.ts.map +1 -0
- package/dist/test/unit/bitgo/tss/redpallas/redpallasMPCv2.js +249 -0
- package/dist/test/unit/bitgo/utils/abstractUtxoCoinUtil.js +45 -4
- package/dist/test/unit/bitgo/utils/messageTypes.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/messageTypes.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/messageTypes.js +64 -0
- package/dist/test/unit/bitgo/utils/mpcUtils.unwrap.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/mpcUtils.unwrap.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/mpcUtils.unwrap.js +109 -0
- package/dist/test/unit/bitgo/utils/mpcUtils.wrapApprove.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/mpcUtils.wrapApprove.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/mpcUtils.wrapApprove.js +106 -0
- package/dist/test/unit/bitgo/utils/notEmpty.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/notEmpty.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/notEmpty.js +15 -0
- package/dist/test/unit/bitgo/utils/postWithCodec.js +32 -38
- package/dist/test/unit/bitgo/utils/siws.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/siws.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/siws.js +206 -0
- package/dist/test/unit/bitgo/utils/tss/addressVerification.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/addressVerification.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/addressVerification.js +251 -0
- 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 +348 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/ecdsaEncryptionVersion.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/ecdsaEncryptionVersion.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/ecdsaEncryptionVersion.js +94 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/ecdsaMPCv2.js +1068 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/gpgKeys.d.ts +5 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/gpgKeys.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/ecdsa/gpgKeys.js +36 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaExternalSigner.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaExternalSigner.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaExternalSigner.js +158 -0
- 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 +1993 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaVrfMPCv2.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaVrfMPCv2.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/eddsaVrfMPCv2.js +380 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/smcUtil.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/smcUtil.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/eddsa/smcUtil.js +376 -0
- package/dist/test/unit/bitgo/utils/tss/keyShareEnvelope.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/keyShareEnvelope.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/keyShareEnvelope.js +83 -0
- package/dist/test/unit/bitgo/utils/tss/keyVerification.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/keyVerification.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/keyVerification.js +229 -0
- package/dist/test/unit/bitgo/utils/tss/preHashedSignable.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/preHashedSignable.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/preHashedSignable.js +55 -0
- package/dist/test/unit/bitgo/utils/tss/recipientUtils.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/recipientUtils.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/recipientUtils.js +462 -0
- package/dist/test/unit/bitgo/utils/tss/redpallas/redpallasMPCv2.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/redpallas/redpallasMPCv2.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/redpallas/redpallasMPCv2.js +80 -0
- package/dist/test/unit/bitgo/utils/tss/redpallas/smcUtil.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/redpallas/smcUtil.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/redpallas/smcUtil.js +279 -0
- package/dist/test/unit/bitgo/utils/tss/redpallasBitgoGpgKey.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/tss/redpallasBitgoGpgKey.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/tss/redpallasBitgoGpgKey.js +111 -0
- package/dist/test/unit/bitgo/utils/txRequest.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/txRequest.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/txRequest.js +179 -0
- package/dist/test/unit/bitgo/utils/wallet.d.ts +2 -0
- package/dist/test/unit/bitgo/utils/wallet.d.ts.map +1 -0
- package/dist/test/unit/bitgo/utils/wallet.js +55 -0
- package/dist/test/unit/bitgo/wallet/BuildParams.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/BuildParams.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/BuildParams.js +154 -0
- package/dist/test/unit/bitgo/wallet/SendTransactionRequest.js +79 -9
- package/dist/test/unit/bitgo/wallet/getAccountResources.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/getAccountResources.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/getAccountResources.js +133 -0
- package/dist/test/unit/bitgo/wallet/getPotentialStuckTxs.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/getPotentialStuckTxs.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/getPotentialStuckTxs.js +88 -0
- package/dist/test/unit/bitgo/wallet/getResourceDelegations.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/getResourceDelegations.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/getResourceDelegations.js +118 -0
- package/dist/test/unit/bitgo/wallet/ofcWalletAddressCreation.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/ofcWalletAddressCreation.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/ofcWalletAddressCreation.js +141 -0
- 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/prebuildTransactionTypes.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/prebuildTransactionTypes.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/prebuildTransactionTypes.js +20 -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/safeGetUserPrv.d.ts +5 -0
- package/dist/test/unit/bitgo/wallet/safeGetUserPrv.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/safeGetUserPrv.js +671 -0
- package/dist/test/unit/bitgo/wallet/safeShareWallet.d.ts +9 -0
- package/dist/test/unit/bitgo/wallet/safeShareWallet.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/safeShareWallet.js +303 -0
- package/dist/test/unit/bitgo/wallet/tokenApproval.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/tokenApproval.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/tokenApproval.js +210 -0
- package/dist/test/unit/bitgo/wallet/walletEvmAddressCreation.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletEvmAddressCreation.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletEvmAddressCreation.js +181 -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 +69 -0
- package/dist/test/unit/bitgo/wallet/walletTssAddressVerification.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletTssAddressVerification.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletTssAddressVerification.js +320 -0
- package/dist/test/unit/bitgo/wallet/walletVerifyKey.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletVerifyKey.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletVerifyKey.js +160 -0
- package/dist/test/unit/bitgo/wallet/walletsEncryptionVersion.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletsEncryptionVersion.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletsEncryptionVersion.js +304 -0
- package/dist/test/unit/bitgo/wallet/walletsEvmKeyring.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletsEvmKeyring.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletsEvmKeyring.js +216 -0
- package/dist/test/unit/bitgo/wallet/walletsExternalSigner.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletsExternalSigner.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletsExternalSigner.js +675 -0
- package/dist/test/unit/bitgo/wallet/walletsGoAccount.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletsGoAccount.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletsGoAccount.js +150 -0
- package/dist/test/unit/bitgo/wallet/walletsWebauthn.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletsWebauthn.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletsWebauthn.js +201 -0
- 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/test/unit/lightning.d.ts +2 -0
- package/dist/test/unit/lightning.d.ts.map +1 -0
- package/dist/test/unit/lightning.js +23 -0
- package/dist/test/unit/units.d.ts.map +1 -1
- package/dist/test/unit/units.js +64 -64
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +25 -22
- package/.eslintignore +0 -5
- package/CHANGELOG.md +0 -1866
- package/dist/src/account-lib/baseCoin/blsKeyPair.d.ts +0 -77
- package/dist/src/account-lib/baseCoin/blsKeyPair.d.ts.map +0 -1
- package/dist/src/account-lib/baseCoin/blsKeyPair.js +0 -209
- package/dist/src/account-lib/util/ed25519KeyDeriver.d.ts +0 -49
- package/dist/src/account-lib/util/ed25519KeyDeriver.d.ts.map +0 -1
- package/dist/src/account-lib/util/ed25519KeyDeriver.js +0 -87
- package/dist/src/bitgo/lightning/iLightning.d.ts +0 -186
- package/dist/src/bitgo/lightning/iLightning.d.ts.map +0 -1
- package/dist/src/bitgo/lightning/iLightning.js +0 -106
- package/dist/src/bitgo/lightning/index.d.ts +0 -5
- package/dist/src/bitgo/lightning/index.d.ts.map +0 -1
- package/dist/src/bitgo/lightning/index.js +0 -17
- package/dist/src/bitgo/lightning/lightning.d.ts +0 -25
- package/dist/src/bitgo/lightning/lightning.d.ts.map +0 -1
- package/dist/src/bitgo/lightning/lightning.js +0 -111
- package/dist/src/bitgo/lightning/lightningUtils.d.ts +0 -46
- package/dist/src/bitgo/lightning/lightningUtils.d.ts.map +0 -1
- package/dist/src/bitgo/lightning/lightningUtils.js +0 -133
- package/dist/src/bitgo/lightning/lnurlCodec.d.ts +0 -3
- package/dist/src/bitgo/lightning/lnurlCodec.d.ts.map +0 -1
- package/dist/src/bitgo/lightning/lnurlCodec.js +0 -28
- package/dist/src/bitgo/utils/blsUtils.d.ts +0 -52
- package/dist/src/bitgo/utils/blsUtils.d.ts.map +0 -1
- package/dist/src/bitgo/utils/blsUtils.js +0 -237
- package/dist/src/bitgo/utils/iBlsUtils.d.ts +0 -14
- package/dist/src/bitgo/utils/iBlsUtils.d.ts.map +0 -1
- package/dist/src/bitgo/utils/iBlsUtils.js +0 -3
- package/dist/src/coins/fiateur.d.ts +0 -31
- package/dist/src/coins/fiateur.d.ts.map +0 -1
- package/dist/src/coins/fiateur.js +0 -57
- package/dist/src/coins/fiatgbp.d.ts +0 -31
- package/dist/src/coins/fiatgbp.d.ts.map +0 -1
- package/dist/src/coins/fiatgbp.js +0 -57
- package/dist/src/coins/fiatusd.d.ts +0 -31
- package/dist/src/coins/fiatusd.d.ts.map +0 -1
- package/dist/src/coins/fiatusd.js +0 -57
- package/dist/src/coins/tfiateur.d.ts +0 -11
- package/dist/src/coins/tfiateur.d.ts.map +0 -1
- package/dist/src/coins/tfiateur.js +0 -17
- package/dist/src/coins/tfiatgbp.d.ts +0 -11
- package/dist/src/coins/tfiatgbp.d.ts.map +0 -1
- package/dist/src/coins/tfiatgbp.js +0 -17
- package/dist/src/coins/tfiatusd.d.ts +0 -11
- package/dist/src/coins/tfiatusd.d.ts.map +0 -1
- package/dist/src/coins/tfiatusd.js +0 -17
- package/dist/src/openssl/index.d.ts +0 -5
- package/dist/src/openssl/index.d.ts.map +0 -1
- package/dist/src/openssl/index.js +0 -9
- package/dist/test/unit/openssl.d.ts +0 -2
- package/dist/test/unit/openssl.d.ts.map +0 -1
- package/dist/test/unit/openssl.js +0 -39
|
@@ -0,0 +1,1993 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const cbor_x_1 = require("cbor-x");
|
|
37
|
+
const assert = __importStar(require("assert"));
|
|
38
|
+
const sinon = __importStar(require("sinon"));
|
|
39
|
+
const pgp = __importStar(require("openpgp"));
|
|
40
|
+
const crypto_1 = require("crypto");
|
|
41
|
+
const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
|
|
42
|
+
const ed25519_1 = require("@noble/curves/ed25519");
|
|
43
|
+
const sjcl = __importStar(require("@bitgo-beta/sjcl"));
|
|
44
|
+
const public_types_1 = require("@bitgo/public-types");
|
|
45
|
+
const src_1 = require("../../../../../../src");
|
|
46
|
+
const eddsaMPCv2_1 = require("../../../../../../src/bitgo/tss/eddsa/eddsaMPCv2");
|
|
47
|
+
const eddsa_1 = require("../../../../../../src/bitgo/tss/eddsa/eddsa");
|
|
48
|
+
const common_1 = require("../../../../../../src/bitgo/tss/common");
|
|
49
|
+
const codecs_1 = require("../../../../../../src/bitgo/utils/codecs");
|
|
50
|
+
const opengpgUtils_1 = require("../../../../../../src/bitgo/utils/opengpgUtils");
|
|
51
|
+
const typesMPCv2_1 = require("../../../../../../src/bitgo/utils/tss/ecdsa/typesMPCv2");
|
|
52
|
+
const baseTypes_1 = require("../../../../../../src/bitgo/utils/tss/baseTypes");
|
|
53
|
+
describe('EdDSA MPS DSG helper functions', async () => {
|
|
54
|
+
let userKeyShare;
|
|
55
|
+
let backupKeyShare;
|
|
56
|
+
let bitgoKeyShare;
|
|
57
|
+
let userGpgPrivKey;
|
|
58
|
+
let backupGpgPrivKey;
|
|
59
|
+
let bitgoGpgPrivKey;
|
|
60
|
+
let bitgoGpgPubKey;
|
|
61
|
+
const signableHex = 'deadbeef';
|
|
62
|
+
const derivationPath = 'm/0';
|
|
63
|
+
before('generate EdDSA DKG key shares', async () => {
|
|
64
|
+
const userGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
65
|
+
const backupGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
66
|
+
const bitgoGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
67
|
+
userGpgPrivKey = await pgp.readPrivateKey({ armoredKey: userGpgKeyPair.privateKey });
|
|
68
|
+
backupGpgPrivKey = await pgp.readPrivateKey({ armoredKey: backupGpgKeyPair.privateKey });
|
|
69
|
+
bitgoGpgPrivKey = await pgp.readPrivateKey({ armoredKey: bitgoGpgKeyPair.privateKey });
|
|
70
|
+
bitgoGpgPubKey = await pgp.readKey({ armoredKey: bitgoGpgKeyPair.publicKey });
|
|
71
|
+
const [userDkg, backupDkg, bitgoDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
72
|
+
userKeyShare = userDkg.getKeyShare();
|
|
73
|
+
backupKeyShare = backupDkg.getKeyShare();
|
|
74
|
+
bitgoKeyShare = bitgoDkg.getKeyShare();
|
|
75
|
+
});
|
|
76
|
+
// ── Round 1 ─────────────────────────────────────────────────────────────────
|
|
77
|
+
it('getSignatureShareRoundOne should build a valid round-1 share', async () => {
|
|
78
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
79
|
+
const userDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
80
|
+
await userDsg.initDsg(userKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
81
|
+
const userMsg1 = userDsg.getFirstMessage();
|
|
82
|
+
const share = await (0, eddsaMPCv2_1.getSignatureShareRoundOne)(userMsg1, userGpgPrivKey);
|
|
83
|
+
assert.strictEqual(share.from, src_1.SignatureShareType.USER);
|
|
84
|
+
assert.strictEqual(share.to, src_1.SignatureShareType.BITGO);
|
|
85
|
+
const parsed = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound1Input, JSON.parse(share.share), 'EddsaMPCv2SignatureShareRound1Input');
|
|
86
|
+
assert.strictEqual(parsed.type, 'round1Input');
|
|
87
|
+
assert.ok(parsed.data.msg1.message, 'msg1.message should be set');
|
|
88
|
+
assert.ok(parsed.data.msg1.signature, 'msg1.signature should be set');
|
|
89
|
+
});
|
|
90
|
+
it('getSignatureShareRoundOne should build a valid backup round-1 share', async () => {
|
|
91
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
92
|
+
const backupDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
93
|
+
await backupDsg.initDsg(backupKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
94
|
+
const backupMsg1 = backupDsg.getFirstMessage();
|
|
95
|
+
const share = await (0, eddsaMPCv2_1.getSignatureShareRoundOne)(backupMsg1, backupGpgPrivKey, typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
96
|
+
assert.strictEqual(share.from, src_1.SignatureShareType.BACKUP);
|
|
97
|
+
assert.strictEqual(share.to, src_1.SignatureShareType.BITGO);
|
|
98
|
+
const parsed = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound1Input, JSON.parse(share.share), 'EddsaMPCv2SignatureShareRound1Input');
|
|
99
|
+
assert.strictEqual(parsed.type, 'round1Input');
|
|
100
|
+
assert.ok(parsed.data.msg1.message, 'msg1.message should be set');
|
|
101
|
+
assert.ok(parsed.data.msg1.signature, 'msg1.signature should be set');
|
|
102
|
+
});
|
|
103
|
+
it('verifyPeerMessageRoundOne should verify a valid BitGo round-1 message', async () => {
|
|
104
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
105
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
106
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
107
|
+
const bitgoMsg1 = bitgoDsg.getFirstMessage();
|
|
108
|
+
const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoGpgPrivKey);
|
|
109
|
+
const round1Output = {
|
|
110
|
+
type: 'round1Output',
|
|
111
|
+
data: { msg1: bitgoSignedMsg1 },
|
|
112
|
+
};
|
|
113
|
+
const result = await (0, eddsaMPCv2_1.verifyPeerMessageRoundOne)(round1Output, bitgoGpgPubKey);
|
|
114
|
+
assert.strictEqual(result.from, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
115
|
+
assert.ok(result.payload.length > 0, 'payload should be non-empty');
|
|
116
|
+
});
|
|
117
|
+
it('verifyPeerMessageRoundOne should throw on a tampered message', async () => {
|
|
118
|
+
const round1Output = {
|
|
119
|
+
type: 'round1Output',
|
|
120
|
+
data: {
|
|
121
|
+
msg1: {
|
|
122
|
+
message: Buffer.from('tampered').toString('base64'),
|
|
123
|
+
signature: '-----BEGIN PGP SIGNATURE-----\n\nINVALID\n-----END PGP SIGNATURE-----\n',
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
await assert.rejects((0, eddsaMPCv2_1.verifyPeerMessageRoundOne)(round1Output, bitgoGpgPubKey), 'should throw on invalid signature');
|
|
128
|
+
});
|
|
129
|
+
// ── Round 2 ─────────────────────────────────────────────────────────────────
|
|
130
|
+
it('getSignatureShareRoundTwo should build a valid round-2 share', async () => {
|
|
131
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
132
|
+
const userDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
133
|
+
await userDsg.initDsg(userKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
134
|
+
const userMsg1 = userDsg.getFirstMessage();
|
|
135
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
136
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
137
|
+
const bitgoMsg1 = bitgoDsg.getFirstMessage();
|
|
138
|
+
const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoGpgPrivKey);
|
|
139
|
+
const bitgoDeserializedMsg1 = await (0, eddsaMPCv2_1.verifyPeerMessageRoundOne)({ type: 'round1Output', data: { msg1: bitgoSignedMsg1 } }, bitgoGpgPubKey);
|
|
140
|
+
const [userMsg2] = userDsg.handleIncomingMessages([userMsg1, bitgoDeserializedMsg1]);
|
|
141
|
+
const share = await (0, eddsaMPCv2_1.getSignatureShareRoundTwo)(userMsg2, userGpgPrivKey);
|
|
142
|
+
assert.strictEqual(share.from, src_1.SignatureShareType.USER);
|
|
143
|
+
assert.strictEqual(share.to, src_1.SignatureShareType.BITGO);
|
|
144
|
+
const parsed = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound2Input, JSON.parse(share.share), 'EddsaMPCv2SignatureShareRound2Input');
|
|
145
|
+
assert.strictEqual(parsed.type, 'round2Input');
|
|
146
|
+
assert.ok(parsed.data.msg2.message, 'msg2.message should be set');
|
|
147
|
+
assert.ok(parsed.data.msg2.signature, 'msg2.signature should be set');
|
|
148
|
+
});
|
|
149
|
+
it('getSignatureShareRoundTwo should build a valid backup round-2 share', async () => {
|
|
150
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
151
|
+
const backupDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
152
|
+
await backupDsg.initDsg(backupKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
153
|
+
const backupMsg1 = backupDsg.getFirstMessage();
|
|
154
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
155
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
156
|
+
const bitgoMsg1 = bitgoDsg.getFirstMessage();
|
|
157
|
+
const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoGpgPrivKey);
|
|
158
|
+
const bitgoDeserializedMsg1 = await (0, eddsaMPCv2_1.verifyPeerMessageRoundOne)({ type: 'round1Output', data: { msg1: bitgoSignedMsg1 } }, bitgoGpgPubKey);
|
|
159
|
+
const [backupMsg2] = backupDsg.handleIncomingMessages([backupMsg1, bitgoDeserializedMsg1]);
|
|
160
|
+
const share = await (0, eddsaMPCv2_1.getSignatureShareRoundTwo)(backupMsg2, backupGpgPrivKey, typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
161
|
+
assert.strictEqual(share.from, src_1.SignatureShareType.BACKUP);
|
|
162
|
+
assert.strictEqual(share.to, src_1.SignatureShareType.BITGO);
|
|
163
|
+
const parsed = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound2Input, JSON.parse(share.share), 'EddsaMPCv2SignatureShareRound2Input');
|
|
164
|
+
assert.strictEqual(parsed.type, 'round2Input');
|
|
165
|
+
assert.ok(parsed.data.msg2.message, 'msg2.message should be set');
|
|
166
|
+
assert.ok(parsed.data.msg2.signature, 'msg2.signature should be set');
|
|
167
|
+
});
|
|
168
|
+
it('verifyPeerMessageRoundTwo should verify a valid BitGo round-2 message', async () => {
|
|
169
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
170
|
+
const userDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
171
|
+
await userDsg.initDsg(userKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
172
|
+
const userMsg1 = userDsg.getFirstMessage();
|
|
173
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
174
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
175
|
+
const bitgoMsg1 = bitgoDsg.getFirstMessage();
|
|
176
|
+
const [bitgoMsg2] = bitgoDsg.handleIncomingMessages([bitgoMsg1, userMsg1]);
|
|
177
|
+
const bitgoSignedMsg2 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg2.payload), bitgoGpgPrivKey);
|
|
178
|
+
const round2Output = {
|
|
179
|
+
type: 'round2Output',
|
|
180
|
+
data: { msg2: bitgoSignedMsg2 },
|
|
181
|
+
};
|
|
182
|
+
const result = await (0, eddsaMPCv2_1.verifyPeerMessageRoundTwo)(round2Output, bitgoGpgPubKey);
|
|
183
|
+
assert.strictEqual(result.from, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
184
|
+
assert.ok(result.payload.length > 0, 'payload should be non-empty');
|
|
185
|
+
});
|
|
186
|
+
it('verifyPeerMessageRoundTwo should throw on a tampered message', async () => {
|
|
187
|
+
const round2Output = {
|
|
188
|
+
type: 'round2Output',
|
|
189
|
+
data: {
|
|
190
|
+
msg2: {
|
|
191
|
+
message: Buffer.from('tampered').toString('base64'),
|
|
192
|
+
signature: '-----BEGIN PGP SIGNATURE-----\n\nINVALID\n-----END PGP SIGNATURE-----\n',
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
await assert.rejects((0, eddsaMPCv2_1.verifyPeerMessageRoundTwo)(round2Output, bitgoGpgPubKey), 'should throw on invalid signature');
|
|
197
|
+
});
|
|
198
|
+
// ── Round 3 ─────────────────────────────────────────────────────────────────
|
|
199
|
+
it('getSignatureShareRoundThree should build a valid round-3 share', async () => {
|
|
200
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
201
|
+
const userDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
202
|
+
await userDsg.initDsg(userKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
203
|
+
const userMsg1 = userDsg.getFirstMessage();
|
|
204
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
205
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
206
|
+
const bitgoMsg1 = bitgoDsg.getFirstMessage();
|
|
207
|
+
// Advance to round 2
|
|
208
|
+
const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoGpgPrivKey);
|
|
209
|
+
const bitgoDeserializedMsg1 = await (0, eddsaMPCv2_1.verifyPeerMessageRoundOne)({ type: 'round1Output', data: { msg1: bitgoSignedMsg1 } }, bitgoGpgPubKey);
|
|
210
|
+
const [userMsg2] = userDsg.handleIncomingMessages([userMsg1, bitgoDeserializedMsg1]);
|
|
211
|
+
const [bitgoMsg2] = bitgoDsg.handleIncomingMessages([bitgoMsg1, userMsg1]);
|
|
212
|
+
const bitgoSignedMsg2 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg2.payload), bitgoGpgPrivKey);
|
|
213
|
+
const bitgoDeserializedMsg2 = await (0, eddsaMPCv2_1.verifyPeerMessageRoundTwo)({ type: 'round2Output', data: { msg2: bitgoSignedMsg2 } }, bitgoGpgPubKey);
|
|
214
|
+
const [userMsg3] = userDsg.handleIncomingMessages([userMsg2, bitgoDeserializedMsg2]);
|
|
215
|
+
const share = await (0, eddsaMPCv2_1.getSignatureShareRoundThree)(userMsg3, userGpgPrivKey);
|
|
216
|
+
assert.strictEqual(share.from, src_1.SignatureShareType.USER);
|
|
217
|
+
assert.strictEqual(share.to, src_1.SignatureShareType.BITGO);
|
|
218
|
+
const parsed = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound3Input, JSON.parse(share.share), 'EddsaMPCv2SignatureShareRound3Input');
|
|
219
|
+
assert.strictEqual(parsed.type, 'round3Input');
|
|
220
|
+
assert.ok(parsed.data.msg3.message, 'msg3.message should be set');
|
|
221
|
+
assert.ok(parsed.data.msg3.signature, 'msg3.signature should be set');
|
|
222
|
+
});
|
|
223
|
+
it('getSignatureShareRoundThree should build a valid backup round-3 share', async () => {
|
|
224
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
225
|
+
const backupDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
226
|
+
await backupDsg.initDsg(backupKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
227
|
+
const backupMsg1 = backupDsg.getFirstMessage();
|
|
228
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
229
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
230
|
+
const bitgoMsg1 = bitgoDsg.getFirstMessage();
|
|
231
|
+
const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoGpgPrivKey);
|
|
232
|
+
const bitgoDeserializedMsg1 = await (0, eddsaMPCv2_1.verifyPeerMessageRoundOne)({ type: 'round1Output', data: { msg1: bitgoSignedMsg1 } }, bitgoGpgPubKey);
|
|
233
|
+
const [backupMsg2] = backupDsg.handleIncomingMessages([backupMsg1, bitgoDeserializedMsg1]);
|
|
234
|
+
const [bitgoMsg2] = bitgoDsg.handleIncomingMessages([bitgoMsg1, backupMsg1]);
|
|
235
|
+
const bitgoSignedMsg2 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg2.payload), bitgoGpgPrivKey);
|
|
236
|
+
const bitgoDeserializedMsg2 = await (0, eddsaMPCv2_1.verifyPeerMessageRoundTwo)({ type: 'round2Output', data: { msg2: bitgoSignedMsg2 } }, bitgoGpgPubKey);
|
|
237
|
+
const [backupMsg3] = backupDsg.handleIncomingMessages([backupMsg2, bitgoDeserializedMsg2]);
|
|
238
|
+
const share = await (0, eddsaMPCv2_1.getSignatureShareRoundThree)(backupMsg3, backupGpgPrivKey, typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
239
|
+
assert.strictEqual(share.from, src_1.SignatureShareType.BACKUP);
|
|
240
|
+
assert.strictEqual(share.to, src_1.SignatureShareType.BITGO);
|
|
241
|
+
const parsed = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound3Input, JSON.parse(share.share), 'EddsaMPCv2SignatureShareRound3Input');
|
|
242
|
+
assert.strictEqual(parsed.type, 'round3Input');
|
|
243
|
+
assert.ok(parsed.data.msg3.message, 'msg3.message should be set');
|
|
244
|
+
assert.ok(parsed.data.msg3.signature, 'msg3.signature should be set');
|
|
245
|
+
});
|
|
246
|
+
it('verifyPeerMessageRoundThree should verify a valid BitGo round-3 message', async () => {
|
|
247
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
248
|
+
const [, [bitgoMsg3]] = (await sdk_lib_mpc_1.MPSUtil.executeTillRound(2, new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.USER), new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO), userKeyShare, bitgoKeyShare, messageBuffer, derivationPath));
|
|
249
|
+
const bitgoSignedMsg3 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg3.payload), bitgoGpgPrivKey);
|
|
250
|
+
const round3Output = {
|
|
251
|
+
type: 'round3Output',
|
|
252
|
+
data: { msg3: bitgoSignedMsg3 },
|
|
253
|
+
};
|
|
254
|
+
const result = await (0, eddsaMPCv2_1.verifyPeerMessageRoundThree)(round3Output, bitgoGpgPubKey);
|
|
255
|
+
assert.strictEqual(result.from, typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
256
|
+
assert.ok(result.payload.length > 0, 'payload should be non-empty');
|
|
257
|
+
});
|
|
258
|
+
it('verifyPeerMessageRoundThree should throw on a tampered message', async () => {
|
|
259
|
+
const round3Output = {
|
|
260
|
+
type: 'round3Output',
|
|
261
|
+
data: {
|
|
262
|
+
msg3: {
|
|
263
|
+
message: Buffer.from('tampered').toString('base64'),
|
|
264
|
+
signature: '-----BEGIN PGP SIGNATURE-----\n\nINVALID\n-----END PGP SIGNATURE-----\n',
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
await assert.rejects((0, eddsaMPCv2_1.verifyPeerMessageRoundThree)(round3Output, bitgoGpgPubKey), 'should throw on invalid signature');
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
describe('getEddsaMPCv2RecoveryKeyShares', () => {
|
|
272
|
+
const walletPassphrase = 'testPass';
|
|
273
|
+
const encryptKey = (keyShare) => sjcl.encrypt(walletPassphrase, keyShare.toString('base64'));
|
|
274
|
+
it('should return recovery key shares from v1-encrypted reduced keys (no bitgo instance)', async () => {
|
|
275
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
276
|
+
const result = await src_1.EDDSAUtils.getEddsaMpcV2RecoveryKeySharesFromReducedKey(encryptKey(userDkg.getReducedKeyShare()), encryptKey(backupDkg.getReducedKeyShare()), walletPassphrase);
|
|
277
|
+
assert.deepStrictEqual(result.userKeyShare, userDkg.getKeyShare());
|
|
278
|
+
assert.deepStrictEqual(result.backupKeyShare, backupDkg.getKeyShare());
|
|
279
|
+
assert.strictEqual(result.commonKeyChain, userDkg.getCommonKeychain());
|
|
280
|
+
});
|
|
281
|
+
it('should unwrap versioned safe-root envelopes and return VRF keyshares', async () => {
|
|
282
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
283
|
+
const userVrfKeyShare = Buffer.from('user-vrf-keyshare');
|
|
284
|
+
const backupVrfKeyShare = Buffer.from('backup-vrf-keyshare');
|
|
285
|
+
const encodeEnvelope = (reducedKeyShare, vrfKeyShare) => Buffer.from((0, cbor_x_1.encode)({
|
|
286
|
+
version: 1,
|
|
287
|
+
prvKeyShare: new Uint8Array(reducedKeyShare),
|
|
288
|
+
vrf: new Uint8Array(vrfKeyShare),
|
|
289
|
+
}));
|
|
290
|
+
const result = await src_1.EDDSAUtils.getEddsaMpcV2RecoveryKeySharesFromReducedKey(encryptKey(encodeEnvelope(userDkg.getReducedKeyShare(), userVrfKeyShare)), encryptKey(encodeEnvelope(backupDkg.getReducedKeyShare(), backupVrfKeyShare)), walletPassphrase);
|
|
291
|
+
assert.strictEqual(Buffer.compare(result.userKeyShare, userDkg.getKeyShare()), 0);
|
|
292
|
+
assert.strictEqual(Buffer.compare(result.backupKeyShare, backupDkg.getKeyShare()), 0);
|
|
293
|
+
assert.strictEqual(result.commonKeyChain, userDkg.getCommonKeychain());
|
|
294
|
+
assert.ok(result.userVrfKeyShare);
|
|
295
|
+
assert.ok(result.backupVrfKeyShare);
|
|
296
|
+
assert.strictEqual(Buffer.compare(result.userVrfKeyShare, userVrfKeyShare), 0);
|
|
297
|
+
assert.strictEqual(Buffer.compare(result.backupVrfKeyShare, backupVrfKeyShare), 0);
|
|
298
|
+
});
|
|
299
|
+
it('should route decryption through bitgo.decrypt when a bitgo instance is provided', async () => {
|
|
300
|
+
// sdk-core has no devDependency on sdk-api or argon2, so we cannot encrypt with a real v2 envelope here.
|
|
301
|
+
// The stub verifies that the function delegates to bitgo.decrypt (which supports v1 + v2 in
|
|
302
|
+
// production) rather than falling back to sjcl.decrypt.
|
|
303
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
304
|
+
const userKeyBase64 = userDkg.getReducedKeyShare().toString('base64');
|
|
305
|
+
const backupKeyBase64 = backupDkg.getReducedKeyShare().toString('base64');
|
|
306
|
+
const mockBitgo = {
|
|
307
|
+
decrypt: sinon.stub().onFirstCall().resolves(userKeyBase64).onSecondCall().resolves(backupKeyBase64),
|
|
308
|
+
};
|
|
309
|
+
const result = await src_1.EDDSAUtils.getEddsaMpcV2RecoveryKeySharesFromReducedKey('encrypted-user-key', 'encrypted-backup-key', walletPassphrase, mockBitgo);
|
|
310
|
+
sinon.assert.calledTwice(mockBitgo.decrypt);
|
|
311
|
+
assert.deepStrictEqual(result.userKeyShare, userDkg.getKeyShare());
|
|
312
|
+
assert.deepStrictEqual(result.backupKeyShare, backupDkg.getKeyShare());
|
|
313
|
+
assert.strictEqual(result.commonKeyChain, userDkg.getCommonKeychain());
|
|
314
|
+
});
|
|
315
|
+
it('should reject a malformed keycard with a descriptive error', async () => {
|
|
316
|
+
const [userDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
317
|
+
const malformedKey = sjcl.encrypt(walletPassphrase, (0, crypto_1.randomBytes)(64).toString('base64'));
|
|
318
|
+
await assert.rejects(src_1.EDDSAUtils.getEddsaMpcV2RecoveryKeySharesFromReducedKey(malformedKey, encryptKey(userDkg.getReducedKeyShare()), walletPassphrase), /unable to decode reduced key share/);
|
|
319
|
+
});
|
|
320
|
+
it('should reject reduced keys from different wallets', async () => {
|
|
321
|
+
const [userDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
322
|
+
const [, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
323
|
+
await assert.rejects(src_1.EDDSAUtils.getEddsaMpcV2RecoveryKeySharesFromReducedKey(encryptKey(userDkg.getReducedKeyShare()), encryptKey(backupDkg.getReducedKeyShare()), walletPassphrase), /pub keys do not match/);
|
|
324
|
+
});
|
|
325
|
+
it('should reject reduced keys with matching pub but mismatched rootChainCodes', async () => {
|
|
326
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
327
|
+
const userReducedKeyShare = userDkg.getReducedKeyShare();
|
|
328
|
+
const backupReducedKeyShare = backupDkg.getReducedKeyShare();
|
|
329
|
+
const getDecodedReducedKeyShare = sdk_lib_mpc_1.MPSTypes.getDecodedReducedKeyShare;
|
|
330
|
+
const decodeStub = sinon.stub(sdk_lib_mpc_1.MPSTypes, 'getDecodedReducedKeyShare').callsFake((buf) => {
|
|
331
|
+
const reduced = getDecodedReducedKeyShare(buf);
|
|
332
|
+
if (Buffer.from(buf).equals(backupReducedKeyShare)) {
|
|
333
|
+
return {
|
|
334
|
+
...reduced,
|
|
335
|
+
rootChainCode: Array.from((0, crypto_1.randomBytes)(32)),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
return reduced;
|
|
339
|
+
});
|
|
340
|
+
try {
|
|
341
|
+
await assert.rejects(src_1.EDDSAUtils.getEddsaMpcV2RecoveryKeySharesFromReducedKey(encryptKey(userReducedKeyShare), encryptKey(backupReducedKeyShare), walletPassphrase), /rootChainCodes do not match/);
|
|
342
|
+
}
|
|
343
|
+
finally {
|
|
344
|
+
decodeStub.restore();
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
describe('EddsaMPCv2Utils.createOfflineRound1Share', () => {
|
|
349
|
+
let eddsaMPCv2Utils;
|
|
350
|
+
let mockBitgo;
|
|
351
|
+
let userKeyShare;
|
|
352
|
+
const walletPassphrase = 'testPass';
|
|
353
|
+
const signableHex = 'deadbeef';
|
|
354
|
+
const derivationPath = 'm/0/0';
|
|
355
|
+
const expectedAdata = `${signableHex}:${derivationPath}`;
|
|
356
|
+
const txRequest = {
|
|
357
|
+
txRequestId: 'txreq-eddsa-round1',
|
|
358
|
+
walletId: 'wallet-eddsa-round1',
|
|
359
|
+
enterpriseId: 'enterprise-eddsa-round1',
|
|
360
|
+
apiVersion: 'full',
|
|
361
|
+
transactions: [
|
|
362
|
+
{
|
|
363
|
+
unsignedTx: {
|
|
364
|
+
signableHex,
|
|
365
|
+
derivationPath,
|
|
366
|
+
serializedTxHex: signableHex,
|
|
367
|
+
},
|
|
368
|
+
signatureShares: [],
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
intent: { intentType: 'payment' },
|
|
372
|
+
unsignedTxs: [],
|
|
373
|
+
};
|
|
374
|
+
before('generate EdDSA user key share', async () => {
|
|
375
|
+
const [userDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
376
|
+
userKeyShare = userDkg.getKeyShare();
|
|
377
|
+
});
|
|
378
|
+
beforeEach(() => {
|
|
379
|
+
const sjclEncrypt = (params) => {
|
|
380
|
+
const salt = (0, crypto_1.randomBytes)(8);
|
|
381
|
+
const iv = (0, crypto_1.randomBytes)(16);
|
|
382
|
+
return sjcl.encrypt(params.password, params.input, {
|
|
383
|
+
salt: [bytesToWord(salt.subarray(0, 4)), bytesToWord(salt.subarray(4))],
|
|
384
|
+
iv: [
|
|
385
|
+
bytesToWord(iv.subarray(0, 4)),
|
|
386
|
+
bytesToWord(iv.subarray(4, 8)),
|
|
387
|
+
bytesToWord(iv.subarray(8, 12)),
|
|
388
|
+
bytesToWord(iv.subarray(12, 16)),
|
|
389
|
+
],
|
|
390
|
+
adata: params.adata,
|
|
391
|
+
});
|
|
392
|
+
};
|
|
393
|
+
mockBitgo = {
|
|
394
|
+
encrypt: sinon.stub().callsFake(async (params) => sjclEncrypt(params)),
|
|
395
|
+
};
|
|
396
|
+
const mockCoin = {
|
|
397
|
+
getMPCAlgorithm: sinon.stub().returns('eddsa'),
|
|
398
|
+
};
|
|
399
|
+
eddsaMPCv2Utils = new src_1.EddsaMPCv2Utils(mockBitgo, mockCoin);
|
|
400
|
+
});
|
|
401
|
+
it('should create a round-1 share and encrypted SJCL session payload', async () => {
|
|
402
|
+
const result = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
403
|
+
txRequest,
|
|
404
|
+
prv: userKeyShare.toString('base64'),
|
|
405
|
+
walletPassphrase,
|
|
406
|
+
});
|
|
407
|
+
assert.strictEqual(result.signatureShareRound1.from, src_1.SignatureShareType.USER);
|
|
408
|
+
assert.strictEqual(result.signatureShareRound1.to, src_1.SignatureShareType.BITGO);
|
|
409
|
+
assert.ok(result.userGpgPubKey.includes('BEGIN PGP PUBLIC KEY BLOCK'));
|
|
410
|
+
assert.ok(JSON.parse(result.encryptedRound1Session).ct, 'encryptedRound1Session should be an SJCL JSON blob');
|
|
411
|
+
assert.ok(JSON.parse(result.encryptedUserGpgPrvKey).ct, 'encryptedUserGpgPrvKey should be an SJCL JSON blob');
|
|
412
|
+
const parsedShare = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound1Input, JSON.parse(result.signatureShareRound1.share), 'EddsaMPCv2SignatureShareRound1Input');
|
|
413
|
+
assert.strictEqual(parsedShare.type, 'round1Input');
|
|
414
|
+
assert.ok(parsedShare.data.msg1.message, 'msg1.message should be set');
|
|
415
|
+
assert.ok(parsedShare.data.msg1.signature, 'msg1.signature should be set');
|
|
416
|
+
const encryptedRound1Session = JSON.parse(result.encryptedRound1Session);
|
|
417
|
+
const encryptedUserGpgPrvKey = JSON.parse(result.encryptedUserGpgPrvKey);
|
|
418
|
+
assert.strictEqual(decodeURIComponent(encryptedRound1Session.adata), `MPS_DSG_SIGNING_ROUND1_STATE:${expectedAdata}`, 'round-1 session adata should bind the signing context');
|
|
419
|
+
assert.strictEqual(decodeURIComponent(encryptedUserGpgPrvKey.adata), `MPS_DSG_SIGNING_USER_GPG_KEY:${expectedAdata}`, 'GPG private key adata should bind the signing context');
|
|
420
|
+
const sessionPayload = JSON.parse(sjcl.decrypt(walletPassphrase, result.encryptedRound1Session));
|
|
421
|
+
assert.ok(sessionPayload.dsgSession, 'dsgSession should be persisted for round 2');
|
|
422
|
+
assert.ok(sessionPayload.userMsgPayload, 'userMsgPayload should be persisted for round 2');
|
|
423
|
+
});
|
|
424
|
+
it('should use v2 encryption when encryptedPrv is a v2 envelope', async () => {
|
|
425
|
+
const encrypt = sinon
|
|
426
|
+
.stub()
|
|
427
|
+
.callsFake((input, adata) => Promise.resolve(JSON.stringify({ v: 2, input, adata })));
|
|
428
|
+
const destroy = sinon.stub();
|
|
429
|
+
const createEncryptionSession = sinon.stub().resolves({ encrypt, destroy });
|
|
430
|
+
mockBitgo.createEncryptionSession = createEncryptionSession;
|
|
431
|
+
const result = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
432
|
+
txRequest,
|
|
433
|
+
prv: userKeyShare.toString('base64'),
|
|
434
|
+
walletPassphrase,
|
|
435
|
+
encryptedPrv: JSON.stringify({ v: 2 }),
|
|
436
|
+
});
|
|
437
|
+
sinon.assert.calledOnce(createEncryptionSession);
|
|
438
|
+
assert.strictEqual(createEncryptionSession.getCall(0).args[0], walletPassphrase);
|
|
439
|
+
sinon.assert.notCalled(mockBitgo.encrypt);
|
|
440
|
+
sinon.assert.calledTwice(encrypt);
|
|
441
|
+
sinon.assert.calledOnce(destroy);
|
|
442
|
+
const encryptedRound1Session = JSON.parse(result.encryptedRound1Session);
|
|
443
|
+
const encryptedUserGpgPrvKey = JSON.parse(result.encryptedUserGpgPrvKey);
|
|
444
|
+
assert.strictEqual(encryptedRound1Session.v, 2);
|
|
445
|
+
assert.strictEqual(encryptedRound1Session.adata, `MPS_DSG_SIGNING_ROUND1_STATE:${expectedAdata}`);
|
|
446
|
+
assert.strictEqual(encryptedUserGpgPrvKey.v, 2);
|
|
447
|
+
assert.strictEqual(encryptedUserGpgPrvKey.adata, `MPS_DSG_SIGNING_USER_GPG_KEY:${expectedAdata}`);
|
|
448
|
+
const sessionPayload = JSON.parse(encryptedRound1Session.input);
|
|
449
|
+
assert.ok(sessionPayload.dsgSession, 'dsgSession should be persisted for round 2');
|
|
450
|
+
assert.ok(sessionPayload.userMsgPayload, 'userMsgPayload should be persisted for round 2');
|
|
451
|
+
});
|
|
452
|
+
it('should use SJCL encryption when encryptedPrv is a v1 blob', async () => {
|
|
453
|
+
mockBitgo.createEncryptionSession = sinon.stub();
|
|
454
|
+
const encryptedPrv = sjcl.encrypt(walletPassphrase, userKeyShare.toString('base64'));
|
|
455
|
+
const result = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
456
|
+
txRequest,
|
|
457
|
+
prv: userKeyShare.toString('base64'),
|
|
458
|
+
walletPassphrase,
|
|
459
|
+
encryptedPrv,
|
|
460
|
+
});
|
|
461
|
+
sinon.assert.notCalled(mockBitgo.createEncryptionSession);
|
|
462
|
+
sinon.assert.calledTwice(mockBitgo.encrypt);
|
|
463
|
+
assert.ok(JSON.parse(result.encryptedRound1Session).ct, 'encryptedRound1Session should be an SJCL JSON blob');
|
|
464
|
+
assert.ok(JSON.parse(result.encryptedUserGpgPrvKey).ct, 'encryptedUserGpgPrvKey should be an SJCL JSON blob');
|
|
465
|
+
});
|
|
466
|
+
it('should propagate the tx-only guard when transactions are missing', async () => {
|
|
467
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound1Share({
|
|
468
|
+
txRequest: { ...txRequest, transactions: undefined },
|
|
469
|
+
prv: userKeyShare.toString('base64'),
|
|
470
|
+
walletPassphrase,
|
|
471
|
+
}), /Unable to find transactions in txRequest/);
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
describe('EddsaMPCv2Utils.createOfflineKeyGenRound1Share', () => {
|
|
475
|
+
let eddsaMPCv2Utils;
|
|
476
|
+
let mockBitgo;
|
|
477
|
+
let userGpgKeyPair;
|
|
478
|
+
let backupGpgKeyPair;
|
|
479
|
+
let bitgoGpgKeyPair;
|
|
480
|
+
const walletPassphrase = 'testPass';
|
|
481
|
+
before('generate GPG key pairs', async () => {
|
|
482
|
+
userGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
483
|
+
backupGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
484
|
+
bitgoGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
485
|
+
});
|
|
486
|
+
beforeEach(() => {
|
|
487
|
+
const sjclEncrypt = (params) => {
|
|
488
|
+
const salt = (0, crypto_1.randomBytes)(8);
|
|
489
|
+
const iv = (0, crypto_1.randomBytes)(16);
|
|
490
|
+
return sjcl.encrypt(params.password, params.input, {
|
|
491
|
+
salt: [bytesToWord(salt.subarray(0, 4)), bytesToWord(salt.subarray(4))],
|
|
492
|
+
iv: [
|
|
493
|
+
bytesToWord(iv.subarray(0, 4)),
|
|
494
|
+
bytesToWord(iv.subarray(4, 8)),
|
|
495
|
+
bytesToWord(iv.subarray(8, 12)),
|
|
496
|
+
bytesToWord(iv.subarray(12, 16)),
|
|
497
|
+
],
|
|
498
|
+
adata: params.adata,
|
|
499
|
+
});
|
|
500
|
+
};
|
|
501
|
+
mockBitgo = {
|
|
502
|
+
encrypt: sinon.stub().callsFake(sjclEncrypt),
|
|
503
|
+
encryptAsync: sinon.stub().callsFake(async (params) => sjclEncrypt(params)),
|
|
504
|
+
decrypt: sinon.stub().callsFake((params) => sjcl.decrypt(params.password, params.input)),
|
|
505
|
+
decryptAsync: sinon.stub().callsFake(async (params) => sjcl.decrypt(params.password, params.input)),
|
|
506
|
+
getEnv: sinon.stub().returns('mock'),
|
|
507
|
+
};
|
|
508
|
+
const mockCoin = {
|
|
509
|
+
getMPCAlgorithm: sinon.stub().returns('eddsa'),
|
|
510
|
+
};
|
|
511
|
+
eddsaMPCv2Utils = new src_1.EddsaMPCv2Utils(mockBitgo, mockCoin);
|
|
512
|
+
});
|
|
513
|
+
it('should produce valid signedMsg1 and encrypted round-1 session', async () => {
|
|
514
|
+
const encryptedUserGpgPrvKey = sjcl.encrypt(walletPassphrase, userGpgKeyPair.privateKey);
|
|
515
|
+
const result = await eddsaMPCv2Utils.createOfflineKeyGenRound1Share({
|
|
516
|
+
walletPassphrase,
|
|
517
|
+
encryptedUserGpgPrvKey,
|
|
518
|
+
bitgoGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
519
|
+
counterPartyGpgPubKey: backupGpgKeyPair.publicKey,
|
|
520
|
+
});
|
|
521
|
+
assert.ok(result.signedMsg1.message, 'signedMsg1.message should be set');
|
|
522
|
+
assert.ok(result.signedMsg1.signature.includes('BEGIN PGP SIGNATURE'), 'signedMsg1.signature should be PGP armored');
|
|
523
|
+
assert.ok(JSON.parse(result.encryptedRound1Session).ct, 'encryptedRound1Session should be an SJCL JSON blob');
|
|
524
|
+
});
|
|
525
|
+
it('encryptedRound1Session should only be decryptable with correct walletPassphrase', async () => {
|
|
526
|
+
const encryptedUserGpgPrvKey = sjcl.encrypt(walletPassphrase, userGpgKeyPair.privateKey);
|
|
527
|
+
const result = await eddsaMPCv2Utils.createOfflineKeyGenRound1Share({
|
|
528
|
+
walletPassphrase,
|
|
529
|
+
encryptedUserGpgPrvKey,
|
|
530
|
+
bitgoGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
531
|
+
counterPartyGpgPubKey: backupGpgKeyPair.publicKey,
|
|
532
|
+
});
|
|
533
|
+
const decrypted = sjcl.decrypt(walletPassphrase, result.encryptedRound1Session);
|
|
534
|
+
const session = JSON.parse(decrypted);
|
|
535
|
+
assert.ok(session.dkgSession, 'dkgSession should be persisted');
|
|
536
|
+
assert.ok(session.ownMsgPayload, 'ownMsgPayload should be persisted');
|
|
537
|
+
assert.strictEqual(typeof session.ownMsgFrom, 'number', 'ownMsgFrom should be a number');
|
|
538
|
+
assert.throws(() => sjcl.decrypt('wrongpassphrase', result.encryptedRound1Session), 'should throw on wrong passphrase');
|
|
539
|
+
});
|
|
540
|
+
it('should restore DKG session and handle round-2 messages after round 1', async () => {
|
|
541
|
+
const encryptedUserGpgPrvKey = sjcl.encrypt(walletPassphrase, userGpgKeyPair.privateKey);
|
|
542
|
+
const result = await eddsaMPCv2Utils.createOfflineKeyGenRound1Share({
|
|
543
|
+
walletPassphrase,
|
|
544
|
+
encryptedUserGpgPrvKey,
|
|
545
|
+
bitgoGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
546
|
+
counterPartyGpgPubKey: backupGpgKeyPair.publicKey,
|
|
547
|
+
});
|
|
548
|
+
const decrypted = sjcl.decrypt(walletPassphrase, result.encryptedRound1Session);
|
|
549
|
+
const { dkgSession, ownMsgPayload, ownMsgFrom } = JSON.parse(decrypted);
|
|
550
|
+
const restoredDkg = new sdk_lib_mpc_1.EddsaMPSDkg.DKG(3, 2, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
551
|
+
await restoredDkg.restoreSession(dkgSession);
|
|
552
|
+
const ownMsg1 = {
|
|
553
|
+
from: ownMsgFrom,
|
|
554
|
+
payload: new Uint8Array(Buffer.from(ownMsgPayload, 'base64')),
|
|
555
|
+
};
|
|
556
|
+
assert.ok(ownMsg1.payload.length > 0, 'restored payload should be non-empty');
|
|
557
|
+
const userGpgKey = await pgp.readKey({ armoredKey: userGpgKeyPair.publicKey });
|
|
558
|
+
const rawBytes = await sdk_lib_mpc_1.MPSComms.verifyMpsMessage(result.signedMsg1, userGpgKey);
|
|
559
|
+
assert.ok(rawBytes.length > 0, 'signedMsg1 should verify against user GPG key');
|
|
560
|
+
});
|
|
561
|
+
it('should reject invalid encryptedUserGpgPrvKey', async () => {
|
|
562
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineKeyGenRound1Share({
|
|
563
|
+
walletPassphrase,
|
|
564
|
+
encryptedUserGpgPrvKey: sjcl.encrypt(walletPassphrase, 'not-a-gpg-key'),
|
|
565
|
+
bitgoGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
566
|
+
counterPartyGpgPubKey: backupGpgKeyPair.publicKey,
|
|
567
|
+
}), 'should throw when GPG key cannot be parsed');
|
|
568
|
+
});
|
|
569
|
+
it('USER and BACKUP partyId produce different encrypted session state', async () => {
|
|
570
|
+
const userEncryptedGpgPrvKey = sjcl.encrypt(walletPassphrase, userGpgKeyPair.privateKey);
|
|
571
|
+
const userResult = await eddsaMPCv2Utils.createOfflineKeyGenRound1Share({
|
|
572
|
+
walletPassphrase,
|
|
573
|
+
encryptedUserGpgPrvKey: userEncryptedGpgPrvKey,
|
|
574
|
+
bitgoGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
575
|
+
counterPartyGpgPubKey: backupGpgKeyPair.publicKey,
|
|
576
|
+
partyId: typesMPCv2_1.MPCv2PartiesEnum.USER,
|
|
577
|
+
});
|
|
578
|
+
const backupEncryptedGpgPrvKey2 = sjcl.encrypt(walletPassphrase, backupGpgKeyPair.privateKey);
|
|
579
|
+
const backupResult = await eddsaMPCv2Utils.createOfflineKeyGenRound1Share({
|
|
580
|
+
walletPassphrase,
|
|
581
|
+
encryptedUserGpgPrvKey: backupEncryptedGpgPrvKey2,
|
|
582
|
+
bitgoGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
583
|
+
counterPartyGpgPubKey: userGpgKeyPair.publicKey,
|
|
584
|
+
partyId: typesMPCv2_1.MPCv2PartiesEnum.BACKUP,
|
|
585
|
+
});
|
|
586
|
+
const userSession = JSON.parse(sjcl.decrypt(walletPassphrase, userResult.encryptedRound1Session));
|
|
587
|
+
const backupSession = JSON.parse(sjcl.decrypt(walletPassphrase, backupResult.encryptedRound1Session));
|
|
588
|
+
assert.strictEqual(userSession.ownMsgFrom, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
589
|
+
assert.strictEqual(backupSession.ownMsgFrom, typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
590
|
+
assert.notStrictEqual(userSession.dkgSession, backupSession.dkgSession, 'Sessions should differ between parties');
|
|
591
|
+
// Sessions encrypted with party-bound adata — tampered adata fails CCM tag check
|
|
592
|
+
const tamperedSession = (() => {
|
|
593
|
+
const parsed = JSON.parse(userResult.encryptedRound1Session);
|
|
594
|
+
parsed.adata = encodeURIComponent(`MPS_DKG_KEYGEN_ROUND1_STATE:${typesMPCv2_1.MPCv2PartiesEnum.BACKUP}`);
|
|
595
|
+
return JSON.stringify(parsed);
|
|
596
|
+
})();
|
|
597
|
+
assert.throws(() => sjcl.decrypt(walletPassphrase, tamperedSession), 'should fail to decrypt with wrong party adata');
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
describe('EddsaMPCv2Utils.createOfflineRound2Share', () => {
|
|
601
|
+
let eddsaMPCv2Utils;
|
|
602
|
+
let mockBitgo;
|
|
603
|
+
let userKeyShare;
|
|
604
|
+
let bitgoKeyShare;
|
|
605
|
+
let bitgoGpgKeyPair;
|
|
606
|
+
let bitgoGpgPrivKey;
|
|
607
|
+
const walletPassphrase = 'testPass';
|
|
608
|
+
const signableHex = 'deadbeef';
|
|
609
|
+
const derivationPath = 'm/0/0';
|
|
610
|
+
const expectedAdata = `${signableHex}:${derivationPath}`;
|
|
611
|
+
const baseTxRequest = {
|
|
612
|
+
txRequestId: 'txreq-eddsa-round2',
|
|
613
|
+
walletId: 'wallet-eddsa-round2',
|
|
614
|
+
enterpriseId: 'enterprise-eddsa-round2',
|
|
615
|
+
apiVersion: 'full',
|
|
616
|
+
transactions: [
|
|
617
|
+
{
|
|
618
|
+
unsignedTx: {
|
|
619
|
+
signableHex,
|
|
620
|
+
derivationPath,
|
|
621
|
+
serializedTxHex: signableHex,
|
|
622
|
+
},
|
|
623
|
+
signatureShares: [],
|
|
624
|
+
},
|
|
625
|
+
],
|
|
626
|
+
intent: { intentType: 'payment' },
|
|
627
|
+
unsignedTxs: [],
|
|
628
|
+
};
|
|
629
|
+
before('generate EdDSA key shares and GPG keys', async () => {
|
|
630
|
+
const [userDkg, , bitgoDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
631
|
+
userKeyShare = userDkg.getKeyShare();
|
|
632
|
+
bitgoKeyShare = bitgoDkg.getKeyShare();
|
|
633
|
+
bitgoGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
634
|
+
bitgoGpgPrivKey = await pgp.readPrivateKey({ armoredKey: bitgoGpgKeyPair.privateKey });
|
|
635
|
+
});
|
|
636
|
+
beforeEach(() => {
|
|
637
|
+
mockBitgo = {
|
|
638
|
+
encrypt: sinon.stub().callsFake(async (params) => {
|
|
639
|
+
const salt = (0, crypto_1.randomBytes)(8);
|
|
640
|
+
const iv = (0, crypto_1.randomBytes)(16);
|
|
641
|
+
return sjcl.encrypt(params.password, params.input, {
|
|
642
|
+
salt: [bytesToWord(salt.subarray(0, 4)), bytesToWord(salt.subarray(4))],
|
|
643
|
+
iv: [
|
|
644
|
+
bytesToWord(iv.subarray(0, 4)),
|
|
645
|
+
bytesToWord(iv.subarray(4, 8)),
|
|
646
|
+
bytesToWord(iv.subarray(8, 12)),
|
|
647
|
+
bytesToWord(iv.subarray(12, 16)),
|
|
648
|
+
],
|
|
649
|
+
adata: params.adata,
|
|
650
|
+
});
|
|
651
|
+
}),
|
|
652
|
+
decrypt: sinon.stub().callsFake(async (params) => sjcl.decrypt(params.password, params.input)),
|
|
653
|
+
};
|
|
654
|
+
const mockCoin = {
|
|
655
|
+
getMPCAlgorithm: sinon.stub().returns('eddsa'),
|
|
656
|
+
};
|
|
657
|
+
eddsaMPCv2Utils = new src_1.EddsaMPCv2Utils(mockBitgo, mockCoin);
|
|
658
|
+
});
|
|
659
|
+
it('should create a round-2 share from offline round 1', async () => {
|
|
660
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
661
|
+
txRequest: baseTxRequest,
|
|
662
|
+
prv: userKeyShare.toString('base64'),
|
|
663
|
+
walletPassphrase,
|
|
664
|
+
});
|
|
665
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
666
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
667
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
668
|
+
const txRequestRound1 = await signBitgoEddsaRound1(bitgoDsg, cloneTxRequestWithEmptySignatureShares(baseTxRequest), round1.signatureShareRound1, round1.userGpgPubKey, bitgoGpgPrivKey);
|
|
669
|
+
const round2 = await eddsaMPCv2Utils.createOfflineRound2Share({
|
|
670
|
+
txRequest: txRequestRound1,
|
|
671
|
+
walletPassphrase,
|
|
672
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
673
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
674
|
+
encryptedRound1Session: round1.encryptedRound1Session,
|
|
675
|
+
});
|
|
676
|
+
assert.strictEqual(round2.signatureShareRound2.from, src_1.SignatureShareType.USER);
|
|
677
|
+
assert.strictEqual(round2.signatureShareRound2.to, src_1.SignatureShareType.BITGO);
|
|
678
|
+
const parsedShare = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound2Input, JSON.parse(round2.signatureShareRound2.share), 'EddsaMPCv2SignatureShareRound2Input');
|
|
679
|
+
assert.strictEqual(parsedShare.type, 'round2Input');
|
|
680
|
+
assert.ok(parsedShare.data.msg2.message, 'msg2.message should be set');
|
|
681
|
+
assert.ok(parsedShare.data.msg2.signature, 'msg2.signature should be set');
|
|
682
|
+
const encryptedRound2Session = JSON.parse(round2.encryptedRound2Session);
|
|
683
|
+
assert.strictEqual(decodeURIComponent(encryptedRound2Session.adata), `MPS_DSG_SIGNING_ROUND2_STATE:${expectedAdata}`);
|
|
684
|
+
const sessionPayload = JSON.parse(sjcl.decrypt(walletPassphrase, round2.encryptedRound2Session));
|
|
685
|
+
assert.ok(sessionPayload.dsgSession, 'dsgSession should be persisted for round 3');
|
|
686
|
+
assert.ok(sessionPayload.userMsgPayload, 'userMsgPayload should be persisted for round 3');
|
|
687
|
+
});
|
|
688
|
+
it('should use v2 decryption when encryptedRound1Session is a v2 envelope', async () => {
|
|
689
|
+
const encrypt = sinon
|
|
690
|
+
.stub()
|
|
691
|
+
.callsFake((input, adata) => Promise.resolve(JSON.stringify({ v: 2, input, adata })));
|
|
692
|
+
const destroy = sinon.stub();
|
|
693
|
+
const createEncryptionSession = sinon.stub().resolves({ encrypt, destroy });
|
|
694
|
+
mockBitgo.createEncryptionSession = createEncryptionSession;
|
|
695
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
696
|
+
txRequest: baseTxRequest,
|
|
697
|
+
prv: userKeyShare.toString('base64'),
|
|
698
|
+
walletPassphrase,
|
|
699
|
+
encryptedPrv: JSON.stringify({ v: 2 }),
|
|
700
|
+
});
|
|
701
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
702
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
703
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
704
|
+
const txRequestRound1 = await signBitgoEddsaRound1(bitgoDsg, cloneTxRequestWithEmptySignatureShares(baseTxRequest), round1.signatureShareRound1, round1.userGpgPubKey, bitgoGpgPrivKey);
|
|
705
|
+
const decrypt = sinon.stub().callsFake(async (params) => {
|
|
706
|
+
const envelope = JSON.parse(params.input);
|
|
707
|
+
return envelope.input;
|
|
708
|
+
});
|
|
709
|
+
mockBitgo.decrypt = decrypt;
|
|
710
|
+
const round2 = await eddsaMPCv2Utils.createOfflineRound2Share({
|
|
711
|
+
txRequest: txRequestRound1,
|
|
712
|
+
walletPassphrase,
|
|
713
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
714
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
715
|
+
encryptedRound1Session: round1.encryptedRound1Session,
|
|
716
|
+
});
|
|
717
|
+
sinon.assert.called(mockBitgo.decrypt);
|
|
718
|
+
assert.strictEqual(round2.signatureShareRound2.from, src_1.SignatureShareType.USER);
|
|
719
|
+
const encryptedRound2Session = JSON.parse(round2.encryptedRound2Session);
|
|
720
|
+
assert.strictEqual(encryptedRound2Session.v, 2);
|
|
721
|
+
assert.strictEqual(encryptedRound2Session.adata, `MPS_DSG_SIGNING_ROUND2_STATE:${expectedAdata}`);
|
|
722
|
+
});
|
|
723
|
+
it('should reject tampered encryptedRound1Session adata', async () => {
|
|
724
|
+
const otherTxRequest = {
|
|
725
|
+
...baseTxRequest,
|
|
726
|
+
transactions: [
|
|
727
|
+
{
|
|
728
|
+
unsignedTx: {
|
|
729
|
+
signableHex: 'cafebabe',
|
|
730
|
+
derivationPath: 'm/1/2',
|
|
731
|
+
serializedTxHex: 'cafebabe',
|
|
732
|
+
},
|
|
733
|
+
signatureShares: [],
|
|
734
|
+
},
|
|
735
|
+
],
|
|
736
|
+
};
|
|
737
|
+
const round1Other = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
738
|
+
txRequest: otherTxRequest,
|
|
739
|
+
prv: userKeyShare.toString('base64'),
|
|
740
|
+
walletPassphrase,
|
|
741
|
+
});
|
|
742
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
743
|
+
txRequest: baseTxRequest,
|
|
744
|
+
prv: userKeyShare.toString('base64'),
|
|
745
|
+
walletPassphrase,
|
|
746
|
+
});
|
|
747
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
748
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
749
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
750
|
+
const txRequestRound1 = await signBitgoEddsaRound1(bitgoDsg, cloneTxRequestWithEmptySignatureShares(baseTxRequest), round1.signatureShareRound1, round1.userGpgPubKey, bitgoGpgPrivKey);
|
|
751
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound2Share({
|
|
752
|
+
txRequest: txRequestRound1,
|
|
753
|
+
walletPassphrase,
|
|
754
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
755
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
756
|
+
encryptedRound1Session: round1Other.encryptedRound1Session,
|
|
757
|
+
}), /Adata does not match cyphertext adata/);
|
|
758
|
+
});
|
|
759
|
+
it('should reject tampered encryptedUserGpgPrvKey adata', async () => {
|
|
760
|
+
const otherTxRequest = {
|
|
761
|
+
...baseTxRequest,
|
|
762
|
+
transactions: [
|
|
763
|
+
{
|
|
764
|
+
unsignedTx: {
|
|
765
|
+
signableHex: 'cafebabe',
|
|
766
|
+
derivationPath: 'm/1/2',
|
|
767
|
+
serializedTxHex: 'cafebabe',
|
|
768
|
+
},
|
|
769
|
+
signatureShares: [],
|
|
770
|
+
},
|
|
771
|
+
],
|
|
772
|
+
};
|
|
773
|
+
const round1Other = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
774
|
+
txRequest: otherTxRequest,
|
|
775
|
+
prv: userKeyShare.toString('base64'),
|
|
776
|
+
walletPassphrase,
|
|
777
|
+
});
|
|
778
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
779
|
+
txRequest: baseTxRequest,
|
|
780
|
+
prv: userKeyShare.toString('base64'),
|
|
781
|
+
walletPassphrase,
|
|
782
|
+
});
|
|
783
|
+
const messageBuffer = Buffer.from(signableHex, 'hex');
|
|
784
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
785
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
786
|
+
const txRequestRound1 = await signBitgoEddsaRound1(bitgoDsg, cloneTxRequestWithEmptySignatureShares(baseTxRequest), round1.signatureShareRound1, round1.userGpgPubKey, bitgoGpgPrivKey);
|
|
787
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound2Share({
|
|
788
|
+
txRequest: txRequestRound1,
|
|
789
|
+
walletPassphrase,
|
|
790
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
791
|
+
encryptedUserGpgPrvKey: round1Other.encryptedUserGpgPrvKey,
|
|
792
|
+
encryptedRound1Session: round1.encryptedRound1Session,
|
|
793
|
+
}), /Adata does not match cyphertext adata/);
|
|
794
|
+
});
|
|
795
|
+
it('should reject when BitGo signature share is missing', async () => {
|
|
796
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
797
|
+
txRequest: baseTxRequest,
|
|
798
|
+
prv: userKeyShare.toString('base64'),
|
|
799
|
+
walletPassphrase,
|
|
800
|
+
});
|
|
801
|
+
const baseTransaction = assertSingleTransaction(baseTxRequest);
|
|
802
|
+
const txRequestNoBitgoShare = {
|
|
803
|
+
...baseTxRequest,
|
|
804
|
+
transactions: [
|
|
805
|
+
{
|
|
806
|
+
...baseTransaction,
|
|
807
|
+
signatureShares: [round1.signatureShareRound1],
|
|
808
|
+
},
|
|
809
|
+
],
|
|
810
|
+
};
|
|
811
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound2Share({
|
|
812
|
+
txRequest: txRequestNoBitgoShare,
|
|
813
|
+
walletPassphrase,
|
|
814
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
815
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
816
|
+
encryptedRound1Session: round1.encryptedRound1Session,
|
|
817
|
+
}), /Missing BitGo round1Output signature share/);
|
|
818
|
+
});
|
|
819
|
+
it('should propagate the tx-only guard when transactions are missing', async () => {
|
|
820
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
821
|
+
txRequest: baseTxRequest,
|
|
822
|
+
prv: userKeyShare.toString('base64'),
|
|
823
|
+
walletPassphrase,
|
|
824
|
+
});
|
|
825
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound2Share({
|
|
826
|
+
txRequest: { ...baseTxRequest, transactions: undefined },
|
|
827
|
+
walletPassphrase,
|
|
828
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
829
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
830
|
+
encryptedRound1Session: round1.encryptedRound1Session,
|
|
831
|
+
}), /Unable to find transactions in txRequest/);
|
|
832
|
+
});
|
|
833
|
+
it('should reject when transactions array is empty', async () => {
|
|
834
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
835
|
+
txRequest: baseTxRequest,
|
|
836
|
+
prv: userKeyShare.toString('base64'),
|
|
837
|
+
walletPassphrase,
|
|
838
|
+
});
|
|
839
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound2Share({
|
|
840
|
+
txRequest: { ...baseTxRequest, transactions: [] },
|
|
841
|
+
walletPassphrase,
|
|
842
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
843
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
844
|
+
encryptedRound1Session: round1.encryptedRound1Session,
|
|
845
|
+
}), /Unable to find transactions in txRequest/);
|
|
846
|
+
});
|
|
847
|
+
});
|
|
848
|
+
describe('EddsaMPCv2Utils.createOfflineRound3Share', () => {
|
|
849
|
+
let eddsaMPCv2Utils;
|
|
850
|
+
let mockBitgo;
|
|
851
|
+
let userKeyShare;
|
|
852
|
+
let bitgoKeyShare;
|
|
853
|
+
let bitgoGpgKeyPair;
|
|
854
|
+
let bitgoGpgPrivKey;
|
|
855
|
+
const walletPassphrase = 'testPass';
|
|
856
|
+
const signableHex = 'deadbeef';
|
|
857
|
+
const derivationPath = 'm/0/0';
|
|
858
|
+
const baseTxRequest = {
|
|
859
|
+
txRequestId: 'txreq-eddsa-round3',
|
|
860
|
+
walletId: 'wallet-eddsa-round3',
|
|
861
|
+
enterpriseId: 'enterprise-eddsa-round3',
|
|
862
|
+
apiVersion: 'full',
|
|
863
|
+
transactions: [
|
|
864
|
+
{
|
|
865
|
+
unsignedTx: {
|
|
866
|
+
signableHex,
|
|
867
|
+
derivationPath,
|
|
868
|
+
serializedTxHex: signableHex,
|
|
869
|
+
},
|
|
870
|
+
signatureShares: [],
|
|
871
|
+
},
|
|
872
|
+
],
|
|
873
|
+
intent: { intentType: 'payment' },
|
|
874
|
+
unsignedTxs: [],
|
|
875
|
+
};
|
|
876
|
+
before('generate EdDSA key shares and GPG keys', async () => {
|
|
877
|
+
const [userDkg, , bitgoDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
878
|
+
userKeyShare = userDkg.getKeyShare();
|
|
879
|
+
bitgoKeyShare = bitgoDkg.getKeyShare();
|
|
880
|
+
bitgoGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
881
|
+
bitgoGpgPrivKey = await pgp.readPrivateKey({ armoredKey: bitgoGpgKeyPair.privateKey });
|
|
882
|
+
});
|
|
883
|
+
beforeEach(() => {
|
|
884
|
+
mockBitgo = {
|
|
885
|
+
encrypt: sinon.stub().callsFake(async (params) => {
|
|
886
|
+
const salt = (0, crypto_1.randomBytes)(8);
|
|
887
|
+
const iv = (0, crypto_1.randomBytes)(16);
|
|
888
|
+
return sjcl.encrypt(params.password, params.input, {
|
|
889
|
+
salt: [bytesToWord(salt.subarray(0, 4)), bytesToWord(salt.subarray(4))],
|
|
890
|
+
iv: [
|
|
891
|
+
bytesToWord(iv.subarray(0, 4)),
|
|
892
|
+
bytesToWord(iv.subarray(4, 8)),
|
|
893
|
+
bytesToWord(iv.subarray(8, 12)),
|
|
894
|
+
bytesToWord(iv.subarray(12, 16)),
|
|
895
|
+
],
|
|
896
|
+
adata: params.adata,
|
|
897
|
+
});
|
|
898
|
+
}),
|
|
899
|
+
decrypt: sinon.stub().callsFake(async (params) => sjcl.decrypt(params.password, params.input)),
|
|
900
|
+
};
|
|
901
|
+
const mockCoin = {
|
|
902
|
+
getMPCAlgorithm: sinon.stub().returns('eddsa'),
|
|
903
|
+
};
|
|
904
|
+
eddsaMPCv2Utils = new src_1.EddsaMPCv2Utils(mockBitgo, mockCoin);
|
|
905
|
+
});
|
|
906
|
+
async function createRound2Flow(txRequest, encryptedPrv) {
|
|
907
|
+
const round1 = await eddsaMPCv2Utils.createOfflineRound1Share({
|
|
908
|
+
txRequest,
|
|
909
|
+
prv: userKeyShare.toString('base64'),
|
|
910
|
+
walletPassphrase,
|
|
911
|
+
encryptedPrv,
|
|
912
|
+
});
|
|
913
|
+
const transaction = assertSingleTransaction(txRequest);
|
|
914
|
+
const messageBuffer = Buffer.from(transaction.unsignedTx.signableHex, 'hex');
|
|
915
|
+
const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(typesMPCv2_1.MPCv2PartiesEnum.BITGO);
|
|
916
|
+
await bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, transaction.unsignedTx.derivationPath, typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
917
|
+
const txRequestRound1 = await signBitgoEddsaRound1(bitgoDsg, cloneTxRequestWithEmptySignatureShares(txRequest), round1.signatureShareRound1, round1.userGpgPubKey, bitgoGpgPrivKey);
|
|
918
|
+
const round2 = await eddsaMPCv2Utils.createOfflineRound2Share({
|
|
919
|
+
txRequest: txRequestRound1,
|
|
920
|
+
walletPassphrase,
|
|
921
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
922
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
923
|
+
encryptedRound1Session: round1.encryptedRound1Session,
|
|
924
|
+
});
|
|
925
|
+
const round1Transaction = assertSingleTransaction(txRequestRound1);
|
|
926
|
+
const txRequestRound2 = await signBitgoEddsaRound2(bitgoDsg, {
|
|
927
|
+
...txRequestRound1,
|
|
928
|
+
transactions: [
|
|
929
|
+
{
|
|
930
|
+
...round1Transaction,
|
|
931
|
+
signatureShares: [...round1Transaction.signatureShares],
|
|
932
|
+
},
|
|
933
|
+
],
|
|
934
|
+
}, round2.signatureShareRound2, round1.userGpgPubKey, bitgoGpgPrivKey);
|
|
935
|
+
return { round1, round2, txRequestRound1, txRequestRound2, messageBuffer };
|
|
936
|
+
}
|
|
937
|
+
it('should create a round-3 share from offline round 2', async () => {
|
|
938
|
+
const { round1, round2, txRequestRound2 } = await createRound2Flow(baseTxRequest);
|
|
939
|
+
const round3 = await eddsaMPCv2Utils.createOfflineRound3Share({
|
|
940
|
+
txRequest: txRequestRound2,
|
|
941
|
+
walletPassphrase,
|
|
942
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
943
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
944
|
+
encryptedRound2Session: round2.encryptedRound2Session,
|
|
945
|
+
});
|
|
946
|
+
assert.strictEqual(round3.signatureShareRound3.from, src_1.SignatureShareType.USER);
|
|
947
|
+
assert.strictEqual(round3.signatureShareRound3.to, src_1.SignatureShareType.BITGO);
|
|
948
|
+
const parsedShare = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound3Input, JSON.parse(round3.signatureShareRound3.share), 'EddsaMPCv2SignatureShareRound3Input');
|
|
949
|
+
assert.strictEqual(parsedShare.type, 'round3Input');
|
|
950
|
+
assert.ok(parsedShare.data.msg3.message, 'msg3.message should be set');
|
|
951
|
+
assert.ok(parsedShare.data.msg3.signature, 'msg3.signature should be set');
|
|
952
|
+
});
|
|
953
|
+
it('should use v2 decryption when encryptedRound2Session is a v2 envelope', async () => {
|
|
954
|
+
const encrypt = sinon
|
|
955
|
+
.stub()
|
|
956
|
+
.callsFake((input, adata) => Promise.resolve(JSON.stringify({ v: 2, input, adata })));
|
|
957
|
+
const destroy = sinon.stub();
|
|
958
|
+
const createEncryptionSession = sinon.stub().resolves({ encrypt, destroy });
|
|
959
|
+
mockBitgo.createEncryptionSession = createEncryptionSession;
|
|
960
|
+
const decrypt = sinon.stub().callsFake(async (params) => {
|
|
961
|
+
const envelope = JSON.parse(params.input);
|
|
962
|
+
return envelope.input;
|
|
963
|
+
});
|
|
964
|
+
mockBitgo.decrypt = decrypt;
|
|
965
|
+
const { round1, round2, txRequestRound2 } = await createRound2Flow(baseTxRequest, JSON.stringify({ v: 2 }));
|
|
966
|
+
const round3 = await eddsaMPCv2Utils.createOfflineRound3Share({
|
|
967
|
+
txRequest: txRequestRound2,
|
|
968
|
+
walletPassphrase,
|
|
969
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
970
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
971
|
+
encryptedRound2Session: round2.encryptedRound2Session,
|
|
972
|
+
});
|
|
973
|
+
assert.strictEqual(mockBitgo.decrypt.callCount, 4);
|
|
974
|
+
assert.strictEqual(round3.signatureShareRound3.from, src_1.SignatureShareType.USER);
|
|
975
|
+
});
|
|
976
|
+
it('should reject tampered encryptedRound2Session adata', async () => {
|
|
977
|
+
const otherTxRequest = {
|
|
978
|
+
...baseTxRequest,
|
|
979
|
+
transactions: [
|
|
980
|
+
{
|
|
981
|
+
unsignedTx: {
|
|
982
|
+
signableHex: 'cafebabe',
|
|
983
|
+
derivationPath: 'm/1/2',
|
|
984
|
+
serializedTxHex: 'cafebabe',
|
|
985
|
+
},
|
|
986
|
+
signatureShares: [],
|
|
987
|
+
},
|
|
988
|
+
],
|
|
989
|
+
};
|
|
990
|
+
const otherFlow = await createRound2Flow(otherTxRequest);
|
|
991
|
+
const { round1, txRequestRound2 } = await createRound2Flow(baseTxRequest);
|
|
992
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound3Share({
|
|
993
|
+
txRequest: txRequestRound2,
|
|
994
|
+
walletPassphrase,
|
|
995
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
996
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
997
|
+
encryptedRound2Session: otherFlow.round2.encryptedRound2Session,
|
|
998
|
+
}), /Adata does not match cyphertext adata/);
|
|
999
|
+
});
|
|
1000
|
+
it('should reject tampered encryptedUserGpgPrvKey adata', async () => {
|
|
1001
|
+
const otherTxRequest = {
|
|
1002
|
+
...baseTxRequest,
|
|
1003
|
+
transactions: [
|
|
1004
|
+
{
|
|
1005
|
+
unsignedTx: {
|
|
1006
|
+
signableHex: 'cafebabe',
|
|
1007
|
+
derivationPath: 'm/1/2',
|
|
1008
|
+
serializedTxHex: 'cafebabe',
|
|
1009
|
+
},
|
|
1010
|
+
signatureShares: [],
|
|
1011
|
+
},
|
|
1012
|
+
],
|
|
1013
|
+
};
|
|
1014
|
+
const otherFlow = await createRound2Flow(otherTxRequest);
|
|
1015
|
+
const { round2, txRequestRound2 } = await createRound2Flow(baseTxRequest);
|
|
1016
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound3Share({
|
|
1017
|
+
txRequest: txRequestRound2,
|
|
1018
|
+
walletPassphrase,
|
|
1019
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
1020
|
+
encryptedUserGpgPrvKey: otherFlow.round1.encryptedUserGpgPrvKey,
|
|
1021
|
+
encryptedRound2Session: round2.encryptedRound2Session,
|
|
1022
|
+
}), /Adata does not match cyphertext adata/);
|
|
1023
|
+
});
|
|
1024
|
+
it('should reject when BitGo round-2 signature share is missing', async () => {
|
|
1025
|
+
const { round1, round2, txRequestRound1 } = await createRound2Flow(baseTxRequest);
|
|
1026
|
+
const round1Transaction = assertSingleTransaction(txRequestRound1);
|
|
1027
|
+
const txRequestNoBitgoRound2Share = {
|
|
1028
|
+
...txRequestRound1,
|
|
1029
|
+
transactions: [
|
|
1030
|
+
{
|
|
1031
|
+
...round1Transaction,
|
|
1032
|
+
signatureShares: [...round1Transaction.signatureShares, round2.signatureShareRound2],
|
|
1033
|
+
},
|
|
1034
|
+
],
|
|
1035
|
+
};
|
|
1036
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound3Share({
|
|
1037
|
+
txRequest: txRequestNoBitgoRound2Share,
|
|
1038
|
+
walletPassphrase,
|
|
1039
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
1040
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
1041
|
+
encryptedRound2Session: round2.encryptedRound2Session,
|
|
1042
|
+
}), /Missing BitGo round2Output signature share/);
|
|
1043
|
+
});
|
|
1044
|
+
it('should propagate the tx-only guard when transactions are missing', async () => {
|
|
1045
|
+
const { round1, round2 } = await createRound2Flow(baseTxRequest);
|
|
1046
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound3Share({
|
|
1047
|
+
txRequest: { ...baseTxRequest, transactions: undefined },
|
|
1048
|
+
walletPassphrase,
|
|
1049
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
1050
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
1051
|
+
encryptedRound2Session: round2.encryptedRound2Session,
|
|
1052
|
+
}), /Unable to find transactions in txRequest/);
|
|
1053
|
+
});
|
|
1054
|
+
it('should reject when transactions array is empty', async () => {
|
|
1055
|
+
const { round1, round2 } = await createRound2Flow(baseTxRequest);
|
|
1056
|
+
await assert.rejects(() => eddsaMPCv2Utils.createOfflineRound3Share({
|
|
1057
|
+
txRequest: { ...baseTxRequest, transactions: [] },
|
|
1058
|
+
walletPassphrase,
|
|
1059
|
+
bitgoPublicGpgKey: bitgoGpgKeyPair.publicKey,
|
|
1060
|
+
encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey,
|
|
1061
|
+
encryptedRound2Session: round2.encryptedRound2Session,
|
|
1062
|
+
}), /Unable to find transactions in txRequest/);
|
|
1063
|
+
});
|
|
1064
|
+
});
|
|
1065
|
+
describe('getBitgoSignatureShare', () => {
|
|
1066
|
+
const round1OutputShare = {
|
|
1067
|
+
from: src_1.SignatureShareType.BITGO,
|
|
1068
|
+
to: src_1.SignatureShareType.USER,
|
|
1069
|
+
share: JSON.stringify({ type: 'round1Output', data: {} }),
|
|
1070
|
+
};
|
|
1071
|
+
const round2OutputShare = {
|
|
1072
|
+
from: src_1.SignatureShareType.BITGO,
|
|
1073
|
+
to: src_1.SignatureShareType.USER,
|
|
1074
|
+
share: JSON.stringify({ type: 'round2Output', data: {} }),
|
|
1075
|
+
};
|
|
1076
|
+
it('selects the requested BitGo round output when multiple round outputs are present', () => {
|
|
1077
|
+
const signatureShares = [round1OutputShare, round2OutputShare];
|
|
1078
|
+
assert.strictEqual((0, common_1.getBitgoSignatureShare)(signatureShares, src_1.SignatureShareType.USER, 'round2Output'), round2OutputShare);
|
|
1079
|
+
assert.strictEqual((0, common_1.getBitgoSignatureShare)(signatureShares, src_1.SignatureShareType.USER, 'round1Output'), round1OutputShare);
|
|
1080
|
+
});
|
|
1081
|
+
it('skips malformed share records while selecting the requested BitGo round output', () => {
|
|
1082
|
+
const malformedShare = {
|
|
1083
|
+
from: src_1.SignatureShareType.BITGO,
|
|
1084
|
+
to: src_1.SignatureShareType.USER,
|
|
1085
|
+
share: 'not-json',
|
|
1086
|
+
};
|
|
1087
|
+
assert.strictEqual((0, common_1.getBitgoSignatureShare)([malformedShare, round2OutputShare], src_1.SignatureShareType.USER, 'round2Output'), round2OutputShare);
|
|
1088
|
+
});
|
|
1089
|
+
});
|
|
1090
|
+
function assertSingleTransaction(txRequest) {
|
|
1091
|
+
assert.ok(txRequest.transactions, 'txRequest must include transactions');
|
|
1092
|
+
assert.strictEqual(txRequest.transactions.length, 1, 'txRequest must have exactly one transaction');
|
|
1093
|
+
return txRequest.transactions[0];
|
|
1094
|
+
}
|
|
1095
|
+
function cloneTxRequestWithEmptySignatureShares(txRequest) {
|
|
1096
|
+
const transaction = assertSingleTransaction(txRequest);
|
|
1097
|
+
return {
|
|
1098
|
+
...txRequest,
|
|
1099
|
+
transactions: [{ ...transaction, signatureShares: [] }],
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
async function signBitgoEddsaRound1(bitgoDsg, txRequest, userRound1Share, userGpgPubKeyArmored, bitgoGpgPrivKey) {
|
|
1103
|
+
const transaction = assertSingleTransaction(txRequest);
|
|
1104
|
+
transaction.signatureShares.push(userRound1Share);
|
|
1105
|
+
const bitgoMsg1 = bitgoDsg.getFirstMessage();
|
|
1106
|
+
const parsedUserShare = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound1Input, JSON.parse(userRound1Share.share), 'EddsaMPCv2SignatureShareRound1Input');
|
|
1107
|
+
const userGpgKey = await pgp.readKey({ armoredKey: userGpgPubKeyArmored });
|
|
1108
|
+
const userRawMsg1Bytes = await sdk_lib_mpc_1.MPSComms.verifyMpsMessage(parsedUserShare.data.msg1, userGpgKey);
|
|
1109
|
+
const userMsg1 = {
|
|
1110
|
+
from: typesMPCv2_1.MPCv2PartiesEnum.USER,
|
|
1111
|
+
payload: new Uint8Array(userRawMsg1Bytes),
|
|
1112
|
+
};
|
|
1113
|
+
const [bitgoMsg2] = bitgoDsg.handleIncomingMessages([bitgoMsg1, userMsg1]);
|
|
1114
|
+
assert.ok(bitgoMsg2, 'BitGo DSG produced no round-2 output');
|
|
1115
|
+
bitgoDsg.round2Message = bitgoMsg2;
|
|
1116
|
+
const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoGpgPrivKey);
|
|
1117
|
+
const round1Output = {
|
|
1118
|
+
type: 'round1Output',
|
|
1119
|
+
data: { msg1: bitgoSignedMsg1 },
|
|
1120
|
+
};
|
|
1121
|
+
transaction.signatureShares.push({
|
|
1122
|
+
from: src_1.SignatureShareType.BITGO,
|
|
1123
|
+
to: src_1.SignatureShareType.USER,
|
|
1124
|
+
share: JSON.stringify(round1Output),
|
|
1125
|
+
});
|
|
1126
|
+
return txRequest;
|
|
1127
|
+
}
|
|
1128
|
+
async function signBitgoEddsaRound2(bitgoDsg, txRequest, userRound2Share, userGpgPubKeyArmored, bitgoGpgPrivKey) {
|
|
1129
|
+
const transaction = assertSingleTransaction(txRequest);
|
|
1130
|
+
transaction.signatureShares.push(userRound2Share);
|
|
1131
|
+
const userGpgKey = await pgp.readKey({ armoredKey: userGpgPubKeyArmored });
|
|
1132
|
+
const bitgoMsg2 = bitgoDsg.round2Message;
|
|
1133
|
+
assert.ok(bitgoMsg2, 'BitGo DSG is missing the cached round-2 output');
|
|
1134
|
+
const parsedUserRound2Share = (0, codecs_1.decodeWithCodec)(public_types_1.EddsaMPCv2SignatureShareRound2Input, JSON.parse(userRound2Share.share), 'EddsaMPCv2SignatureShareRound2Input');
|
|
1135
|
+
const userRawMsg2Bytes = await sdk_lib_mpc_1.MPSComms.verifyMpsMessage(parsedUserRound2Share.data.msg2, userGpgKey);
|
|
1136
|
+
const userMsg2 = {
|
|
1137
|
+
from: typesMPCv2_1.MPCv2PartiesEnum.USER,
|
|
1138
|
+
payload: new Uint8Array(userRawMsg2Bytes),
|
|
1139
|
+
};
|
|
1140
|
+
const bitgoSignedMsg2 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg2.payload), bitgoGpgPrivKey);
|
|
1141
|
+
const round2Output = {
|
|
1142
|
+
type: 'round2Output',
|
|
1143
|
+
data: { msg2: bitgoSignedMsg2 },
|
|
1144
|
+
};
|
|
1145
|
+
transaction.signatureShares.push({
|
|
1146
|
+
from: src_1.SignatureShareType.BITGO,
|
|
1147
|
+
to: src_1.SignatureShareType.USER,
|
|
1148
|
+
share: JSON.stringify(round2Output),
|
|
1149
|
+
});
|
|
1150
|
+
bitgoDsg.handleIncomingMessages([bitgoMsg2, userMsg2]);
|
|
1151
|
+
return txRequest;
|
|
1152
|
+
}
|
|
1153
|
+
describe('EddsaMPCv2Utils.signEddsaMPCv2TssUsingExternalSigner', () => {
|
|
1154
|
+
let sandbox;
|
|
1155
|
+
let eddsaMPCv2Utils;
|
|
1156
|
+
let mockBitgo;
|
|
1157
|
+
let bitgoGpgKeyPair;
|
|
1158
|
+
let bitgoGpgPubKey;
|
|
1159
|
+
const walletId = 'abc123wallet';
|
|
1160
|
+
const txRequestId = 'txreq-001';
|
|
1161
|
+
const enterpriseId = 'ent-001';
|
|
1162
|
+
const mockTxRequest = {
|
|
1163
|
+
txRequestId,
|
|
1164
|
+
walletId,
|
|
1165
|
+
enterpriseId,
|
|
1166
|
+
apiVersion: 'full',
|
|
1167
|
+
transactions: [
|
|
1168
|
+
{
|
|
1169
|
+
unsignedTx: {
|
|
1170
|
+
signableHex: 'deadbeef',
|
|
1171
|
+
derivationPath: 'm/0',
|
|
1172
|
+
serializedTxHex: 'deadbeef',
|
|
1173
|
+
},
|
|
1174
|
+
signatureShares: [
|
|
1175
|
+
{
|
|
1176
|
+
from: src_1.SignatureShareType.BITGO,
|
|
1177
|
+
to: src_1.SignatureShareType.USER,
|
|
1178
|
+
share: JSON.stringify({ type: 'round1Output', data: {} }),
|
|
1179
|
+
},
|
|
1180
|
+
],
|
|
1181
|
+
},
|
|
1182
|
+
],
|
|
1183
|
+
intent: { intentType: 'payment' },
|
|
1184
|
+
unsignedTxs: [],
|
|
1185
|
+
};
|
|
1186
|
+
const mockTxRequestTransaction = assertSingleTransaction(mockTxRequest);
|
|
1187
|
+
const mockTxRequestRound2 = {
|
|
1188
|
+
...mockTxRequest,
|
|
1189
|
+
transactions: [
|
|
1190
|
+
{
|
|
1191
|
+
...mockTxRequestTransaction,
|
|
1192
|
+
signatureShares: [
|
|
1193
|
+
{
|
|
1194
|
+
from: src_1.SignatureShareType.BITGO,
|
|
1195
|
+
to: src_1.SignatureShareType.USER,
|
|
1196
|
+
share: JSON.stringify({ type: 'round2Output', data: {} }),
|
|
1197
|
+
},
|
|
1198
|
+
],
|
|
1199
|
+
},
|
|
1200
|
+
],
|
|
1201
|
+
};
|
|
1202
|
+
const dummyShare = {
|
|
1203
|
+
from: src_1.SignatureShareType.USER,
|
|
1204
|
+
to: src_1.SignatureShareType.BITGO,
|
|
1205
|
+
share: JSON.stringify({ type: 'round1Input', data: {} }),
|
|
1206
|
+
};
|
|
1207
|
+
// Returns a chain compatible with: bitgo.post(url).send(body).result()
|
|
1208
|
+
const makePostChain = (response) => ({ send: () => ({ result: sinon.stub().resolves(response) }) });
|
|
1209
|
+
// Returns a chain compatible with: bitgo.get(url).query(params).retry(n).result()
|
|
1210
|
+
const makeGetChain = (txRequests) => ({
|
|
1211
|
+
query: () => ({
|
|
1212
|
+
retry: () => ({ result: sinon.stub().resolves({ txRequests }) }),
|
|
1213
|
+
}),
|
|
1214
|
+
});
|
|
1215
|
+
before(async () => {
|
|
1216
|
+
bitgoGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
1217
|
+
bitgoGpgPubKey = await pgp.readKey({ armoredKey: bitgoGpgKeyPair.publicKey });
|
|
1218
|
+
});
|
|
1219
|
+
beforeEach(async () => {
|
|
1220
|
+
sandbox = sinon.createSandbox();
|
|
1221
|
+
// Full mock of the BitGo HTTP client (consistent with other sdk-core tests such as
|
|
1222
|
+
// tokenApproval.ts and walletsEvmKeyring.ts). Module-level stubs on tssCommon functions
|
|
1223
|
+
// do not work under tsx 4.x (ESM live bindings), so we mock at the bitgo object level.
|
|
1224
|
+
mockBitgo = {
|
|
1225
|
+
getEnv: sinon.stub().returns('test'),
|
|
1226
|
+
setRequestTracer: sinon.stub(),
|
|
1227
|
+
url: sinon.stub().callsFake((path) => `https://test.bitgo.com${path}`),
|
|
1228
|
+
post: sinon.stub(),
|
|
1229
|
+
get: sinon.stub(),
|
|
1230
|
+
};
|
|
1231
|
+
const mockCoin = {
|
|
1232
|
+
getMPCAlgorithm: sinon.stub().returns('eddsa'),
|
|
1233
|
+
};
|
|
1234
|
+
const mockWallet = {
|
|
1235
|
+
id: sinon.stub().returns(walletId),
|
|
1236
|
+
keyIds: sinon.stub().returns(['userKeyId', 'backupKeyId', 'bitgoKeyId']),
|
|
1237
|
+
multisigTypeVersion: sinon.stub().returns('MPCv2'),
|
|
1238
|
+
};
|
|
1239
|
+
eddsaMPCv2Utils = new src_1.EddsaMPCv2Utils(mockBitgo, mockCoin, mockWallet);
|
|
1240
|
+
sandbox.stub(eddsaMPCv2Utils, 'pickBitgoPubGpgKeyForSigning').resolves(bitgoGpgPubKey);
|
|
1241
|
+
});
|
|
1242
|
+
afterEach(() => {
|
|
1243
|
+
sandbox.restore();
|
|
1244
|
+
});
|
|
1245
|
+
it('should call all 3 generators and return the final tx request', async () => {
|
|
1246
|
+
const finalTxRequest = { ...mockTxRequest, txRequestId };
|
|
1247
|
+
// sendSignatureShareV2 is called 3 times (one per round), sendTxRequest once — all use bitgo.post
|
|
1248
|
+
mockBitgo.post
|
|
1249
|
+
.onCall(0)
|
|
1250
|
+
.returns(makePostChain(mockTxRequest)) // round 1 sign
|
|
1251
|
+
.onCall(1)
|
|
1252
|
+
.returns(makePostChain(mockTxRequestRound2)) // round 2 sign
|
|
1253
|
+
.onCall(2)
|
|
1254
|
+
.returns(makePostChain(mockTxRequestRound2)) // round 3 sign
|
|
1255
|
+
.onCall(3)
|
|
1256
|
+
.returns(makePostChain(finalTxRequest)); // sendTxRequest (send)
|
|
1257
|
+
const encryptedRound1Session = 'encrypted-r1-session';
|
|
1258
|
+
const encryptedRound2Session = 'encrypted-r2-session';
|
|
1259
|
+
const encryptedUserGpgPrvKey = 'encrypted-gpg-key';
|
|
1260
|
+
const userGpgPubKey = bitgoGpgKeyPair.publicKey;
|
|
1261
|
+
const round1Share = { ...dummyShare };
|
|
1262
|
+
const round2Share = { ...dummyShare, share: JSON.stringify({ type: 'round2Input' }) };
|
|
1263
|
+
const round3Share = { ...dummyShare, share: JSON.stringify({ type: 'round3Input' }) };
|
|
1264
|
+
const round1Generator = sinon
|
|
1265
|
+
.stub()
|
|
1266
|
+
.resolves({ signatureShareRound1: round1Share, userGpgPubKey, encryptedRound1Session, encryptedUserGpgPrvKey });
|
|
1267
|
+
const round2Generator = sinon.stub().resolves({ signatureShareRound2: round2Share, encryptedRound2Session });
|
|
1268
|
+
const round3Generator = sinon.stub().resolves({ signatureShareRound3: round3Share });
|
|
1269
|
+
const result = await eddsaMPCv2Utils.signEddsaMPCv2TssUsingExternalSigner({ txRequest: mockTxRequest, reqId: new src_1.RequestTracer() }, round1Generator, round2Generator, round3Generator);
|
|
1270
|
+
assert.deepStrictEqual(result, finalTxRequest);
|
|
1271
|
+
sinon.assert.calledOnce(round1Generator);
|
|
1272
|
+
sinon.assert.calledWith(round1Generator, { txRequest: mockTxRequest });
|
|
1273
|
+
sinon.assert.calledOnce(round2Generator);
|
|
1274
|
+
const round2Call = round2Generator.getCall(0);
|
|
1275
|
+
assert.strictEqual(round2Call.args[0].txRequest, mockTxRequest);
|
|
1276
|
+
assert.strictEqual(round2Call.args[0].encryptedRound1Session, encryptedRound1Session);
|
|
1277
|
+
assert.strictEqual(round2Call.args[0].encryptedUserGpgPrvKey, encryptedUserGpgPrvKey);
|
|
1278
|
+
assert.strictEqual(round2Call.args[0].bitgoPublicGpgKey, bitgoGpgPubKey.armor());
|
|
1279
|
+
sinon.assert.calledOnce(round3Generator);
|
|
1280
|
+
const round3Call = round3Generator.getCall(0);
|
|
1281
|
+
assert.strictEqual(round3Call.args[0].txRequest, mockTxRequestRound2);
|
|
1282
|
+
assert.strictEqual(round3Call.args[0].encryptedRound2Session, encryptedRound2Session);
|
|
1283
|
+
assert.strictEqual(round3Call.args[0].encryptedUserGpgPrvKey, encryptedUserGpgPrvKey);
|
|
1284
|
+
assert.strictEqual(round3Call.args[0].bitgoPublicGpgKey, bitgoGpgPubKey.armor());
|
|
1285
|
+
// 3 sendSignatureShareV2 calls + 1 sendTxRequest = 4 POST calls total
|
|
1286
|
+
assert.strictEqual(mockBitgo.post.callCount, 4);
|
|
1287
|
+
});
|
|
1288
|
+
it('should resolve txRequest by ID string using getTxRequest', async () => {
|
|
1289
|
+
// getTxRequest uses bitgo.get; sendSignatureShareV2 (×3) + sendTxRequest use bitgo.post
|
|
1290
|
+
mockBitgo.get.returns(makeGetChain([mockTxRequest]));
|
|
1291
|
+
mockBitgo.post
|
|
1292
|
+
.onCall(0)
|
|
1293
|
+
.returns(makePostChain(mockTxRequest))
|
|
1294
|
+
.onCall(1)
|
|
1295
|
+
.returns(makePostChain(mockTxRequestRound2))
|
|
1296
|
+
.onCall(2)
|
|
1297
|
+
.returns(makePostChain(mockTxRequestRound2))
|
|
1298
|
+
.onCall(3)
|
|
1299
|
+
.returns(makePostChain(mockTxRequest));
|
|
1300
|
+
const round1Generator = sinon.stub().resolves({
|
|
1301
|
+
signatureShareRound1: dummyShare,
|
|
1302
|
+
userGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
1303
|
+
encryptedRound1Session: 'r1',
|
|
1304
|
+
encryptedUserGpgPrvKey: 'key',
|
|
1305
|
+
});
|
|
1306
|
+
const round2Generator = sinon.stub().resolves({ signatureShareRound2: dummyShare, encryptedRound2Session: 'r2' });
|
|
1307
|
+
const round3Generator = sinon.stub().resolves({ signatureShareRound3: dummyShare });
|
|
1308
|
+
await eddsaMPCv2Utils.signEddsaMPCv2TssUsingExternalSigner({ txRequest: txRequestId, reqId: new src_1.RequestTracer() }, round1Generator, round2Generator, round3Generator);
|
|
1309
|
+
sinon.assert.calledOnce(mockBitgo.get);
|
|
1310
|
+
sinon.assert.calledWith(round1Generator, { txRequest: mockTxRequest });
|
|
1311
|
+
});
|
|
1312
|
+
it('should throw when round 2 txRequest is missing signatureShares', async () => {
|
|
1313
|
+
const round2NoShares = {
|
|
1314
|
+
...mockTxRequest,
|
|
1315
|
+
transactions: [{ ...mockTxRequestTransaction, signatureShares: undefined }],
|
|
1316
|
+
};
|
|
1317
|
+
mockBitgo.post
|
|
1318
|
+
.onCall(0)
|
|
1319
|
+
.returns(makePostChain(mockTxRequest))
|
|
1320
|
+
.onCall(1)
|
|
1321
|
+
.returns(makePostChain(round2NoShares));
|
|
1322
|
+
const round1Generator = sinon.stub().resolves({
|
|
1323
|
+
signatureShareRound1: dummyShare,
|
|
1324
|
+
userGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
1325
|
+
encryptedRound1Session: 'r1',
|
|
1326
|
+
encryptedUserGpgPrvKey: 'key',
|
|
1327
|
+
});
|
|
1328
|
+
const round2Generator = sinon.stub().resolves({ signatureShareRound2: dummyShare, encryptedRound2Session: 'r2' });
|
|
1329
|
+
const round3Generator = sinon.stub().resolves({ signatureShareRound3: dummyShare });
|
|
1330
|
+
await assert.rejects(() => eddsaMPCv2Utils.signEddsaMPCv2TssUsingExternalSigner({ txRequest: mockTxRequest, reqId: new src_1.RequestTracer() }, round1Generator, round2Generator, round3Generator), /Missing signature shares in round 2 txRequest/);
|
|
1331
|
+
});
|
|
1332
|
+
it('should pass armored BitGo public GPG key to round 2 and round 3 generators', async () => {
|
|
1333
|
+
mockBitgo.post
|
|
1334
|
+
.onCall(0)
|
|
1335
|
+
.returns(makePostChain(mockTxRequest))
|
|
1336
|
+
.onCall(1)
|
|
1337
|
+
.returns(makePostChain(mockTxRequestRound2))
|
|
1338
|
+
.onCall(2)
|
|
1339
|
+
.returns(makePostChain(mockTxRequestRound2))
|
|
1340
|
+
.onCall(3)
|
|
1341
|
+
.returns(makePostChain(mockTxRequest));
|
|
1342
|
+
const round1Generator = sinon.stub().resolves({
|
|
1343
|
+
signatureShareRound1: dummyShare,
|
|
1344
|
+
userGpgPubKey: bitgoGpgKeyPair.publicKey,
|
|
1345
|
+
encryptedRound1Session: 'r1',
|
|
1346
|
+
encryptedUserGpgPrvKey: 'key',
|
|
1347
|
+
});
|
|
1348
|
+
const round2Generator = sinon.stub().resolves({ signatureShareRound2: dummyShare, encryptedRound2Session: 'r2' });
|
|
1349
|
+
const round3Generator = sinon.stub().resolves({ signatureShareRound3: dummyShare });
|
|
1350
|
+
await eddsaMPCv2Utils.signEddsaMPCv2TssUsingExternalSigner({ txRequest: mockTxRequest, reqId: new src_1.RequestTracer() }, round1Generator, round2Generator, round3Generator);
|
|
1351
|
+
const armoredKey = bitgoGpgPubKey.armor();
|
|
1352
|
+
assert.strictEqual(round2Generator.getCall(0).args[0].bitgoPublicGpgKey, armoredKey, 'round 2 should receive armored BitGo GPG key');
|
|
1353
|
+
assert.strictEqual(round3Generator.getCall(0).args[0].bitgoPublicGpgKey, armoredKey, 'round 3 should receive armored BitGo GPG key');
|
|
1354
|
+
});
|
|
1355
|
+
});
|
|
1356
|
+
function bytesToWord(bytes) {
|
|
1357
|
+
if (!(bytes instanceof Uint8Array) || bytes.length !== 4) {
|
|
1358
|
+
throw new Error('bytes must be a Uint8Array with length 4');
|
|
1359
|
+
}
|
|
1360
|
+
return bytes.reduce((num, byte) => num * 0x100 + byte, 0);
|
|
1361
|
+
}
|
|
1362
|
+
describe('EDDSAUtils.isEddsaMpcV1SigningMaterial', () => {
|
|
1363
|
+
const PASSPHRASE = 'test-passphrase';
|
|
1364
|
+
const MPCv1_MATERIAL_BACKUP = {
|
|
1365
|
+
uShare: { i: 1, t: 2, n: 3, y: 'aabbcc', seed: 'deadbeef01234567', chaincode: '00' },
|
|
1366
|
+
bitgoYShare: { i: 3, j: 1, y: 'aabbcc', u: 'bitgo-u-value', chaincode: '00' },
|
|
1367
|
+
backupYShare: { i: 2, j: 1, y: 'aabbcc', u: 'backup-u-value', chaincode: '00' },
|
|
1368
|
+
};
|
|
1369
|
+
const MPCv1_MATERIAL_USER = {
|
|
1370
|
+
uShare: { i: 2, t: 2, n: 3, y: 'aabbcc', seed: 'deadbeef01234567', chaincode: '00' },
|
|
1371
|
+
bitgoYShare: { i: 3, j: 2, y: 'aabbcc', u: 'bitgo-u-value', chaincode: '00' },
|
|
1372
|
+
userYShare: { i: 1, j: 2, y: 'aabbcc', u: 'user-u-value', chaincode: '00' },
|
|
1373
|
+
};
|
|
1374
|
+
const MPCv2_CBOR_BYTES = Buffer.from([0xd9, 0x01, 0x04, 0xa3, 0x61, 0x78, 0x18, 0x00]).toString('base64');
|
|
1375
|
+
let mockBitgo;
|
|
1376
|
+
beforeEach(() => {
|
|
1377
|
+
// sdk-core has no devDependency on sdk-api/argon2, so v2 envelopes are simulated here.
|
|
1378
|
+
// Real bitgo.decrypt routes v2 to Argon2id; the stub returns MPCv2 CBOR plaintext instead.
|
|
1379
|
+
mockBitgo = {
|
|
1380
|
+
decrypt: sinon.stub().callsFake(async (params) => {
|
|
1381
|
+
if ((0, baseTypes_1.isV2Envelope)(params.input)) {
|
|
1382
|
+
return MPCv2_CBOR_BYTES;
|
|
1383
|
+
}
|
|
1384
|
+
return sjcl.decrypt(params.password, params.input);
|
|
1385
|
+
}),
|
|
1386
|
+
};
|
|
1387
|
+
});
|
|
1388
|
+
it('returns true for MPCv1 SJCL-encrypted keycard with backupYShare + correct passphrase', async () => {
|
|
1389
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, JSON.stringify(MPCv1_MATERIAL_BACKUP));
|
|
1390
|
+
assert.strictEqual(await src_1.EDDSAUtils.isEddsaMpcV1SigningMaterial(encrypted, PASSPHRASE), true);
|
|
1391
|
+
});
|
|
1392
|
+
it('returns true for MPCv1 SJCL-encrypted keycard with userYShare + correct passphrase', async () => {
|
|
1393
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, JSON.stringify(MPCv1_MATERIAL_USER));
|
|
1394
|
+
assert.strictEqual(await src_1.EDDSAUtils.isEddsaMpcV1SigningMaterial(encrypted, PASSPHRASE), true);
|
|
1395
|
+
});
|
|
1396
|
+
it('returns false for MPCv2 CBOR content wrapped in SJCL envelope + correct passphrase', async () => {
|
|
1397
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, MPCv2_CBOR_BYTES);
|
|
1398
|
+
assert.strictEqual(await src_1.EDDSAUtils.isEddsaMpcV1SigningMaterial(encrypted, PASSPHRASE), false);
|
|
1399
|
+
});
|
|
1400
|
+
it('returns false for MPCv2 Argon2id envelope (v2) + correct passphrase (forward-compat)', async () => {
|
|
1401
|
+
const fakeV2Envelope = JSON.stringify({ v: 2, m: 65536, t: 3, p: 4, salt: 'AAAA', iv: 'AAAA', ct: 'AAAA' });
|
|
1402
|
+
assert.strictEqual(await src_1.EDDSAUtils.isEddsaMpcV1SigningMaterial(fakeV2Envelope, PASSPHRASE, mockBitgo), false);
|
|
1403
|
+
});
|
|
1404
|
+
it('throws on wrong passphrase', async () => {
|
|
1405
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, JSON.stringify(MPCv1_MATERIAL_BACKUP));
|
|
1406
|
+
await assert.rejects(src_1.EDDSAUtils.isEddsaMpcV1SigningMaterial(encrypted, 'wrong-passphrase'), /ccm: tag doesn't match/);
|
|
1407
|
+
});
|
|
1408
|
+
it('returns false when neither backupYShare.u nor userYShare.u is present', async () => {
|
|
1409
|
+
const partial = { uShare: { seed: 'abc' }, bitgoYShare: { u: 'xyz' } };
|
|
1410
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, JSON.stringify(partial));
|
|
1411
|
+
assert.strictEqual(await src_1.EDDSAUtils.isEddsaMpcV1SigningMaterial(encrypted, PASSPHRASE), false);
|
|
1412
|
+
});
|
|
1413
|
+
});
|
|
1414
|
+
describe('signRecoveryEddsaMPCv2', () => {
|
|
1415
|
+
const derivationPath = 'm/0/0';
|
|
1416
|
+
it('should return a 64-byte signature that verifies against the derived public key', async () => {
|
|
1417
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
1418
|
+
const message = Buffer.from('deadbeef', 'hex');
|
|
1419
|
+
const commonKeyChain = userDkg.getCommonKeychain();
|
|
1420
|
+
const signature = await src_1.EDDSAUtils.signRecoveryEddsaMPCv2(message, derivationPath, userDkg.getKeyShare(), backupDkg.getKeyShare(), commonKeyChain);
|
|
1421
|
+
assert.strictEqual(signature.length, 64);
|
|
1422
|
+
const mpc = await (0, eddsa_1.getInitializedMpcInstance)();
|
|
1423
|
+
const derivedKeychain = mpc.deriveUnhardened(commonKeyChain, derivationPath);
|
|
1424
|
+
const publicKeyBytes = Buffer.from(derivedKeychain.slice(0, 64), 'hex');
|
|
1425
|
+
const ok = ed25519_1.ed25519.verify(new Uint8Array(signature), new Uint8Array(message), new Uint8Array(publicKeyBytes));
|
|
1426
|
+
assert.strictEqual(ok, true);
|
|
1427
|
+
});
|
|
1428
|
+
it('should return false when verifying the signature against a different message', async () => {
|
|
1429
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
1430
|
+
const message = Buffer.from('deadbeef', 'hex');
|
|
1431
|
+
const commonKeyChain = userDkg.getCommonKeychain();
|
|
1432
|
+
const signature = await src_1.EDDSAUtils.signRecoveryEddsaMPCv2(message, derivationPath, userDkg.getKeyShare(), backupDkg.getKeyShare(), commonKeyChain);
|
|
1433
|
+
const differentMessage = Buffer.from('cafebabe', 'hex');
|
|
1434
|
+
const mpc = await (0, eddsa_1.getInitializedMpcInstance)();
|
|
1435
|
+
const derivedKeychain = mpc.deriveUnhardened(commonKeyChain, derivationPath);
|
|
1436
|
+
const publicKeyBytes = Buffer.from(derivedKeychain.slice(0, 64), 'hex');
|
|
1437
|
+
const ok = ed25519_1.ed25519.verify(new Uint8Array(signature), new Uint8Array(differentMessage), new Uint8Array(publicKeyBytes));
|
|
1438
|
+
assert.strictEqual(ok, false);
|
|
1439
|
+
});
|
|
1440
|
+
it('should throw when a wrong commonKeyChain is provided (verification mismatch)', async () => {
|
|
1441
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
1442
|
+
const [wrongDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
1443
|
+
const message = Buffer.from('deadbeef', 'hex');
|
|
1444
|
+
await assert.rejects(() => src_1.EDDSAUtils.signRecoveryEddsaMPCv2(message, derivationPath, userDkg.getKeyShare(), backupDkg.getKeyShare(), wrongDkg.getCommonKeychain() // key chain from a different wallet
|
|
1445
|
+
), /EdDSA MPCv2 recovery signature verification failed/);
|
|
1446
|
+
});
|
|
1447
|
+
});
|
|
1448
|
+
describe('getEddsaSigningMaterial', () => {
|
|
1449
|
+
const PASSPHRASE = 'test-passphrase';
|
|
1450
|
+
const MPCv1_MATERIAL = {
|
|
1451
|
+
uShare: { i: 1, t: 2, n: 3, y: 'aabbcc', seed: 'deadbeef01234567', chaincode: '00' },
|
|
1452
|
+
bitgoYShare: { i: 3, j: 1, y: 'aabbcc', u: 'bitgo-u-value', chaincode: '00' },
|
|
1453
|
+
backupYShare: { i: 2, j: 1, y: 'aabbcc', u: 'backup-u-value', chaincode: '00' },
|
|
1454
|
+
};
|
|
1455
|
+
it('returns { version: v1, userPrv } for MPCv1 JSON keycard', async () => {
|
|
1456
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, JSON.stringify(MPCv1_MATERIAL));
|
|
1457
|
+
const decryptStub = sinon.stub().resolves(JSON.stringify(MPCv1_MATERIAL));
|
|
1458
|
+
const mockBitgo = { decrypt: decryptStub };
|
|
1459
|
+
const result = await (0, src_1.getEddsaSigningMaterial)(encrypted, PASSPHRASE, mockBitgo);
|
|
1460
|
+
assert.strictEqual(result.version, 'v1');
|
|
1461
|
+
assert.strictEqual(result.userPrv, JSON.stringify(MPCv1_MATERIAL));
|
|
1462
|
+
sinon.assert.calledOnce(decryptStub);
|
|
1463
|
+
sinon.assert.calledWithMatch(decryptStub, { input: sinon.match.string, password: PASSPHRASE });
|
|
1464
|
+
});
|
|
1465
|
+
it('returns { version: v2, encryptedUserKey } for MPCv2 CBOR keycard', async () => {
|
|
1466
|
+
const MPCv2_CBOR_BYTES = Buffer.from([0xd9, 0x01, 0x04, 0xa3, 0x61, 0x78, 0x18, 0x00]).toString('base64');
|
|
1467
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, MPCv2_CBOR_BYTES);
|
|
1468
|
+
const normalizedKey = encrypted.replace(/\s/g, '');
|
|
1469
|
+
const result = await (0, src_1.getEddsaSigningMaterial)(encrypted, PASSPHRASE);
|
|
1470
|
+
assert.strictEqual(result.version, 'v2');
|
|
1471
|
+
assert.ok('encryptedUserKey' in result);
|
|
1472
|
+
assert.strictEqual(result.encryptedUserKey, normalizedKey);
|
|
1473
|
+
});
|
|
1474
|
+
it('throws with context message when decryption fails', async () => {
|
|
1475
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, JSON.stringify(MPCv1_MATERIAL));
|
|
1476
|
+
await assert.rejects(() => (0, src_1.getEddsaSigningMaterial)(encrypted, 'wrong-passphrase'), /Error decrypting user keychain/);
|
|
1477
|
+
});
|
|
1478
|
+
it('returns v1 via sjcl fallback when bitgo is omitted', async () => {
|
|
1479
|
+
const encrypted = sjcl.encrypt(PASSPHRASE, JSON.stringify(MPCv1_MATERIAL));
|
|
1480
|
+
const result = await (0, src_1.getEddsaSigningMaterial)(encrypted, PASSPHRASE);
|
|
1481
|
+
assert.strictEqual(result.version, 'v1');
|
|
1482
|
+
assert.strictEqual(result.userPrv, JSON.stringify(MPCv1_MATERIAL));
|
|
1483
|
+
});
|
|
1484
|
+
});
|
|
1485
|
+
describe('isEddsaSigningMaterial', () => {
|
|
1486
|
+
it('returns true for a valid v1 shape', () => {
|
|
1487
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)({ version: 'v1', userPrv: '{}' }), true);
|
|
1488
|
+
});
|
|
1489
|
+
it('returns true for a valid v2 shape', () => {
|
|
1490
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)({ version: 'v2', encryptedUserKey: 'abc123' }), true);
|
|
1491
|
+
});
|
|
1492
|
+
it('returns false for a v1 shape with a non-string userPrv', () => {
|
|
1493
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)({ version: 'v1', userPrv: 123 }), false);
|
|
1494
|
+
});
|
|
1495
|
+
it('returns false for a v2 shape with a non-string encryptedUserKey', () => {
|
|
1496
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)({ version: 'v2', encryptedUserKey: 123 }), false);
|
|
1497
|
+
});
|
|
1498
|
+
it('returns false for an unrecognized version value', () => {
|
|
1499
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)({ version: 'v3', userPrv: '{}' }), false);
|
|
1500
|
+
});
|
|
1501
|
+
it('returns false for an object missing a version field', () => {
|
|
1502
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)({ userPrv: '{}' }), false);
|
|
1503
|
+
});
|
|
1504
|
+
it('returns false for null', () => {
|
|
1505
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)(null), false);
|
|
1506
|
+
});
|
|
1507
|
+
it('returns false for undefined', () => {
|
|
1508
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)(undefined), false);
|
|
1509
|
+
});
|
|
1510
|
+
it('returns false for primitive values', () => {
|
|
1511
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)('a string'), false);
|
|
1512
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)(42), false);
|
|
1513
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)(true), false);
|
|
1514
|
+
});
|
|
1515
|
+
it('returns false for an ArrayBuffer (regression: WRW openSSLBytes collision)', () => {
|
|
1516
|
+
// WRW's generic Electron 'recover' IPC handler passes openSSLBytes as a second
|
|
1517
|
+
// positional argument to every coin's recover(), colliding with precomputedMaterial
|
|
1518
|
+
// on coins that accept it. This must be rejected rather than misread as signing material.
|
|
1519
|
+
assert.strictEqual((0, src_1.isEddsaSigningMaterial)(new ArrayBuffer(8)), false);
|
|
1520
|
+
});
|
|
1521
|
+
});
|
|
1522
|
+
describe('signEddsaMpcV2RecoveryTx', () => {
|
|
1523
|
+
const derivationPath = 'm/0/0';
|
|
1524
|
+
const walletPassphrase = 'testPass';
|
|
1525
|
+
const makeDecryptBitgo = (userKeyBase64, backupKeyBase64) => ({
|
|
1526
|
+
decrypt: sinon.stub().onFirstCall().resolves(userKeyBase64).onSecondCall().resolves(backupKeyBase64),
|
|
1527
|
+
});
|
|
1528
|
+
it('returns a 64-byte signature that verifies against the derived public key', async () => {
|
|
1529
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
1530
|
+
const message = Buffer.from('deadbeef', 'hex');
|
|
1531
|
+
const commonKeyChain = userDkg.getCommonKeychain();
|
|
1532
|
+
const mockBitgo = makeDecryptBitgo(userDkg.getReducedKeyShare().toString('base64'), backupDkg.getReducedKeyShare().toString('base64'));
|
|
1533
|
+
const result = await (0, src_1.signEddsaMpcV2RecoveryTx)({
|
|
1534
|
+
message,
|
|
1535
|
+
userKey: 'encrypted-user-key',
|
|
1536
|
+
backupKey: 'encrypted-backup-key',
|
|
1537
|
+
walletPassphrase,
|
|
1538
|
+
bitgoKey: commonKeyChain,
|
|
1539
|
+
derivationPath,
|
|
1540
|
+
bitgo: mockBitgo,
|
|
1541
|
+
});
|
|
1542
|
+
assert.strictEqual(result.length, 64);
|
|
1543
|
+
const mpc = await (0, eddsa_1.getInitializedMpcInstance)();
|
|
1544
|
+
const derivedKeychain = mpc.deriveUnhardened(commonKeyChain, derivationPath);
|
|
1545
|
+
const publicKeyBytes = Buffer.from(derivedKeychain.slice(0, 64), 'hex');
|
|
1546
|
+
const ok = ed25519_1.ed25519.verify(new Uint8Array(result), new Uint8Array(message), new Uint8Array(publicKeyBytes));
|
|
1547
|
+
assert.strictEqual(ok, true);
|
|
1548
|
+
});
|
|
1549
|
+
it('throws when commonKeyChain does not match bitgoKey', async () => {
|
|
1550
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
1551
|
+
const message = Buffer.from('deadbeef', 'hex');
|
|
1552
|
+
const mockBitgo = makeDecryptBitgo(userDkg.getReducedKeyShare().toString('base64'), backupDkg.getReducedKeyShare().toString('base64'));
|
|
1553
|
+
await assert.rejects(() => (0, src_1.signEddsaMpcV2RecoveryTx)({
|
|
1554
|
+
message,
|
|
1555
|
+
userKey: 'encrypted-user-key',
|
|
1556
|
+
backupKey: 'encrypted-backup-key',
|
|
1557
|
+
walletPassphrase,
|
|
1558
|
+
bitgoKey: 'bbbb'.repeat(32),
|
|
1559
|
+
derivationPath,
|
|
1560
|
+
bitgo: mockBitgo,
|
|
1561
|
+
}), /commonKeyChain from keycard does not match bitgoKey/);
|
|
1562
|
+
});
|
|
1563
|
+
it('passes userKey, backupKey, passphrase, and bitgo to getEddsaMpcV2RecoveryKeySharesFromReducedKey', async () => {
|
|
1564
|
+
const [userDkg, backupDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares();
|
|
1565
|
+
const message = Buffer.from('deadbeef', 'hex');
|
|
1566
|
+
const decryptStub = sinon
|
|
1567
|
+
.stub()
|
|
1568
|
+
.onFirstCall()
|
|
1569
|
+
.resolves(userDkg.getReducedKeyShare().toString('base64'))
|
|
1570
|
+
.onSecondCall()
|
|
1571
|
+
.resolves(backupDkg.getReducedKeyShare().toString('base64'));
|
|
1572
|
+
const mockBitgo = { decrypt: decryptStub };
|
|
1573
|
+
await (0, src_1.signEddsaMpcV2RecoveryTx)({
|
|
1574
|
+
message,
|
|
1575
|
+
userKey: 'u-key',
|
|
1576
|
+
backupKey: 'b-key',
|
|
1577
|
+
walletPassphrase,
|
|
1578
|
+
bitgoKey: userDkg.getCommonKeychain(),
|
|
1579
|
+
derivationPath,
|
|
1580
|
+
bitgo: mockBitgo,
|
|
1581
|
+
});
|
|
1582
|
+
sinon.assert.calledWith(decryptStub.firstCall, { input: 'u-key', password: walletPassphrase });
|
|
1583
|
+
sinon.assert.calledWith(decryptStub.secondCall, { input: 'b-key', password: walletPassphrase });
|
|
1584
|
+
});
|
|
1585
|
+
});
|
|
1586
|
+
describe('EddsaMPCv2Utils.createKeychainsWithExternalSigner', function () {
|
|
1587
|
+
let utils;
|
|
1588
|
+
let callbacks;
|
|
1589
|
+
const enterprise = 'enterprise-id';
|
|
1590
|
+
const sessionId = 'session-001';
|
|
1591
|
+
const commonKeychain = 'common-keychain-hex';
|
|
1592
|
+
const userState = { encryptedData: 'u-data', encryptedDataKey: 'u-data-key' };
|
|
1593
|
+
const backupState = { encryptedData: 'b-data', encryptedDataKey: 'b-data-key' };
|
|
1594
|
+
const userSignedMsg1 = { message: 'umsg1', signature: 'usig1' };
|
|
1595
|
+
const backupSignedMsg1 = { message: 'bmsg1', signature: 'bsig1' };
|
|
1596
|
+
const userSignedMsg2 = { message: 'umsg2', signature: 'usig2' };
|
|
1597
|
+
const backupSignedMsg2 = { message: 'bmsg2', signature: 'bsig2' };
|
|
1598
|
+
const bitgoMsg1 = { message: 'bitgo-msg1', signature: 'bitgo-sig1' };
|
|
1599
|
+
const bitgoMsg2 = { message: 'bitgo-msg2', signature: 'bitgo-sig2' };
|
|
1600
|
+
beforeEach(function () {
|
|
1601
|
+
callbacks = {
|
|
1602
|
+
initializeCallback: sinon.stub().resolves({
|
|
1603
|
+
userGpgPublicKey: 'user-gpg-pub',
|
|
1604
|
+
backupGpgPublicKey: 'backup-gpg-pub',
|
|
1605
|
+
userState,
|
|
1606
|
+
backupState,
|
|
1607
|
+
}),
|
|
1608
|
+
round1Callback: sinon.stub().resolves({
|
|
1609
|
+
userSignedMsg1,
|
|
1610
|
+
backupSignedMsg1,
|
|
1611
|
+
userState,
|
|
1612
|
+
backupState,
|
|
1613
|
+
}),
|
|
1614
|
+
round2Callback: sinon.stub().resolves({
|
|
1615
|
+
userSignedMsg2,
|
|
1616
|
+
backupSignedMsg2,
|
|
1617
|
+
userState,
|
|
1618
|
+
backupState,
|
|
1619
|
+
}),
|
|
1620
|
+
finalizeCallback: sinon.stub().resolves({ commonKeychain }),
|
|
1621
|
+
};
|
|
1622
|
+
const mockBitGo = {
|
|
1623
|
+
getEnv: sinon.stub().returns('dev'),
|
|
1624
|
+
};
|
|
1625
|
+
const mockKeychains = {
|
|
1626
|
+
add: sinon
|
|
1627
|
+
.stub()
|
|
1628
|
+
.callsFake((params) => Promise.resolve({ id: `${params.source}-key-id`, commonKeychain, isMPCv2: true })),
|
|
1629
|
+
};
|
|
1630
|
+
const mockCoin = {
|
|
1631
|
+
keychains: sinon.stub().returns(mockKeychains),
|
|
1632
|
+
};
|
|
1633
|
+
utils = new src_1.EddsaMPCv2Utils(mockBitGo, mockCoin);
|
|
1634
|
+
sinon.stub(utils, 'getBitgoGpgPubkeyBasedOnFeatureFlags').resolves({ eddsaMpcv2PublicKey: null });
|
|
1635
|
+
utils.bitgoEddsaMpcv2PublicGpgKey = { armor: () => '-----BEGIN PGP PUBLIC KEY BLOCK-----\n' };
|
|
1636
|
+
sinon.stub(utils, 'sendKeyGenerationRound1').resolves({
|
|
1637
|
+
sessionId: sessionId,
|
|
1638
|
+
bitgoMsg1,
|
|
1639
|
+
});
|
|
1640
|
+
sinon.stub(utils, 'sendKeyGenerationRound2').resolves({
|
|
1641
|
+
sessionId: sessionId,
|
|
1642
|
+
commonPublicKeychain: commonKeychain,
|
|
1643
|
+
bitgoMsg2,
|
|
1644
|
+
});
|
|
1645
|
+
sinon.stub(utils, 'addBitgoKeychain').resolves({ id: 'bitgo-key-id', commonKeychain, isMPCv2: true });
|
|
1646
|
+
});
|
|
1647
|
+
afterEach(function () {
|
|
1648
|
+
sinon.restore();
|
|
1649
|
+
});
|
|
1650
|
+
it('should invoke callbacks in order and return keychains', async function () {
|
|
1651
|
+
const keychains = await utils.createKeychainsWithExternalSigner({ enterprise, callbacks });
|
|
1652
|
+
assert.ok(keychains.userKeychain);
|
|
1653
|
+
assert.ok(keychains.backupKeychain);
|
|
1654
|
+
assert.ok(keychains.bitgoKeychain);
|
|
1655
|
+
sinon.assert.calledOnce(callbacks.initializeCallback);
|
|
1656
|
+
sinon.assert.calledOnce(callbacks.round1Callback);
|
|
1657
|
+
sinon.assert.calledOnce(callbacks.round2Callback);
|
|
1658
|
+
sinon.assert.calledOnce(callbacks.finalizeCallback);
|
|
1659
|
+
});
|
|
1660
|
+
it('should pass round1 response to round2Callback', async function () {
|
|
1661
|
+
await utils.createKeychainsWithExternalSigner({ enterprise, callbacks });
|
|
1662
|
+
const round2Args = callbacks.round2Callback.firstCall.args[0];
|
|
1663
|
+
assert.deepStrictEqual(round2Args.bitgoMsg1, bitgoMsg1);
|
|
1664
|
+
assert.deepStrictEqual(round2Args.userSignedMsg1, userSignedMsg1);
|
|
1665
|
+
assert.deepStrictEqual(round2Args.backupSignedMsg1, backupSignedMsg1);
|
|
1666
|
+
assert.deepStrictEqual(round2Args.userState, userState);
|
|
1667
|
+
assert.deepStrictEqual(round2Args.backupState, backupState);
|
|
1668
|
+
});
|
|
1669
|
+
it('should pass round2 response to finalizeCallback', async function () {
|
|
1670
|
+
await utils.createKeychainsWithExternalSigner({ enterprise, callbacks });
|
|
1671
|
+
const finalizeArgs = callbacks.finalizeCallback.firstCall.args[0];
|
|
1672
|
+
assert.deepStrictEqual(finalizeArgs.bitgoMsg2, bitgoMsg2);
|
|
1673
|
+
assert.strictEqual(finalizeArgs.bitgoCommonKeychain, commonKeychain);
|
|
1674
|
+
assert.deepStrictEqual(finalizeArgs.userState, userState);
|
|
1675
|
+
assert.deepStrictEqual(finalizeArgs.backupState, backupState);
|
|
1676
|
+
});
|
|
1677
|
+
it('should register keychains with isMPCv2: true', async function () {
|
|
1678
|
+
await utils.createKeychainsWithExternalSigner({ enterprise, callbacks });
|
|
1679
|
+
const mockKeychains = utils.baseCoin.keychains();
|
|
1680
|
+
const addCalls = mockKeychains.add.getCalls();
|
|
1681
|
+
assert.ok(addCalls.length >= 2, 'keychains.add should be called for user and backup');
|
|
1682
|
+
for (const call of addCalls) {
|
|
1683
|
+
assert.strictEqual(call.args[0].isMPCv2, true);
|
|
1684
|
+
assert.strictEqual(call.args[0].keyType, 'tss');
|
|
1685
|
+
assert.strictEqual(call.args[0].commonKeychain, commonKeychain);
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1688
|
+
it('should reject when finalizeCallback returns mismatched commonKeychain', async function () {
|
|
1689
|
+
callbacks.finalizeCallback.resolves({ commonKeychain: 'different-keychain' });
|
|
1690
|
+
await assert.rejects(() => utils.createKeychainsWithExternalSigner({ enterprise, callbacks }), /Common keychains do not match/);
|
|
1691
|
+
});
|
|
1692
|
+
it('should reject when round2 returns mismatched sessionId', async function () {
|
|
1693
|
+
utils.sendKeyGenerationRound2.resolves({
|
|
1694
|
+
sessionId: 'different-session',
|
|
1695
|
+
commonPublicKeychain: commonKeychain,
|
|
1696
|
+
bitgoMsg2,
|
|
1697
|
+
});
|
|
1698
|
+
await assert.rejects(() => utils.createKeychainsWithExternalSigner({ enterprise, callbacks }), /Round 1 and round 2 session IDs do not match/);
|
|
1699
|
+
});
|
|
1700
|
+
it('should reject when BitGo EdDSA MPCv2 GPG public key is missing', async function () {
|
|
1701
|
+
utils.bitgoEddsaMpcv2PublicGpgKey = undefined;
|
|
1702
|
+
await assert.rejects(() => utils.createKeychainsWithExternalSigner({ enterprise, callbacks }), /Failed to get BitGo EdDSA MPCv2 GPG public key/);
|
|
1703
|
+
});
|
|
1704
|
+
});
|
|
1705
|
+
describe('EddsaMPCv2Utils.getMpcV2RetrofitDataFromMpcV1Keys', () => {
|
|
1706
|
+
let utils;
|
|
1707
|
+
// Real 3-party MPCv1 EdDSA key shares: 1 = user, 2 = backup, 3 = bitgo.
|
|
1708
|
+
let userSigningMaterial;
|
|
1709
|
+
let backupSigningMaterial;
|
|
1710
|
+
let expectedUserPShare;
|
|
1711
|
+
let expectedBackupPShare;
|
|
1712
|
+
before(async () => {
|
|
1713
|
+
const MPC = await (0, eddsa_1.getInitializedMpcInstance)();
|
|
1714
|
+
const user = MPC.keyShare(1, 2, 3);
|
|
1715
|
+
const backup = MPC.keyShare(2, 2, 3);
|
|
1716
|
+
const bitgo = MPC.keyShare(3, 2, 3);
|
|
1717
|
+
expectedUserPShare = MPC.keyCombine(user.uShare, [backup.yShares[1], bitgo.yShares[1]]).pShare;
|
|
1718
|
+
expectedBackupPShare = MPC.keyCombine(backup.uShare, [user.yShares[2], bitgo.yShares[2]]).pShare;
|
|
1719
|
+
userSigningMaterial = {
|
|
1720
|
+
uShare: user.uShare,
|
|
1721
|
+
bitgoYShare: bitgo.yShares[1],
|
|
1722
|
+
backupYShare: backup.yShares[1],
|
|
1723
|
+
};
|
|
1724
|
+
backupSigningMaterial = {
|
|
1725
|
+
uShare: backup.uShare,
|
|
1726
|
+
bitgoYShare: bitgo.yShares[2],
|
|
1727
|
+
userYShare: user.yShares[2],
|
|
1728
|
+
};
|
|
1729
|
+
});
|
|
1730
|
+
beforeEach(() => {
|
|
1731
|
+
const mockBitGo = {};
|
|
1732
|
+
const mockCoin = {};
|
|
1733
|
+
utils = new src_1.EddsaMPCv2Utils(mockBitGo, mockCoin);
|
|
1734
|
+
});
|
|
1735
|
+
it('derives matching expectedPk and chainCode for user and backup from real MPCv1 key combine', async () => {
|
|
1736
|
+
const { userRetrofitData, backupRetrofitData } = await utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1737
|
+
mpcv1UserKeyShare: JSON.stringify(userSigningMaterial),
|
|
1738
|
+
mpcv1BackupKeyShare: JSON.stringify(backupSigningMaterial),
|
|
1739
|
+
});
|
|
1740
|
+
assert.strictEqual(userRetrofitData.expectedPk, expectedUserPShare.y);
|
|
1741
|
+
assert.strictEqual(backupRetrofitData.expectedPk, expectedBackupPShare.y);
|
|
1742
|
+
assert.strictEqual(userRetrofitData.expectedPk, backupRetrofitData.expectedPk);
|
|
1743
|
+
assert.strictEqual(userRetrofitData.chainCode, expectedUserPShare.chaincode);
|
|
1744
|
+
assert.strictEqual(backupRetrofitData.chainCode, expectedBackupPShare.chaincode);
|
|
1745
|
+
assert.strictEqual(userRetrofitData.chainCode, backupRetrofitData.chainCode);
|
|
1746
|
+
});
|
|
1747
|
+
it('derives s_i_0 as the combined pShare.u (clamped scalar) for each party', async () => {
|
|
1748
|
+
const { userRetrofitData, backupRetrofitData } = await utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1749
|
+
mpcv1UserKeyShare: JSON.stringify(userSigningMaterial),
|
|
1750
|
+
mpcv1BackupKeyShare: JSON.stringify(backupSigningMaterial),
|
|
1751
|
+
});
|
|
1752
|
+
assert.strictEqual(userRetrofitData.s_i_0, expectedUserPShare.u);
|
|
1753
|
+
assert.strictEqual(backupRetrofitData.s_i_0, expectedBackupPShare.u);
|
|
1754
|
+
assert.notStrictEqual(userRetrofitData.s_i_0, backupRetrofitData.s_i_0);
|
|
1755
|
+
});
|
|
1756
|
+
it('throws if user key is missing uShare', async () => {
|
|
1757
|
+
const keyNoUShare = JSON.stringify({
|
|
1758
|
+
bitgoYShare: userSigningMaterial.bitgoYShare,
|
|
1759
|
+
backupYShare: userSigningMaterial.backupYShare,
|
|
1760
|
+
});
|
|
1761
|
+
await assert.rejects(() => utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1762
|
+
mpcv1UserKeyShare: keyNoUShare,
|
|
1763
|
+
mpcv1BackupKeyShare: JSON.stringify(backupSigningMaterial),
|
|
1764
|
+
}), /MPCv1 key material missing uShare/);
|
|
1765
|
+
});
|
|
1766
|
+
it('throws if user key is missing bitgoYShare', async () => {
|
|
1767
|
+
const keyNoBitgoYShare = JSON.stringify({
|
|
1768
|
+
uShare: userSigningMaterial.uShare,
|
|
1769
|
+
backupYShare: userSigningMaterial.backupYShare,
|
|
1770
|
+
});
|
|
1771
|
+
await assert.rejects(() => utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1772
|
+
mpcv1UserKeyShare: keyNoBitgoYShare,
|
|
1773
|
+
mpcv1BackupKeyShare: JSON.stringify(backupSigningMaterial),
|
|
1774
|
+
}), /MPCv1 key material missing bitgoYShare/);
|
|
1775
|
+
});
|
|
1776
|
+
it('throws if user key is missing backupYShare', async () => {
|
|
1777
|
+
const keyNoBackupYShare = JSON.stringify({
|
|
1778
|
+
uShare: userSigningMaterial.uShare,
|
|
1779
|
+
bitgoYShare: userSigningMaterial.bitgoYShare,
|
|
1780
|
+
});
|
|
1781
|
+
await assert.rejects(() => utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1782
|
+
mpcv1UserKeyShare: keyNoBackupYShare,
|
|
1783
|
+
mpcv1BackupKeyShare: JSON.stringify(backupSigningMaterial),
|
|
1784
|
+
}), /User MPCv1 key material missing backupYShare/);
|
|
1785
|
+
});
|
|
1786
|
+
it('throws if backup key is missing uShare', async () => {
|
|
1787
|
+
const keyNoUShare = JSON.stringify({
|
|
1788
|
+
bitgoYShare: backupSigningMaterial.bitgoYShare,
|
|
1789
|
+
userYShare: backupSigningMaterial.userYShare,
|
|
1790
|
+
});
|
|
1791
|
+
await assert.rejects(() => utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1792
|
+
mpcv1UserKeyShare: JSON.stringify(userSigningMaterial),
|
|
1793
|
+
mpcv1BackupKeyShare: keyNoUShare,
|
|
1794
|
+
}), /MPCv1 key material missing uShare/);
|
|
1795
|
+
});
|
|
1796
|
+
it('throws if backup key is missing bitgoYShare', async () => {
|
|
1797
|
+
const keyNoBitgoYShare = JSON.stringify({
|
|
1798
|
+
uShare: backupSigningMaterial.uShare,
|
|
1799
|
+
userYShare: backupSigningMaterial.userYShare,
|
|
1800
|
+
});
|
|
1801
|
+
await assert.rejects(() => utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1802
|
+
mpcv1UserKeyShare: JSON.stringify(userSigningMaterial),
|
|
1803
|
+
mpcv1BackupKeyShare: keyNoBitgoYShare,
|
|
1804
|
+
}), /MPCv1 key material missing bitgoYShare/);
|
|
1805
|
+
});
|
|
1806
|
+
it('throws if backup key is missing userYShare', async () => {
|
|
1807
|
+
const keyNoUserYShare = JSON.stringify({
|
|
1808
|
+
uShare: backupSigningMaterial.uShare,
|
|
1809
|
+
bitgoYShare: backupSigningMaterial.bitgoYShare,
|
|
1810
|
+
});
|
|
1811
|
+
await assert.rejects(() => utils.getMpcV2RetrofitDataFromMpcV1Keys({
|
|
1812
|
+
mpcv1UserKeyShare: JSON.stringify(userSigningMaterial),
|
|
1813
|
+
mpcv1BackupKeyShare: keyNoUserYShare,
|
|
1814
|
+
}), /Backup MPCv1 key material missing userYShare/);
|
|
1815
|
+
});
|
|
1816
|
+
});
|
|
1817
|
+
describe('EddsaMPCv2Utils.getKeyDataForRetrofit', () => {
|
|
1818
|
+
let userSigningMaterial;
|
|
1819
|
+
let backupSigningMaterial;
|
|
1820
|
+
let expectedUserPShare;
|
|
1821
|
+
let expectedBackupPShare;
|
|
1822
|
+
before(async () => {
|
|
1823
|
+
const MPC = await (0, eddsa_1.getInitializedMpcInstance)();
|
|
1824
|
+
const user = MPC.keyShare(1, 2, 3);
|
|
1825
|
+
const backup = MPC.keyShare(2, 2, 3);
|
|
1826
|
+
const bitgo = MPC.keyShare(3, 2, 3);
|
|
1827
|
+
expectedUserPShare = MPC.keyCombine(user.uShare, [backup.yShares[1], bitgo.yShares[1]]).pShare;
|
|
1828
|
+
expectedBackupPShare = MPC.keyCombine(backup.uShare, [user.yShares[2], bitgo.yShares[2]]).pShare;
|
|
1829
|
+
userSigningMaterial = {
|
|
1830
|
+
uShare: user.uShare,
|
|
1831
|
+
bitgoYShare: bitgo.yShares[1],
|
|
1832
|
+
backupYShare: backup.yShares[1],
|
|
1833
|
+
};
|
|
1834
|
+
backupSigningMaterial = {
|
|
1835
|
+
uShare: backup.uShare,
|
|
1836
|
+
bitgoYShare: bitgo.yShares[2],
|
|
1837
|
+
userYShare: user.yShares[2],
|
|
1838
|
+
};
|
|
1839
|
+
});
|
|
1840
|
+
it('derives USER retrofit data matching keyCombine pShare fields', async () => {
|
|
1841
|
+
const retrofitData = await src_1.EddsaMPCv2Utils.getKeyDataForRetrofit(JSON.stringify(userSigningMaterial), typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
1842
|
+
assert.strictEqual(retrofitData.s_i_0, expectedUserPShare.u);
|
|
1843
|
+
assert.strictEqual(retrofitData.expectedPk, expectedUserPShare.y);
|
|
1844
|
+
assert.strictEqual(retrofitData.chainCode, expectedUserPShare.chaincode);
|
|
1845
|
+
});
|
|
1846
|
+
it('derives BACKUP retrofit data matching keyCombine pShare fields', async () => {
|
|
1847
|
+
const retrofitData = await src_1.EddsaMPCv2Utils.getKeyDataForRetrofit(JSON.stringify(backupSigningMaterial), typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
1848
|
+
assert.strictEqual(retrofitData.s_i_0, expectedBackupPShare.u);
|
|
1849
|
+
assert.strictEqual(retrofitData.expectedPk, expectedBackupPShare.y);
|
|
1850
|
+
assert.strictEqual(retrofitData.chainCode, expectedBackupPShare.chaincode);
|
|
1851
|
+
});
|
|
1852
|
+
it('throws if USER material is missing backupYShare', async () => {
|
|
1853
|
+
const keyNoBackupYShare = JSON.stringify({
|
|
1854
|
+
uShare: userSigningMaterial.uShare,
|
|
1855
|
+
bitgoYShare: userSigningMaterial.bitgoYShare,
|
|
1856
|
+
});
|
|
1857
|
+
await assert.rejects(() => src_1.EddsaMPCv2Utils.getKeyDataForRetrofit(keyNoBackupYShare, typesMPCv2_1.MPCv2PartiesEnum.USER), /User MPCv1 key material missing backupYShare/);
|
|
1858
|
+
});
|
|
1859
|
+
it('throws if BACKUP material is missing userYShare', async () => {
|
|
1860
|
+
const keyNoUserYShare = JSON.stringify({
|
|
1861
|
+
uShare: backupSigningMaterial.uShare,
|
|
1862
|
+
bitgoYShare: backupSigningMaterial.bitgoYShare,
|
|
1863
|
+
});
|
|
1864
|
+
await assert.rejects(() => src_1.EddsaMPCv2Utils.getKeyDataForRetrofit(keyNoUserYShare, typesMPCv2_1.MPCv2PartiesEnum.BACKUP), /Backup MPCv1 key material missing userYShare/);
|
|
1865
|
+
});
|
|
1866
|
+
it('USER and BACKUP expectedPk and chainCode match when built from the same three keyShares', async () => {
|
|
1867
|
+
const userRetrofitData = await src_1.EddsaMPCv2Utils.getKeyDataForRetrofit(JSON.stringify(userSigningMaterial), typesMPCv2_1.MPCv2PartiesEnum.USER);
|
|
1868
|
+
const backupRetrofitData = await src_1.EddsaMPCv2Utils.getKeyDataForRetrofit(JSON.stringify(backupSigningMaterial), typesMPCv2_1.MPCv2PartiesEnum.BACKUP);
|
|
1869
|
+
assert.strictEqual(userRetrofitData.expectedPk, backupRetrofitData.expectedPk);
|
|
1870
|
+
assert.strictEqual(userRetrofitData.chainCode, backupRetrofitData.chainCode);
|
|
1871
|
+
});
|
|
1872
|
+
});
|
|
1873
|
+
describe('EddsaMPCv2Utils.getUserAndBackupSession', () => {
|
|
1874
|
+
let utils;
|
|
1875
|
+
let userSigningMaterial;
|
|
1876
|
+
let backupSigningMaterial;
|
|
1877
|
+
before(async () => {
|
|
1878
|
+
const MPC = await (0, eddsa_1.getInitializedMpcInstance)();
|
|
1879
|
+
const user = MPC.keyShare(1, 2, 3);
|
|
1880
|
+
const backup = MPC.keyShare(2, 2, 3);
|
|
1881
|
+
const bitgo = MPC.keyShare(3, 2, 3);
|
|
1882
|
+
userSigningMaterial = {
|
|
1883
|
+
uShare: user.uShare,
|
|
1884
|
+
bitgoYShare: bitgo.yShares[1],
|
|
1885
|
+
backupYShare: backup.yShares[1],
|
|
1886
|
+
};
|
|
1887
|
+
backupSigningMaterial = {
|
|
1888
|
+
uShare: backup.uShare,
|
|
1889
|
+
bitgoYShare: bitgo.yShares[2],
|
|
1890
|
+
userYShare: user.yShares[2],
|
|
1891
|
+
};
|
|
1892
|
+
});
|
|
1893
|
+
beforeEach(() => {
|
|
1894
|
+
const mockBitGo = {};
|
|
1895
|
+
const mockCoin = {};
|
|
1896
|
+
utils = new src_1.EddsaMPCv2Utils(mockBitGo, mockCoin);
|
|
1897
|
+
});
|
|
1898
|
+
afterEach(() => {
|
|
1899
|
+
sinon.restore();
|
|
1900
|
+
});
|
|
1901
|
+
it('returns plain DKG sessions when retrofit is undefined', async () => {
|
|
1902
|
+
const { userDkg, backupDkg } = await utils.getUserAndBackupSession(undefined);
|
|
1903
|
+
assert.ok(userDkg, 'user DKG should be created');
|
|
1904
|
+
assert.ok(backupDkg, 'backup DKG should be created');
|
|
1905
|
+
});
|
|
1906
|
+
it('returns retrofit-seeded DKG sessions when retrofit payload is supplied', async () => {
|
|
1907
|
+
const retrofit = {
|
|
1908
|
+
decryptedUserKey: JSON.stringify(userSigningMaterial),
|
|
1909
|
+
decryptedBackupKey: JSON.stringify(backupSigningMaterial),
|
|
1910
|
+
walletId: 'wallet-123',
|
|
1911
|
+
};
|
|
1912
|
+
const { userDkg, backupDkg } = await utils.getUserAndBackupSession(retrofit);
|
|
1913
|
+
assert.ok(userDkg, 'user DKG should be created with retrofit data');
|
|
1914
|
+
assert.ok(backupDkg, 'backup DKG should be created with retrofit data');
|
|
1915
|
+
});
|
|
1916
|
+
});
|
|
1917
|
+
describe('EddsaMPCv2Utils.createKeychains with retrofit wiring', () => {
|
|
1918
|
+
let utils;
|
|
1919
|
+
let userSigningMaterial;
|
|
1920
|
+
let backupSigningMaterial;
|
|
1921
|
+
let bitgoGpgPublicKeyArmored;
|
|
1922
|
+
const enterprise = 'enterprise-id';
|
|
1923
|
+
const sessionId = 'session-001';
|
|
1924
|
+
const walletId = 'wallet-retrofit-123';
|
|
1925
|
+
before(async () => {
|
|
1926
|
+
const MPC = await (0, eddsa_1.getInitializedMpcInstance)();
|
|
1927
|
+
const user = MPC.keyShare(1, 2, 3);
|
|
1928
|
+
const backup = MPC.keyShare(2, 2, 3);
|
|
1929
|
+
const bitgo = MPC.keyShare(3, 2, 3);
|
|
1930
|
+
userSigningMaterial = {
|
|
1931
|
+
uShare: user.uShare,
|
|
1932
|
+
bitgoYShare: bitgo.yShares[1],
|
|
1933
|
+
backupYShare: backup.yShares[1],
|
|
1934
|
+
};
|
|
1935
|
+
backupSigningMaterial = {
|
|
1936
|
+
uShare: backup.uShare,
|
|
1937
|
+
bitgoYShare: bitgo.yShares[2],
|
|
1938
|
+
userYShare: user.yShares[2],
|
|
1939
|
+
};
|
|
1940
|
+
// Generate a real Ed25519 GPG key to stand in for the BitGo GPG key
|
|
1941
|
+
const bitgoGpgKeyPair = await (0, opengpgUtils_1.generateGPGKeyPair)('ed25519');
|
|
1942
|
+
bitgoGpgPublicKeyArmored = bitgoGpgKeyPair.publicKey;
|
|
1943
|
+
});
|
|
1944
|
+
beforeEach(() => {
|
|
1945
|
+
const mockBitGo = {
|
|
1946
|
+
getEnv: sinon.stub().returns('dev'),
|
|
1947
|
+
encrypt: sinon.stub().resolves('encrypted'),
|
|
1948
|
+
};
|
|
1949
|
+
const mockKeychains = {
|
|
1950
|
+
add: sinon
|
|
1951
|
+
.stub()
|
|
1952
|
+
.callsFake((params) => Promise.resolve({ id: `${params.source}-key-id`, commonKeychain: 'a'.repeat(128), isMPCv2: true })),
|
|
1953
|
+
};
|
|
1954
|
+
const mockCoin = {
|
|
1955
|
+
keychains: sinon.stub().returns(mockKeychains),
|
|
1956
|
+
};
|
|
1957
|
+
utils = new src_1.EddsaMPCv2Utils(mockBitGo, mockCoin);
|
|
1958
|
+
sinon.stub(utils, 'getBitgoGpgPubkeyBasedOnFeatureFlags').resolves({ eddsaMpcv2PublicKey: null });
|
|
1959
|
+
// Use a real armored GPG public key so pgp.readKey() succeeds inside createKeychains
|
|
1960
|
+
utils.bitgoEddsaMpcv2PublicGpgKey = { armor: () => bitgoGpgPublicKeyArmored };
|
|
1961
|
+
sinon.stub(utils, 'addBitgoKeychain').resolves({ id: 'bitgo-key-id', commonKeychain: 'a'.repeat(128) });
|
|
1962
|
+
});
|
|
1963
|
+
afterEach(() => {
|
|
1964
|
+
sinon.restore();
|
|
1965
|
+
});
|
|
1966
|
+
it('spreads walletId into round-1 payload when retrofit is provided', async () => {
|
|
1967
|
+
const capturedPayloads = [];
|
|
1968
|
+
sinon.stub(utils, 'sendKeyGenerationRound1').callsFake(async (_enterprise, payload) => {
|
|
1969
|
+
capturedPayloads.push(payload);
|
|
1970
|
+
// Return a bad bitgoMsg1 to short-circuit the ceremony after R1 capture
|
|
1971
|
+
return { sessionId: sessionId, bitgoMsg1: { message: '', signature: '' } };
|
|
1972
|
+
});
|
|
1973
|
+
const retrofit = {
|
|
1974
|
+
decryptedUserKey: JSON.stringify(userSigningMaterial),
|
|
1975
|
+
decryptedBackupKey: JSON.stringify(backupSigningMaterial),
|
|
1976
|
+
walletId,
|
|
1977
|
+
};
|
|
1978
|
+
await assert.rejects(() => utils.createKeychains({ passphrase: 'test', enterprise, retrofit }), () => true);
|
|
1979
|
+
assert.strictEqual(capturedPayloads.length, 1, 'sendKeyGenerationRound1 should be called once');
|
|
1980
|
+
assert.strictEqual(capturedPayloads[0].walletId, walletId, 'walletId must be present in round-1 payload');
|
|
1981
|
+
});
|
|
1982
|
+
it('omits walletId from round-1 payload when retrofit is absent', async () => {
|
|
1983
|
+
const capturedPayloads = [];
|
|
1984
|
+
sinon.stub(utils, 'sendKeyGenerationRound1').callsFake(async (_enterprise, payload) => {
|
|
1985
|
+
capturedPayloads.push(payload);
|
|
1986
|
+
return { sessionId: sessionId, bitgoMsg1: { message: '', signature: '' } };
|
|
1987
|
+
});
|
|
1988
|
+
await assert.rejects(() => utils.createKeychains({ passphrase: 'test', enterprise }), () => true);
|
|
1989
|
+
assert.strictEqual(capturedPayloads.length, 1, 'sendKeyGenerationRound1 should be called once');
|
|
1990
|
+
assert.strictEqual(capturedPayloads[0].walletId, undefined, 'walletId must be absent when no retrofit');
|
|
1991
|
+
});
|
|
1992
|
+
});
|
|
1993
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRkc2FNUEN2Mi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Rlc3QvdW5pdC9iaXRnby91dGlscy90c3MvZWRkc2EvZWRkc2FNUEN2Mi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1DQUFnQztBQUNoQywrQ0FBaUM7QUFDakMsNkNBQStCO0FBQy9CLDZDQUErQjtBQUMvQixtQ0FBcUM7QUFDckMseURBQWdHO0FBQ2hHLG1EQUFnRDtBQUNoRCx1REFBeUM7QUFDekMsc0RBTzZCO0FBQzdCLCtDQWtCK0I7QUFDL0IsaUZBTzBEO0FBQzFELHVFQUF3RjtBQUN4RixtRUFBZ0Y7QUFDaEYscUVBQTJFO0FBQzNFLGlGQUFvRjtBQUNwRix1RkFBMEY7QUFDMUYsK0VBQStFO0FBRS9FLFFBQVEsQ0FBQyxnQ0FBZ0MsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNwRCxJQUFJLFlBQW9CLENBQUM7SUFDekIsSUFBSSxjQUFzQixDQUFDO0lBQzNCLElBQUksYUFBcUIsQ0FBQztJQUMxQixJQUFJLGNBQThCLENBQUM7SUFDbkMsSUFBSSxnQkFBZ0MsQ0FBQztJQUNyQyxJQUFJLGVBQStCLENBQUM7SUFDcEMsSUFBSSxjQUF1QixDQUFDO0lBRTVCLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQztJQUMvQixNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUM7SUFFN0IsTUFBTSxDQUFDLCtCQUErQixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2pELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBQSxpQ0FBa0IsRUFBQyxTQUFTLENBQUMsQ0FBQztRQUMzRCxNQUFNLGdCQUFnQixHQUFHLE1BQU0sSUFBQSxpQ0FBa0IsRUFBQyxTQUFTLENBQUMsQ0FBQztRQUM3RCxNQUFNLGVBQWUsR0FBRyxNQUFNLElBQUEsaUNBQWtCLEVBQUMsU0FBUyxDQUFDLENBQUM7UUFFNUQsY0FB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QUFtQixFQUFFLE9BQVksRUFBRSxFQUFFO1lBQ2pHLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMvQixPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQWdCLEVBQUUsU0FBUyxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFTLEVBQUUsQ0FBQztRQUMzRixDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FDbEIsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFDL0QsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUNYLENBQUM7UUFFRixNQUFNLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsK0NBQStDLENBQUMsQ0FBQztRQUNoRyxNQUFNLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsMENBQTBDLENBQUMsQ0FBQztJQUMxRyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZW5jb2RlIH0gZnJvbSAnY2Jvci14JztcbmltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0ICogYXMgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0ICogYXMgcGdwIGZyb20gJ29wZW5wZ3AnO1xuaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgRWRkc2FNUFNEa2csIEVkZHNhTVBTRHNnLCBNUFNDb21tcywgTVBTVHlwZXMsIE1QU1V0aWwgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstbGliLW1wYyc7XG5pbXBvcnQgeyBlZDI1NTE5IH0gZnJvbSAnQG5vYmxlL2N1cnZlcy9lZDI1NTE5JztcbmltcG9ydCAqIGFzIHNqY2wgZnJvbSAnQGJpdGdvLWJldGEvc2pjbCc7XG5pbXBvcnQge1xuICBFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDFJbnB1dCxcbiAgRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxT3V0cHV0LFxuICBFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJJbnB1dCxcbiAgRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQyT3V0cHV0LFxuICBFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDNJbnB1dCxcbiAgRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQzT3V0cHV0LFxufSBmcm9tICdAYml0Z28vcHVibGljLXR5cGVzJztcbmltcG9ydCB7XG4gIEJpdEdvQmFzZSxcbiAgQml0R29SZXF1ZXN0LFxuICBDdXN0b21FZGRzYU1QQ3YyU2lnbmluZ1JvdW5kMUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgQ3VzdG9tRWRkc2FNUEN2MlNpZ25pbmdSb3VuZDJHZW5lcmF0aW5nRnVuY3Rpb24sXG4gIEN1c3RvbUVkZHNhTVBDdjJTaWduaW5nUm91bmQzR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICBFRERTQVV0aWxzLFxuICBFZGRzYU1QQ3YyS2V5R2VuQ2FsbGJhY2tzLFxuICBFZGRzYU1QQ3YyVXRpbHMsXG4gIElCYXNlQ29pbixcbiAgSVdhbGxldCxcbiAgUmVxdWVzdFRyYWNlcixcbiAgU2lnbmF0dXJlU2hhcmVSZWNvcmQsXG4gIFNpZ25hdHVyZVNoYXJlVHlwZSxcbiAgVHhSZXF1ZXN0LFxuICBnZXRFZGRzYVNpZ25pbmdNYXRlcmlhbCxcbiAgaXNFZGRzYVNpZ25pbmdNYXRlcmlhbCxcbiAgc2lnbkVkZHNhTXBjVjJSZWNvdmVyeVR4LFxufSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi9zcmMnO1xuaW1wb3J0IHtcbiAgZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZE9uZSxcbiAgZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZFR3byxcbiAgZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZFRocmVlLFxuICB2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kT25lLFxuICB2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kVHdvLFxuICB2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kVGhyZWUsXG59IGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9iaXRnby90c3MvZWRkc2EvZWRkc2FNUEN2Mic7XG5pbXBvcnQgeyBnZXRJbml0aWFsaXplZE1wY0luc3RhbmNlIH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2JpdGdvL3Rzcy9lZGRzYS9lZGRzYSc7XG5pbXBvcnQgeyBnZXRCaXRnb1NpZ25hdHVyZVNoYXJlIH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2JpdGdvL3Rzcy9jb21tb24nO1xuaW1wb3J0IHsgZGVjb2RlV2l0aENvZGVjIH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2JpdGdvL3V0aWxzL2NvZGVjcyc7XG5pbXBvcnQgeyBnZW5lcmF0ZUdQR0tleVBhaXIgfSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYml0Z28vdXRpbHMvb3BlbmdwZ1V0aWxzJztcbmltcG9ydCB7IE1QQ3YyUGFydGllc0VudW0gfSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYml0Z28vdXRpbHMvdHNzL2VjZHNhL3R5cGVzTVBDdjInO1xuaW1wb3J0IHsgaXNWMkVudmVsb3BlIH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2JpdGdvL3V0aWxzL3Rzcy9iYXNlVHlwZXMnO1xuXG5kZXNjcmliZSgnRWREU0EgTVBTIERTRyBoZWxwZXIgZnVuY3Rpb25zJywgYXN5bmMgKCkgPT4ge1xuICBsZXQgdXNlcktleVNoYXJlOiBCdWZmZXI7XG4gIGxldCBiYWNrdXBLZXlTaGFyZTogQnVmZmVyO1xuICBsZXQgYml0Z29LZXlTaGFyZTogQnVmZmVyO1xuICBsZXQgdXNlckdwZ1ByaXZLZXk6IHBncC5Qcml2YXRlS2V5O1xuICBsZXQgYmFja3VwR3BnUHJpdktleTogcGdwLlByaXZhdGVLZXk7XG4gIGxldCBiaXRnb0dwZ1ByaXZLZXk6IHBncC5Qcml2YXRlS2V5O1xuICBsZXQgYml0Z29HcGdQdWJLZXk6IHBncC5LZXk7XG5cbiAgY29uc3Qgc2lnbmFibGVIZXggPSAnZGVhZGJlZWYnO1xuICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzAnO1xuXG4gIGJlZm9yZSgnZ2VuZXJhdGUgRWREU0EgREtHIGtleSBzaGFyZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdXNlckdwZ0tleVBhaXIgPSBhd2FpdCBnZW5lcmF0ZUdQR0tleVBhaXIoJ2VkMjU1MTknKTtcbiAgICBjb25zdCBiYWNrdXBHcGdLZXlQYWlyID0gYXdhaXQgZ2VuZXJhdGVHUEdLZXlQYWlyKCdlZDI1NTE5Jyk7XG4gICAgY29uc3QgYml0Z29HcGdLZXlQYWlyID0gYXdhaXQgZ2VuZXJhdGVHUEdLZXlQYWlyKCdlZDI1NTE5Jyk7XG5cbiAgICB1c2VyR3BnUHJpdktleSA9IGF3YWl0IHBncC5yZWFkUHJpdmF0ZUtleSh7IGFybW9yZWRLZXk6IHVzZXJHcGdLZXlQYWlyLnByaXZhdGVLZXkgfSk7XG4gICAgYmFja3VwR3BnUHJpdktleSA9IGF3YWl0IHBncC5yZWFkUHJpdmF0ZUtleSh7IGFybW9yZWRLZXk6IGJhY2t1cEdwZ0tleVBhaXIucHJpdmF0ZUtleSB9KTtcbiAgICBiaXRnb0dwZ1ByaXZLZXkgPSBhd2FpdCBwZ3AucmVhZFByaXZhdGVLZXkoeyBhcm1vcmVkS2V5OiBiaXRnb0dwZ0tleVBhaXIucHJpdmF0ZUtleSB9KTtcbiAgICBiaXRnb0dwZ1B1YktleSA9IGF3YWl0IHBncC5yZWFkS2V5KHsgYXJtb3JlZEtleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSB9KTtcblxuICAgIGNvbnN0IFt1c2VyRGtnLCBiYWNrdXBEa2csIGJpdGdvRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgIHVzZXJLZXlTaGFyZSA9IHVzZXJEa2cuZ2V0S2V5U2hhcmUoKTtcbiAgICBiYWNrdXBLZXlTaGFyZSA9IGJhY2t1cERrZy5nZXRLZXlTaGFyZSgpO1xuICAgIGJpdGdvS2V5U2hhcmUgPSBiaXRnb0RrZy5nZXRLZXlTaGFyZSgpO1xuICB9KTtcblxuICAvLyDilIDilIAgUm91bmQgMSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBpdCgnZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZE9uZSBzaG91bGQgYnVpbGQgYSB2YWxpZCByb3VuZC0xIHNoYXJlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG1lc3NhZ2VCdWZmZXIgPSBCdWZmZXIuZnJvbShzaWduYWJsZUhleCwgJ2hleCcpO1xuICAgIGNvbnN0IHVzZXJEc2cgPSBuZXcgRWRkc2FNUFNEc2cuRFNHKE1QQ3YyUGFydGllc0VudW0uVVNFUik7XG4gICAgYXdhaXQgdXNlckRzZy5pbml0RHNnKHVzZXJLZXlTaGFyZSwgbWVzc2FnZUJ1ZmZlciwgZGVyaXZhdGlvblBhdGgsIE1QQ3YyUGFydGllc0VudW0uQklUR08pO1xuICAgIGNvbnN0IHVzZXJNc2cxID0gdXNlckRzZy5nZXRGaXJzdE1lc3NhZ2UoKTtcblxuICAgIGNvbnN0IHNoYXJlOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IGF3YWl0IGdldFNpZ25hdHVyZVNoYXJlUm91bmRPbmUodXNlck1zZzEsIHVzZXJHcGdQcml2S2V5KTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaGFyZS5mcm9tLCBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUik7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNoYXJlLnRvLCBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08pO1xuXG4gICAgY29uc3QgcGFyc2VkID0gZGVjb2RlV2l0aENvZGVjKFxuICAgICAgRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxSW5wdXQsXG4gICAgICBKU09OLnBhcnNlKHNoYXJlLnNoYXJlKSxcbiAgICAgICdFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDFJbnB1dCdcbiAgICApO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQudHlwZSwgJ3JvdW5kMUlucHV0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5kYXRhLm1zZzEubWVzc2FnZSwgJ21zZzEubWVzc2FnZSBzaG91bGQgYmUgc2V0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5kYXRhLm1zZzEuc2lnbmF0dXJlLCAnbXNnMS5zaWduYXR1cmUgc2hvdWxkIGJlIHNldCcpO1xuICB9KTtcblxuICBpdCgnZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZE9uZSBzaG91bGQgYnVpbGQgYSB2YWxpZCBiYWNrdXAgcm91bmQtMSBzaGFyZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCBiYWNrdXBEc2cgPSBuZXcgRWRkc2FNUFNEc2cuRFNHKE1QQ3YyUGFydGllc0VudW0uQkFDS1VQKTtcbiAgICBhd2FpdCBiYWNrdXBEc2cuaW5pdERzZyhiYWNrdXBLZXlTaGFyZSwgbWVzc2FnZUJ1ZmZlciwgZGVyaXZhdGlvblBhdGgsIE1QQ3YyUGFydGllc0VudW0uQklUR08pO1xuICAgIGNvbnN0IGJhY2t1cE1zZzEgPSBiYWNrdXBEc2cuZ2V0Rmlyc3RNZXNzYWdlKCk7XG5cbiAgICBjb25zdCBzaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSBhd2FpdCBnZXRTaWduYXR1cmVTaGFyZVJvdW5kT25lKFxuICAgICAgYmFja3VwTXNnMSxcbiAgICAgIGJhY2t1cEdwZ1ByaXZLZXksXG4gICAgICBNUEN2MlBhcnRpZXNFbnVtLkJBQ0tVUFxuICAgICk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2hhcmUuZnJvbSwgU2lnbmF0dXJlU2hhcmVUeXBlLkJBQ0tVUCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNoYXJlLnRvLCBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08pO1xuXG4gICAgY29uc3QgcGFyc2VkID0gZGVjb2RlV2l0aENvZGVjKFxuICAgICAgRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxSW5wdXQsXG4gICAgICBKU09OLnBhcnNlKHNoYXJlLnNoYXJlKSxcbiAgICAgICdFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDFJbnB1dCdcbiAgICApO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQudHlwZSwgJ3JvdW5kMUlucHV0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5kYXRhLm1zZzEubWVzc2FnZSwgJ21zZzEubWVzc2FnZSBzaG91bGQgYmUgc2V0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5kYXRhLm1zZzEuc2lnbmF0dXJlLCAnbXNnMS5zaWduYXR1cmUgc2hvdWxkIGJlIHNldCcpO1xuICB9KTtcblxuICBpdCgndmVyaWZ5UGVlck1lc3NhZ2VSb3VuZE9uZSBzaG91bGQgdmVyaWZ5IGEgdmFsaWQgQml0R28gcm91bmQtMSBtZXNzYWdlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG1lc3NhZ2VCdWZmZXIgPSBCdWZmZXIuZnJvbShzaWduYWJsZUhleCwgJ2hleCcpO1xuICAgIGNvbnN0IGJpdGdvRHNnID0gbmV3IEVkZHNhTVBTRHNnLkRTRyhNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBhd2FpdCBiaXRnb0RzZy5pbml0RHNnKGJpdGdvS2V5U2hhcmUsIG1lc3NhZ2VCdWZmZXIsIGRlcml2YXRpb25QYXRoLCBNUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuICAgIGNvbnN0IGJpdGdvTXNnMSA9IGJpdGdvRHNnLmdldEZpcnN0TWVzc2FnZSgpO1xuXG4gICAgY29uc3QgYml0Z29TaWduZWRNc2cxID0gYXdhaXQgTVBTQ29tbXMuZGV0YWNoU2lnbk1wc01lc3NhZ2UoQnVmZmVyLmZyb20oYml0Z29Nc2cxLnBheWxvYWQpLCBiaXRnb0dwZ1ByaXZLZXkpO1xuICAgIGNvbnN0IHJvdW5kMU91dHB1dDogRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxT3V0cHV0ID0ge1xuICAgICAgdHlwZTogJ3JvdW5kMU91dHB1dCcsXG4gICAgICBkYXRhOiB7IG1zZzE6IGJpdGdvU2lnbmVkTXNnMSB9LFxuICAgIH07XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kT25lKHJvdW5kMU91dHB1dCwgYml0Z29HcGdQdWJLZXkpO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5mcm9tLCBNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBhc3NlcnQub2socmVzdWx0LnBheWxvYWQubGVuZ3RoID4gMCwgJ3BheWxvYWQgc2hvdWxkIGJlIG5vbi1lbXB0eScpO1xuICB9KTtcblxuICBpdCgndmVyaWZ5UGVlck1lc3NhZ2VSb3VuZE9uZSBzaG91bGQgdGhyb3cgb24gYSB0YW1wZXJlZCBtZXNzYWdlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJvdW5kMU91dHB1dDogRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxT3V0cHV0ID0ge1xuICAgICAgdHlwZTogJ3JvdW5kMU91dHB1dCcsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIG1zZzE6IHtcbiAgICAgICAgICBtZXNzYWdlOiBCdWZmZXIuZnJvbSgndGFtcGVyZWQnKS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICAgICAgc2lnbmF0dXJlOiAnLS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS1cXG5cXG5JTlZBTElEXFxuLS0tLS1FTkQgUEdQIFNJR05BVFVSRS0tLS0tXFxuJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKHZlcmlmeVBlZXJNZXNzYWdlUm91bmRPbmUocm91bmQxT3V0cHV0LCBiaXRnb0dwZ1B1YktleSksICdzaG91bGQgdGhyb3cgb24gaW52YWxpZCBzaWduYXR1cmUnKTtcbiAgfSk7XG5cbiAgLy8g4pSA4pSAIFJvdW5kIDIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgaXQoJ2dldFNpZ25hdHVyZVNoYXJlUm91bmRUd28gc2hvdWxkIGJ1aWxkIGEgdmFsaWQgcm91bmQtMiBzaGFyZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCB1c2VyRHNnID0gbmV3IEVkZHNhTVBTRHNnLkRTRyhNUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuICAgIGF3YWl0IHVzZXJEc2cuaW5pdERzZyh1c2VyS2V5U2hhcmUsIG1lc3NhZ2VCdWZmZXIsIGRlcml2YXRpb25QYXRoLCBNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBjb25zdCB1c2VyTXNnMSA9IHVzZXJEc2cuZ2V0Rmlyc3RNZXNzYWdlKCk7XG5cbiAgICBjb25zdCBiaXRnb0RzZyA9IG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5CSVRHTyk7XG4gICAgYXdhaXQgYml0Z29Ec2cuaW5pdERzZyhiaXRnb0tleVNoYXJlLCBtZXNzYWdlQnVmZmVyLCBkZXJpdmF0aW9uUGF0aCwgTVBDdjJQYXJ0aWVzRW51bS5VU0VSKTtcbiAgICBjb25zdCBiaXRnb01zZzEgPSBiaXRnb0RzZy5nZXRGaXJzdE1lc3NhZ2UoKTtcblxuICAgIGNvbnN0IGJpdGdvU2lnbmVkTXNnMSA9IGF3YWl0IE1QU0NvbW1zLmRldGFjaFNpZ25NcHNNZXNzYWdlKEJ1ZmZlci5mcm9tKGJpdGdvTXNnMS5wYXlsb2FkKSwgYml0Z29HcGdQcml2S2V5KTtcbiAgICBjb25zdCBiaXRnb0Rlc2VyaWFsaXplZE1zZzEgPSBhd2FpdCB2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kT25lKFxuICAgICAgeyB0eXBlOiAncm91bmQxT3V0cHV0JywgZGF0YTogeyBtc2cxOiBiaXRnb1NpZ25lZE1zZzEgfSB9LFxuICAgICAgYml0Z29HcGdQdWJLZXlcbiAgICApO1xuICAgIGNvbnN0IFt1c2VyTXNnMl0gPSB1c2VyRHNnLmhhbmRsZUluY29taW5nTWVzc2FnZXMoW3VzZXJNc2cxLCBiaXRnb0Rlc2VyaWFsaXplZE1zZzFdKTtcblxuICAgIGNvbnN0IHNoYXJlOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IGF3YWl0IGdldFNpZ25hdHVyZVNoYXJlUm91bmRUd28odXNlck1zZzIsIHVzZXJHcGdQcml2S2V5KTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaGFyZS5mcm9tLCBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUik7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNoYXJlLnRvLCBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08pO1xuXG4gICAgY29uc3QgcGFyc2VkID0gZGVjb2RlV2l0aENvZGVjKFxuICAgICAgRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQySW5wdXQsXG4gICAgICBKU09OLnBhcnNlKHNoYXJlLnNoYXJlKSxcbiAgICAgICdFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJJbnB1dCdcbiAgICApO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWQudHlwZSwgJ3JvdW5kMklucHV0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5kYXRhLm1zZzIubWVzc2FnZSwgJ21zZzIubWVzc2FnZSBzaG91bGQgYmUgc2V0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5kYXRhLm1zZzIuc2lnbmF0dXJlLCAnbXNnMi5zaWduYXR1cmUgc2hvdWxkIGJlIHNldCcpO1xuICB9KTtcblxuICBpdCgnZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZFR3byBzaG91bGQgYnVpbGQgYSB2YWxpZCBiYWNrdXAgcm91bmQtMiBzaGFyZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCBiYWNrdXBEc2cgPSBuZXcgRWRkc2FNUFNEc2cuRFNHKE1QQ3YyUGFydGllc0VudW0uQkFDS1VQKTtcbiAgICBhd2FpdCBiYWNrdXBEc2cuaW5pdERzZyhiYWNrdXBLZXlTaGFyZSwgbWVzc2FnZUJ1ZmZlciwgZGVyaXZhdGlvblBhdGgsIE1QQ3YyUGFydGllc0VudW0uQklUR08pO1xuICAgIGNvbnN0IGJhY2t1cE1zZzEgPSBiYWNrdXBEc2cuZ2V0Rmlyc3RNZXNzYWdlKCk7XG5cbiAgICBjb25zdCBiaXRnb0RzZyA9IG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5CSVRHTyk7XG4gICAgYXdhaXQgYml0Z29Ec2cuaW5pdERzZyhiaXRnb0tleVNoYXJlLCBtZXNzYWdlQnVmZmVyLCBkZXJpdmF0aW9uUGF0aCwgTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVApO1xuICAgIGNvbnN0IGJpdGdvTXNnMSA9IGJpdGdvRHNnLmdldEZpcnN0TWVzc2FnZSgpO1xuXG4gICAgY29uc3QgYml0Z29TaWduZWRNc2cxID0gYXdhaXQgTVBTQ29tbXMuZGV0YWNoU2lnbk1wc01lc3NhZ2UoQnVmZmVyLmZyb20oYml0Z29Nc2cxLnBheWxvYWQpLCBiaXRnb0dwZ1ByaXZLZXkpO1xuICAgIGNvbnN0IGJpdGdvRGVzZXJpYWxpemVkTXNnMSA9IGF3YWl0IHZlcmlmeVBlZXJNZXNzYWdlUm91bmRPbmUoXG4gICAgICB7IHR5cGU6ICdyb3VuZDFPdXRwdXQnLCBkYXRhOiB7IG1zZzE6IGJpdGdvU2lnbmVkTXNnMSB9IH0sXG4gICAgICBiaXRnb0dwZ1B1YktleVxuICAgICk7XG4gICAgY29uc3QgW2JhY2t1cE1zZzJdID0gYmFja3VwRHNnLmhhbmRsZUluY29taW5nTWVzc2FnZXMoW2JhY2t1cE1zZzEsIGJpdGdvRGVzZXJpYWxpemVkTXNnMV0pO1xuXG4gICAgY29uc3Qgc2hhcmU6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0gYXdhaXQgZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZFR3byhcbiAgICAgIGJhY2t1cE1zZzIsXG4gICAgICBiYWNrdXBHcGdQcml2S2V5LFxuICAgICAgTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVBcbiAgICApO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNoYXJlLmZyb20sIFNpZ25hdHVyZVNoYXJlVHlwZS5CQUNLVVApO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaGFyZS50bywgU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPKTtcblxuICAgIGNvbnN0IHBhcnNlZCA9IGRlY29kZVdpdGhDb2RlYyhcbiAgICAgIEVkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMklucHV0LFxuICAgICAgSlNPTi5wYXJzZShzaGFyZS5zaGFyZSksXG4gICAgICAnRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQySW5wdXQnXG4gICAgKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnR5cGUsICdyb3VuZDJJbnB1dCcpO1xuICAgIGFzc2VydC5vayhwYXJzZWQuZGF0YS5tc2cyLm1lc3NhZ2UsICdtc2cyLm1lc3NhZ2Ugc2hvdWxkIGJlIHNldCcpO1xuICAgIGFzc2VydC5vayhwYXJzZWQuZGF0YS5tc2cyLnNpZ25hdHVyZSwgJ21zZzIuc2lnbmF0dXJlIHNob3VsZCBiZSBzZXQnKTtcbiAgfSk7XG5cbiAgaXQoJ3ZlcmlmeVBlZXJNZXNzYWdlUm91bmRUd28gc2hvdWxkIHZlcmlmeSBhIHZhbGlkIEJpdEdvIHJvdW5kLTIgbWVzc2FnZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCB1c2VyRHNnID0gbmV3IEVkZHNhTVBTRHNnLkRTRyhNUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuICAgIGF3YWl0IHVzZXJEc2cuaW5pdERzZyh1c2VyS2V5U2hhcmUsIG1lc3NhZ2VCdWZmZXIsIGRlcml2YXRpb25QYXRoLCBNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBjb25zdCB1c2VyTXNnMSA9IHVzZXJEc2cuZ2V0Rmlyc3RNZXNzYWdlKCk7XG5cbiAgICBjb25zdCBiaXRnb0RzZyA9IG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5CSVRHTyk7XG4gICAgYXdhaXQgYml0Z29Ec2cuaW5pdERzZyhiaXRnb0tleVNoYXJlLCBtZXNzYWdlQnVmZmVyLCBkZXJpdmF0aW9uUGF0aCwgTVBDdjJQYXJ0aWVzRW51bS5VU0VSKTtcbiAgICBjb25zdCBiaXRnb01zZzEgPSBiaXRnb0RzZy5nZXRGaXJzdE1lc3NhZ2UoKTtcblxuICAgIGNvbnN0IFtiaXRnb01zZzJdID0gYml0Z29Ec2cuaGFuZGxlSW5jb21pbmdNZXNzYWdlcyhbYml0Z29Nc2cxLCB1c2VyTXNnMV0pO1xuICAgIGNvbnN0IGJpdGdvU2lnbmVkTXNnMiA9IGF3YWl0IE1QU0NvbW1zLmRldGFjaFNpZ25NcHNNZXNzYWdlKEJ1ZmZlci5mcm9tKGJpdGdvTXNnMi5wYXlsb2FkKSwgYml0Z29HcGdQcml2S2V5KTtcblxuICAgIGNvbnN0IHJvdW5kMk91dHB1dDogRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQyT3V0cHV0ID0ge1xuICAgICAgdHlwZTogJ3JvdW5kMk91dHB1dCcsXG4gICAgICBkYXRhOiB7IG1zZzI6IGJpdGdvU2lnbmVkTXNnMiB9LFxuICAgIH07XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kVHdvKHJvdW5kMk91dHB1dCwgYml0Z29HcGdQdWJLZXkpO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5mcm9tLCBNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBhc3NlcnQub2socmVzdWx0LnBheWxvYWQubGVuZ3RoID4gMCwgJ3BheWxvYWQgc2hvdWxkIGJlIG5vbi1lbXB0eScpO1xuICB9KTtcblxuICBpdCgndmVyaWZ5UGVlck1lc3NhZ2VSb3VuZFR3byBzaG91bGQgdGhyb3cgb24gYSB0YW1wZXJlZCBtZXNzYWdlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJvdW5kMk91dHB1dDogRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQyT3V0cHV0ID0ge1xuICAgICAgdHlwZTogJ3JvdW5kMk91dHB1dCcsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIG1zZzI6IHtcbiAgICAgICAgICBtZXNzYWdlOiBCdWZmZXIuZnJvbSgndGFtcGVyZWQnKS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICAgICAgc2lnbmF0dXJlOiAnLS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS1cXG5cXG5JTlZBTElEXFxuLS0tLS1FTkQgUEdQIFNJR05BVFVSRS0tLS0tXFxuJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKHZlcmlmeVBlZXJNZXNzYWdlUm91bmRUd28ocm91bmQyT3V0cHV0LCBiaXRnb0dwZ1B1YktleSksICdzaG91bGQgdGhyb3cgb24gaW52YWxpZCBzaWduYXR1cmUnKTtcbiAgfSk7XG5cbiAgLy8g4pSA4pSAIFJvdW5kIDMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgaXQoJ2dldFNpZ25hdHVyZVNoYXJlUm91bmRUaHJlZSBzaG91bGQgYnVpbGQgYSB2YWxpZCByb3VuZC0zIHNoYXJlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG1lc3NhZ2VCdWZmZXIgPSBCdWZmZXIuZnJvbShzaWduYWJsZUhleCwgJ2hleCcpO1xuICAgIGNvbnN0IHVzZXJEc2cgPSBuZXcgRWRkc2FNUFNEc2cuRFNHKE1QQ3YyUGFydGllc0VudW0uVVNFUik7XG4gICAgYXdhaXQgdXNlckRzZy5pbml0RHNnKHVzZXJLZXlTaGFyZSwgbWVzc2FnZUJ1ZmZlciwgZGVyaXZhdGlvblBhdGgsIE1QQ3YyUGFydGllc0VudW0uQklUR08pO1xuICAgIGNvbnN0IHVzZXJNc2cxID0gdXNlckRzZy5nZXRGaXJzdE1lc3NhZ2UoKTtcblxuICAgIGNvbnN0IGJpdGdvRHNnID0gbmV3IEVkZHNhTVBTRHNnLkRTRyhNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBhd2FpdCBiaXRnb0RzZy5pbml0RHNnKGJpdGdvS2V5U2hhcmUsIG1lc3NhZ2VCdWZmZXIsIGRlcml2YXRpb25QYXRoLCBNUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuICAgIGNvbnN0IGJpdGdvTXNnMSA9IGJpdGdvRHNnLmdldEZpcnN0TWVzc2FnZSgpO1xuXG4gICAgLy8gQWR2YW5jZSB0byByb3VuZCAyXG4gICAgY29uc3QgYml0Z29TaWduZWRNc2cxID0gYXdhaXQgTVBTQ29tbXMuZGV0YWNoU2lnbk1wc01lc3NhZ2UoQnVmZmVyLmZyb20oYml0Z29Nc2cxLnBheWxvYWQpLCBiaXRnb0dwZ1ByaXZLZXkpO1xuICAgIGNvbnN0IGJpdGdvRGVzZXJpYWxpemVkTXNnMSA9IGF3YWl0IHZlcmlmeVBlZXJNZXNzYWdlUm91bmRPbmUoXG4gICAgICB7IHR5cGU6ICdyb3VuZDFPdXRwdXQnLCBkYXRhOiB7IG1zZzE6IGJpdGdvU2lnbmVkTXNnMSB9IH0sXG4gICAgICBiaXRnb0dwZ1B1YktleVxuICAgICk7XG4gICAgY29uc3QgW3VzZXJNc2cyXSA9IHVzZXJEc2cuaGFuZGxlSW5jb21pbmdNZXNzYWdlcyhbdXNlck1zZzEsIGJpdGdvRGVzZXJpYWxpemVkTXNnMV0pO1xuXG4gICAgY29uc3QgW2JpdGdvTXNnMl0gPSBiaXRnb0RzZy5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKFtiaXRnb01zZzEsIHVzZXJNc2cxXSk7XG4gICAgY29uc3QgYml0Z29TaWduZWRNc2cyID0gYXdhaXQgTVBTQ29tbXMuZGV0YWNoU2lnbk1wc01lc3NhZ2UoQnVmZmVyLmZyb20oYml0Z29Nc2cyLnBheWxvYWQpLCBiaXRnb0dwZ1ByaXZLZXkpO1xuICAgIGNvbnN0IGJpdGdvRGVzZXJpYWxpemVkTXNnMiA9IGF3YWl0IHZlcmlmeVBlZXJNZXNzYWdlUm91bmRUd28oXG4gICAgICB7IHR5cGU6ICdyb3VuZDJPdXRwdXQnLCBkYXRhOiB7IG1zZzI6IGJpdGdvU2lnbmVkTXNnMiB9IH0sXG4gICAgICBiaXRnb0dwZ1B1YktleVxuICAgICk7XG4gICAgY29uc3QgW3VzZXJNc2czXSA9IHVzZXJEc2cuaGFuZGxlSW5jb21pbmdNZXNzYWdlcyhbdXNlck1zZzIsIGJpdGdvRGVzZXJpYWxpemVkTXNnMl0pO1xuXG4gICAgY29uc3Qgc2hhcmU6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0gYXdhaXQgZ2V0U2lnbmF0dXJlU2hhcmVSb3VuZFRocmVlKHVzZXJNc2czLCB1c2VyR3BnUHJpdktleSk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2hhcmUuZnJvbSwgU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaGFyZS50bywgU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPKTtcblxuICAgIGNvbnN0IHBhcnNlZCA9IGRlY29kZVdpdGhDb2RlYyhcbiAgICAgIEVkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kM0lucHV0LFxuICAgICAgSlNPTi5wYXJzZShzaGFyZS5zaGFyZSksXG4gICAgICAnRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQzSW5wdXQnXG4gICAgKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnR5cGUsICdyb3VuZDNJbnB1dCcpO1xuICAgIGFzc2VydC5vayhwYXJzZWQuZGF0YS5tc2czLm1lc3NhZ2UsICdtc2czLm1lc3NhZ2Ugc2hvdWxkIGJlIHNldCcpO1xuICAgIGFzc2VydC5vayhwYXJzZWQuZGF0YS5tc2czLnNpZ25hdHVyZSwgJ21zZzMuc2lnbmF0dXJlIHNob3VsZCBiZSBzZXQnKTtcbiAgfSk7XG5cbiAgaXQoJ2dldFNpZ25hdHVyZVNoYXJlUm91bmRUaHJlZSBzaG91bGQgYnVpbGQgYSB2YWxpZCBiYWNrdXAgcm91bmQtMyBzaGFyZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCBiYWNrdXBEc2cgPSBuZXcgRWRkc2FNUFNEc2cuRFNHKE1QQ3YyUGFydGllc0VudW0uQkFDS1VQKTtcbiAgICBhd2FpdCBiYWNrdXBEc2cuaW5pdERzZyhiYWNrdXBLZXlTaGFyZSwgbWVzc2FnZUJ1ZmZlciwgZGVyaXZhdGlvblBhdGgsIE1QQ3YyUGFydGllc0VudW0uQklUR08pO1xuICAgIGNvbnN0IGJhY2t1cE1zZzEgPSBiYWNrdXBEc2cuZ2V0Rmlyc3RNZXNzYWdlKCk7XG5cbiAgICBjb25zdCBiaXRnb0RzZyA9IG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5CSVRHTyk7XG4gICAgYXdhaXQgYml0Z29Ec2cuaW5pdERzZyhiaXRnb0tleVNoYXJlLCBtZXNzYWdlQnVmZmVyLCBkZXJpdmF0aW9uUGF0aCwgTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVApO1xuICAgIGNvbnN0IGJpdGdvTXNnMSA9IGJpdGdvRHNnLmdldEZpcnN0TWVzc2FnZSgpO1xuXG4gICAgY29uc3QgYml0Z29TaWduZWRNc2cxID0gYXdhaXQgTVBTQ29tbXMuZGV0YWNoU2lnbk1wc01lc3NhZ2UoQnVmZmVyLmZyb20oYml0Z29Nc2cxLnBheWxvYWQpLCBiaXRnb0dwZ1ByaXZLZXkpO1xuICAgIGNvbnN0IGJpdGdvRGVzZXJpYWxpemVkTXNnMSA9IGF3YWl0IHZlcmlmeVBlZXJNZXNzYWdlUm91bmRPbmUoXG4gICAgICB7IHR5cGU6ICdyb3VuZDFPdXRwdXQnLCBkYXRhOiB7IG1zZzE6IGJpdGdvU2lnbmVkTXNnMSB9IH0sXG4gICAgICBiaXRnb0dwZ1B1YktleVxuICAgICk7XG4gICAgY29uc3QgW2JhY2t1cE1zZzJdID0gYmFja3VwRHNnLmhhbmRsZUluY29taW5nTWVzc2FnZXMoW2JhY2t1cE1zZzEsIGJpdGdvRGVzZXJpYWxpemVkTXNnMV0pO1xuXG4gICAgY29uc3QgW2JpdGdvTXNnMl0gPSBiaXRnb0RzZy5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKFtiaXRnb01zZzEsIGJhY2t1cE1zZzFdKTtcbiAgICBjb25zdCBiaXRnb1NpZ25lZE1zZzIgPSBhd2FpdCBNUFNDb21tcy5kZXRhY2hTaWduTXBzTWVzc2FnZShCdWZmZXIuZnJvbShiaXRnb01zZzIucGF5bG9hZCksIGJpdGdvR3BnUHJpdktleSk7XG4gICAgY29uc3QgYml0Z29EZXNlcmlhbGl6ZWRNc2cyID0gYXdhaXQgdmVyaWZ5UGVlck1lc3NhZ2VSb3VuZFR3byhcbiAgICAgIHsgdHlwZTogJ3JvdW5kMk91dHB1dCcsIGRhdGE6IHsgbXNnMjogYml0Z29TaWduZWRNc2cyIH0gfSxcbiAgICAgIGJpdGdvR3BnUHViS2V5XG4gICAgKTtcbiAgICBjb25zdCBbYmFja3VwTXNnM10gPSBiYWNrdXBEc2cuaGFuZGxlSW5jb21pbmdNZXNzYWdlcyhbYmFja3VwTXNnMiwgYml0Z29EZXNlcmlhbGl6ZWRNc2cyXSk7XG5cbiAgICBjb25zdCBzaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSBhd2FpdCBnZXRTaWduYXR1cmVTaGFyZVJvdW5kVGhyZWUoXG4gICAgICBiYWNrdXBNc2czLFxuICAgICAgYmFja3VwR3BnUHJpdktleSxcbiAgICAgIE1QQ3YyUGFydGllc0VudW0uQkFDS1VQXG4gICAgKTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaGFyZS5mcm9tLCBTaWduYXR1cmVTaGFyZVR5cGUuQkFDS1VQKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2hhcmUudG8sIFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyk7XG5cbiAgICBjb25zdCBwYXJzZWQgPSBkZWNvZGVXaXRoQ29kZWMoXG4gICAgICBFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDNJbnB1dCxcbiAgICAgIEpTT04ucGFyc2Uoc2hhcmUuc2hhcmUpLFxuICAgICAgJ0VkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kM0lucHV0J1xuICAgICk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC50eXBlLCAncm91bmQzSW5wdXQnKTtcbiAgICBhc3NlcnQub2socGFyc2VkLmRhdGEubXNnMy5tZXNzYWdlLCAnbXNnMy5tZXNzYWdlIHNob3VsZCBiZSBzZXQnKTtcbiAgICBhc3NlcnQub2socGFyc2VkLmRhdGEubXNnMy5zaWduYXR1cmUsICdtc2czLnNpZ25hdHVyZSBzaG91bGQgYmUgc2V0Jyk7XG4gIH0pO1xuXG4gIGl0KCd2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kVGhyZWUgc2hvdWxkIHZlcmlmeSBhIHZhbGlkIEJpdEdvIHJvdW5kLTMgbWVzc2FnZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCBbLCBbYml0Z29Nc2czXV0gPSAoYXdhaXQgTVBTVXRpbC5leGVjdXRlVGlsbFJvdW5kKFxuICAgICAgMixcbiAgICAgIG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5VU0VSKSxcbiAgICAgIG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5CSVRHTyksXG4gICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICBiaXRnb0tleVNoYXJlLFxuICAgICAgbWVzc2FnZUJ1ZmZlcixcbiAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgKSkgYXMgTVBTVHlwZXMuRGVzZXJpYWxpemVkTWVzc2FnZXNbXTtcbiAgICBjb25zdCBiaXRnb1NpZ25lZE1zZzMgPSBhd2FpdCBNUFNDb21tcy5kZXRhY2hTaWduTXBzTWVzc2FnZShCdWZmZXIuZnJvbShiaXRnb01zZzMucGF5bG9hZCksIGJpdGdvR3BnUHJpdktleSk7XG5cbiAgICBjb25zdCByb3VuZDNPdXRwdXQ6IEVkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kM091dHB1dCA9IHtcbiAgICAgIHR5cGU6ICdyb3VuZDNPdXRwdXQnLFxuICAgICAgZGF0YTogeyBtc2czOiBiaXRnb1NpZ25lZE1zZzMgfSxcbiAgICB9O1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdmVyaWZ5UGVlck1lc3NhZ2VSb3VuZFRocmVlKHJvdW5kM091dHB1dCwgYml0Z29HcGdQdWJLZXkpO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC5mcm9tLCBNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBhc3NlcnQub2socmVzdWx0LnBheWxvYWQubGVuZ3RoID4gMCwgJ3BheWxvYWQgc2hvdWxkIGJlIG5vbi1lbXB0eScpO1xuICB9KTtcblxuICBpdCgndmVyaWZ5UGVlck1lc3NhZ2VSb3VuZFRocmVlIHNob3VsZCB0aHJvdyBvbiBhIHRhbXBlcmVkIG1lc3NhZ2UnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgcm91bmQzT3V0cHV0OiBFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDNPdXRwdXQgPSB7XG4gICAgICB0eXBlOiAncm91bmQzT3V0cHV0JyxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgbXNnMzoge1xuICAgICAgICAgIG1lc3NhZ2U6IEJ1ZmZlci5mcm9tKCd0YW1wZXJlZCcpLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgICBzaWduYXR1cmU6ICctLS0tLUJFR0lOIFBHUCBTSUdOQVRVUkUtLS0tLVxcblxcbklOVkFMSURcXG4tLS0tLUVORCBQR1AgU0lHTkFUVVJFLS0tLS1cXG4nLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuXG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICB2ZXJpZnlQZWVyTWVzc2FnZVJvdW5kVGhyZWUocm91bmQzT3V0cHV0LCBiaXRnb0dwZ1B1YktleSksXG4gICAgICAnc2hvdWxkIHRocm93IG9uIGludmFsaWQgc2lnbmF0dXJlJ1xuICAgICk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdnZXRFZGRzYU1QQ3YyUmVjb3ZlcnlLZXlTaGFyZXMnLCAoKSA9PiB7XG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuXG4gIGNvbnN0IGVuY3J5cHRLZXkgPSAoa2V5U2hhcmU6IEJ1ZmZlcik6IHN0cmluZyA9PiBzamNsLmVuY3J5cHQod2FsbGV0UGFzc3BocmFzZSwga2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpKTtcblxuICBpdCgnc2hvdWxkIHJldHVybiByZWNvdmVyeSBrZXkgc2hhcmVzIGZyb20gdjEtZW5jcnlwdGVkIHJlZHVjZWQga2V5cyAobm8gYml0Z28gaW5zdGFuY2UpJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IFt1c2VyRGtnLCBiYWNrdXBEa2ddID0gYXdhaXQgTVBTVXRpbC5nZW5lcmF0ZUVkRHNhREtHS2V5U2hhcmVzKCk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgRUREU0FVdGlscy5nZXRFZGRzYU1wY1YyUmVjb3ZlcnlLZXlTaGFyZXNGcm9tUmVkdWNlZEtleShcbiAgICAgIGVuY3J5cHRLZXkodXNlckRrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKSksXG4gICAgICBlbmNyeXB0S2V5KGJhY2t1cERrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKSksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlXG4gICAgKTtcblxuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocmVzdWx0LnVzZXJLZXlTaGFyZSwgdXNlckRrZy5nZXRLZXlTaGFyZSgpKTtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHJlc3VsdC5iYWNrdXBLZXlTaGFyZSwgYmFja3VwRGtnLmdldEtleVNoYXJlKCkpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuY29tbW9uS2V5Q2hhaW4sIHVzZXJEa2cuZ2V0Q29tbW9uS2V5Y2hhaW4oKSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdW53cmFwIHZlcnNpb25lZCBzYWZlLXJvb3QgZW52ZWxvcGVzIGFuZCByZXR1cm4gVlJGIGtleXNoYXJlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZywgYmFja3VwRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgIGNvbnN0IHVzZXJWcmZLZXlTaGFyZSA9IEJ1ZmZlci5mcm9tKCd1c2VyLXZyZi1rZXlzaGFyZScpO1xuICAgIGNvbnN0IGJhY2t1cFZyZktleVNoYXJlID0gQnVmZmVyLmZyb20oJ2JhY2t1cC12cmYta2V5c2hhcmUnKTtcbiAgICBjb25zdCBlbmNvZGVFbnZlbG9wZSA9IChyZWR1Y2VkS2V5U2hhcmU6IEJ1ZmZlciwgdnJmS2V5U2hhcmU6IEJ1ZmZlcik6IEJ1ZmZlciA9PlxuICAgICAgQnVmZmVyLmZyb20oXG4gICAgICAgIGVuY29kZSh7XG4gICAgICAgICAgdmVyc2lvbjogMSxcbiAgICAgICAgICBwcnZLZXlTaGFyZTogbmV3IFVpbnQ4QXJyYXkocmVkdWNlZEtleVNoYXJlKSxcbiAgICAgICAgICB2cmY6IG5ldyBVaW50OEFycmF5KHZyZktleVNoYXJlKSxcbiAgICAgICAgfSlcbiAgICAgICk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBFRERTQVV0aWxzLmdldEVkZHNhTXBjVjJSZWNvdmVyeUtleVNoYXJlc0Zyb21SZWR1Y2VkS2V5KFxuICAgICAgZW5jcnlwdEtleShlbmNvZGVFbnZlbG9wZSh1c2VyRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpLCB1c2VyVnJmS2V5U2hhcmUpKSxcbiAgICAgIGVuY3J5cHRLZXkoZW5jb2RlRW52ZWxvcGUoYmFja3VwRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpLCBiYWNrdXBWcmZLZXlTaGFyZSkpLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZVxuICAgICk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoQnVmZmVyLmNvbXBhcmUocmVzdWx0LnVzZXJLZXlTaGFyZSwgdXNlckRrZy5nZXRLZXlTaGFyZSgpKSwgMCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKEJ1ZmZlci5jb21wYXJlKHJlc3VsdC5iYWNrdXBLZXlTaGFyZSwgYmFja3VwRGtnLmdldEtleVNoYXJlKCkpLCAwKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LmNvbW1vbktleUNoYWluLCB1c2VyRGtnLmdldENvbW1vbktleWNoYWluKCkpO1xuICAgIGFzc2VydC5vayhyZXN1bHQudXNlclZyZktleVNoYXJlKTtcbiAgICBhc3NlcnQub2socmVzdWx0LmJhY2t1cFZyZktleVNoYXJlKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoQnVmZmVyLmNvbXBhcmUocmVzdWx0LnVzZXJWcmZLZXlTaGFyZSwgdXNlclZyZktleVNoYXJlKSwgMCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKEJ1ZmZlci5jb21wYXJlKHJlc3VsdC5iYWNrdXBWcmZLZXlTaGFyZSwgYmFja3VwVnJmS2V5U2hhcmUpLCAwKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByb3V0ZSBkZWNyeXB0aW9uIHRocm91Z2ggYml0Z28uZGVjcnlwdCB3aGVuIGEgYml0Z28gaW5zdGFuY2UgaXMgcHJvdmlkZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgLy8gc2RrLWNvcmUgaGFzIG5vIGRldkRlcGVuZGVuY3kgb24gc2RrLWFwaSBvciBhcmdvbjIsIHNvIHdlIGNhbm5vdCBlbmNyeXB0IHdpdGggYSByZWFsIHYyIGVudmVsb3BlIGhlcmUuXG4gICAgLy8gVGhlIHN0dWIgdmVyaWZpZXMgdGhhdCB0aGUgZnVuY3Rpb24gZGVsZWdhdGVzIHRvIGJpdGdvLmRlY3J5cHQgKHdoaWNoIHN1cHBvcnRzIHYxICsgdjIgaW5cbiAgICAvLyBwcm9kdWN0aW9uKSByYXRoZXIgdGhhbiBmYWxsaW5nIGJhY2sgdG8gc2pjbC5kZWNyeXB0LlxuICAgIGNvbnN0IFt1c2VyRGtnLCBiYWNrdXBEa2ddID0gYXdhaXQgTVBTVXRpbC5nZW5lcmF0ZUVkRHNhREtHS2V5U2hhcmVzKCk7XG4gICAgY29uc3QgdXNlcktleUJhc2U2NCA9IHVzZXJEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgIGNvbnN0IGJhY2t1cEtleUJhc2U2NCA9IGJhY2t1cERrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKS50b1N0cmluZygnYmFzZTY0Jyk7XG5cbiAgICBjb25zdCBtb2NrQml0Z28gPSB7XG4gICAgICBkZWNyeXB0OiBzaW5vbi5zdHViKCkub25GaXJzdENhbGwoKS5yZXNvbHZlcyh1c2VyS2V5QmFzZTY0KS5vblNlY29uZENhbGwoKS5yZXNvbHZlcyhiYWNrdXBLZXlCYXNlNjQpLFxuICAgIH0gYXMgdW5rbm93biBhcyBCaXRHb0Jhc2U7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBFRERTQVV0aWxzLmdldEVkZHNhTXBjVjJSZWNvdmVyeUtleVNoYXJlc0Zyb21SZWR1Y2VkS2V5KFxuICAgICAgJ2VuY3J5cHRlZC11c2VyLWtleScsXG4gICAgICAnZW5jcnlwdGVkLWJhY2t1cC1rZXknLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIG1vY2tCaXRnb1xuICAgICk7XG5cbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkVHdpY2UobW9ja0JpdGdvLmRlY3J5cHQgYXMgc2lub24uU2lub25TdHViKTtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHJlc3VsdC51c2VyS2V5U2hhcmUsIHVzZXJEa2cuZ2V0S2V5U2hhcmUoKSk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChyZXN1bHQuYmFja3VwS2V5U2hhcmUsIGJhY2t1cERrZy5nZXRLZXlTaGFyZSgpKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LmNvbW1vbktleUNoYWluLCB1c2VyRGtnLmdldENvbW1vbktleWNoYWluKCkpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCBhIG1hbGZvcm1lZCBrZXljYXJkIHdpdGggYSBkZXNjcmlwdGl2ZSBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZ10gPSBhd2FpdCBNUFNVdGlsLmdlbmVyYXRlRWREc2FES0dLZXlTaGFyZXMoKTtcbiAgICBjb25zdCBtYWxmb3JtZWRLZXkgPSBzamNsLmVuY3J5cHQod2FsbGV0UGFzc3BocmFzZSwgcmFuZG9tQnl0ZXMoNjQpLnRvU3RyaW5nKCdiYXNlNjQnKSk7XG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICBFRERTQVV0aWxzLmdldEVkZHNhTXBjVjJSZWNvdmVyeUtleVNoYXJlc0Zyb21SZWR1Y2VkS2V5KFxuICAgICAgICBtYWxmb3JtZWRLZXksXG4gICAgICAgIGVuY3J5cHRLZXkodXNlckRrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKSksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2VcbiAgICAgICksXG4gICAgICAvdW5hYmxlIHRvIGRlY29kZSByZWR1Y2VkIGtleSBzaGFyZS9cbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCByZWR1Y2VkIGtleXMgZnJvbSBkaWZmZXJlbnQgd2FsbGV0cycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZ10gPSBhd2FpdCBNUFNVdGlsLmdlbmVyYXRlRWREc2FES0dLZXlTaGFyZXMoKTtcbiAgICBjb25zdCBbLCBiYWNrdXBEa2ddID0gYXdhaXQgTVBTVXRpbC5nZW5lcmF0ZUVkRHNhREtHS2V5U2hhcmVzKCk7XG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICBFRERTQVV0aWxzLmdldEVkZHNhTXBjVjJSZWNvdmVyeUtleVNoYXJlc0Zyb21SZWR1Y2VkS2V5KFxuICAgICAgICBlbmNyeXB0S2V5KHVzZXJEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkpLFxuICAgICAgICBlbmNyeXB0S2V5KGJhY2t1cERrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKSksXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2VcbiAgICAgICksXG4gICAgICAvcHViIGtleXMgZG8gbm90IG1hdGNoL1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IHJlZHVjZWQga2V5cyB3aXRoIG1hdGNoaW5nIHB1YiBidXQgbWlzbWF0Y2hlZCByb290Q2hhaW5Db2RlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZywgYmFja3VwRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgIGNvbnN0IHVzZXJSZWR1Y2VkS2V5U2hhcmUgPSB1c2VyRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpO1xuICAgIGNvbnN0IGJhY2t1cFJlZHVjZWRLZXlTaGFyZSA9IGJhY2t1cERrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKTtcbiAgICBjb25zdCBnZXREZWNvZGVkUmVkdWNlZEtleVNoYXJlID0gTVBTVHlwZXMuZ2V0RGVjb2RlZFJlZHVjZWRLZXlTaGFyZTtcbiAgICBjb25zdCBkZWNvZGVTdHViID0gc2lub24uc3R1YihNUFNUeXBlcywgJ2dldERlY29kZWRSZWR1Y2VkS2V5U2hhcmUnKS5jYWxsc0Zha2UoKGJ1ZikgPT4ge1xuICAgICAgY29uc3QgcmVkdWNlZCA9IGdldERlY29kZWRSZWR1Y2VkS2V5U2hhcmUoYnVmKTtcbiAgICAgIGlmIChCdWZmZXIuZnJvbShidWYpLmVxdWFscyhiYWNrdXBSZWR1Y2VkS2V5U2hhcmUpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4ucmVkdWNlZCxcbiAgICAgICAgICByb290Q2hhaW5Db2RlOiBBcnJheS5mcm9tKHJhbmRvbUJ5dGVzKDMyKSksXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVkdWNlZDtcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgRUREU0FVdGlscy5nZXRFZGRzYU1wY1YyUmVjb3ZlcnlLZXlTaGFyZXNGcm9tUmVkdWNlZEtleShcbiAgICAgICAgICBlbmNyeXB0S2V5KHVzZXJSZWR1Y2VkS2V5U2hhcmUpLFxuICAgICAgICAgIGVuY3J5cHRLZXkoYmFja3VwUmVkdWNlZEtleVNoYXJlKSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlXG4gICAgICAgICksXG4gICAgICAgIC9yb290Q2hhaW5Db2RlcyBkbyBub3QgbWF0Y2gvXG4gICAgICApO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBkZWNvZGVTdHViLnJlc3RvcmUoKTtcbiAgICB9XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdFZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kMVNoYXJlJywgKCkgPT4ge1xuICBsZXQgZWRkc2FNUEN2MlV0aWxzOiBFZGRzYU1QQ3YyVXRpbHM7XG4gIGxldCBtb2NrQml0Z286IEJpdEdvQmFzZTtcbiAgbGV0IHVzZXJLZXlTaGFyZTogQnVmZmVyO1xuXG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuICBjb25zdCBzaWduYWJsZUhleCA9ICdkZWFkYmVlZic7XG4gIGNvbnN0IGRlcml2YXRpb25QYXRoID0gJ20vMC8wJztcbiAgY29uc3QgZXhwZWN0ZWRBZGF0YSA9IGAke3NpZ25hYmxlSGV4fToke2Rlcml2YXRpb25QYXRofWA7XG4gIGNvbnN0IHR4UmVxdWVzdDogVHhSZXF1ZXN0ID0ge1xuICAgIHR4UmVxdWVzdElkOiAndHhyZXEtZWRkc2Etcm91bmQxJyxcbiAgICB3YWxsZXRJZDogJ3dhbGxldC1lZGRzYS1yb3VuZDEnLFxuICAgIGVudGVycHJpc2VJZDogJ2VudGVycHJpc2UtZWRkc2Etcm91bmQxJyxcbiAgICBhcGlWZXJzaW9uOiAnZnVsbCcsXG4gICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICB7XG4gICAgICAgIHVuc2lnbmVkVHg6IHtcbiAgICAgICAgICBzaWduYWJsZUhleCxcbiAgICAgICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgICBzZXJpYWxpemVkVHhIZXg6IHNpZ25hYmxlSGV4LFxuICAgICAgICB9LFxuICAgICAgICBzaWduYXR1cmVTaGFyZXM6IFtdLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGludGVudDogeyBpbnRlbnRUeXBlOiAncGF5bWVudCcgfSxcbiAgICB1bnNpZ25lZFR4czogW10sXG4gIH0gYXMgdW5rbm93biBhcyBUeFJlcXVlc3Q7XG5cbiAgYmVmb3JlKCdnZW5lcmF0ZSBFZERTQSB1c2VyIGtleSBzaGFyZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZ10gPSBhd2FpdCBNUFNVdGlsLmdlbmVyYXRlRWREc2FES0dLZXlTaGFyZXMoKTtcbiAgICB1c2VyS2V5U2hhcmUgPSB1c2VyRGtnLmdldEtleVNoYXJlKCk7XG4gIH0pO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGNvbnN0IHNqY2xFbmNyeXB0ID0gKHBhcmFtczogeyBwYXNzd29yZDogc3RyaW5nOyBpbnB1dDogc3RyaW5nOyBhZGF0YT86IHN0cmluZyB9KSA9PiB7XG4gICAgICBjb25zdCBzYWx0ID0gcmFuZG9tQnl0ZXMoOCk7XG4gICAgICBjb25zdCBpdiA9IHJhbmRvbUJ5dGVzKDE2KTtcbiAgICAgIHJldHVybiBzamNsLmVuY3J5cHQocGFyYW1zLnBhc3N3b3JkLCBwYXJhbXMuaW5wdXQsIHtcbiAgICAgICAgc2FsdDogW2J5dGVzVG9Xb3JkKHNhbHQuc3ViYXJyYXkoMCwgNCkpLCBieXRlc1RvV29yZChzYWx0LnN1YmFycmF5KDQpKV0sXG4gICAgICAgIGl2OiBbXG4gICAgICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoMCwgNCkpLFxuICAgICAgICAgIGJ5dGVzVG9Xb3JkKGl2LnN1YmFycmF5KDQsIDgpKSxcbiAgICAgICAgICBieXRlc1RvV29yZChpdi5zdWJhcnJheSg4LCAxMikpLFxuICAgICAgICAgIGJ5dGVzVG9Xb3JkKGl2LnN1YmFycmF5KDEyLCAxNikpLFxuICAgICAgICBdLFxuICAgICAgICBhZGF0YTogcGFyYW1zLmFkYXRhLFxuICAgICAgfSk7XG4gICAgfTtcbiAgICBtb2NrQml0Z28gPSB7XG4gICAgICBlbmNyeXB0OiBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKGFzeW5jIChwYXJhbXMpID0+IHNqY2xFbmNyeXB0KHBhcmFtcykpLFxuICAgIH0gYXMgdW5rbm93biBhcyBCaXRHb0Jhc2U7XG5cbiAgICBjb25zdCBtb2NrQ29pbiA9IHtcbiAgICAgIGdldE1QQ0FsZ29yaXRobTogc2lub24uc3R1YigpLnJldHVybnMoJ2VkZHNhJyksXG4gICAgfSBhcyB1bmtub3duIGFzIElCYXNlQ29pbjtcblxuICAgIGVkZHNhTVBDdjJVdGlscyA9IG5ldyBFZGRzYU1QQ3YyVXRpbHMobW9ja0JpdGdvLCBtb2NrQ29pbik7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgY3JlYXRlIGEgcm91bmQtMSBzaGFyZSBhbmQgZW5jcnlwdGVkIFNKQ0wgc2Vzc2lvbiBwYXlsb2FkJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUoe1xuICAgICAgdHhSZXF1ZXN0LFxuICAgICAgcHJ2OiB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICB9KTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuc2lnbmF0dXJlU2hhcmVSb3VuZDEuZnJvbSwgU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuc2lnbmF0dXJlU2hhcmVSb3VuZDEudG8sIFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyk7XG4gICAgYXNzZXJ0Lm9rKHJlc3VsdC51c2VyR3BnUHViS2V5LmluY2x1ZGVzKCdCRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSycpKTtcbiAgICBhc3NlcnQub2soSlNPTi5wYXJzZShyZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbikuY3QsICdlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uIHNob3VsZCBiZSBhbiBTSkNMIEpTT04gYmxvYicpO1xuICAgIGFzc2VydC5vayhKU09OLnBhcnNlKHJlc3VsdC5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5KS5jdCwgJ2VuY3J5cHRlZFVzZXJHcGdQcnZLZXkgc2hvdWxkIGJlIGFuIFNKQ0wgSlNPTiBibG9iJyk7XG5cbiAgICBjb25zdCBwYXJzZWRTaGFyZSA9IGRlY29kZVdpdGhDb2RlYyhcbiAgICAgIEVkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMUlucHV0LFxuICAgICAgSlNPTi5wYXJzZShyZXN1bHQuc2lnbmF0dXJlU2hhcmVSb3VuZDEuc2hhcmUpLFxuICAgICAgJ0VkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMUlucHV0J1xuICAgICk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZFNoYXJlLnR5cGUsICdyb3VuZDFJbnB1dCcpO1xuICAgIGFzc2VydC5vayhwYXJzZWRTaGFyZS5kYXRhLm1zZzEubWVzc2FnZSwgJ21zZzEubWVzc2FnZSBzaG91bGQgYmUgc2V0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZFNoYXJlLmRhdGEubXNnMS5zaWduYXR1cmUsICdtc2cxLnNpZ25hdHVyZSBzaG91bGQgYmUgc2V0Jyk7XG5cbiAgICBjb25zdCBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uID0gSlNPTi5wYXJzZShyZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbik7XG4gICAgY29uc3QgZW5jcnlwdGVkVXNlckdwZ1BydktleSA9IEpTT04ucGFyc2UocmVzdWx0LmVuY3J5cHRlZFVzZXJHcGdQcnZLZXkpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgIGRlY29kZVVSSUNvbXBvbmVudChlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uLmFkYXRhKSxcbiAgICAgIGBNUFNfRFNHX1NJR05JTkdfUk9VTkQxX1NUQVRFOiR7ZXhwZWN0ZWRBZGF0YX1gLFxuICAgICAgJ3JvdW5kLTEgc2Vzc2lvbiBhZGF0YSBzaG91bGQgYmluZCB0aGUgc2lnbmluZyBjb250ZXh0J1xuICAgICk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgZGVjb2RlVVJJQ29tcG9uZW50KGVuY3J5cHRlZFVzZXJHcGdQcnZLZXkuYWRhdGEpLFxuICAgICAgYE1QU19EU0dfU0lHTklOR19VU0VSX0dQR19LRVk6JHtleHBlY3RlZEFkYXRhfWAsXG4gICAgICAnR1BHIHByaXZhdGUga2V5IGFkYXRhIHNob3VsZCBiaW5kIHRoZSBzaWduaW5nIGNvbnRleHQnXG4gICAgKTtcblxuICAgIGNvbnN0IHNlc3Npb25QYXlsb2FkID0gSlNPTi5wYXJzZShzamNsLmRlY3J5cHQod2FsbGV0UGFzc3BocmFzZSwgcmVzdWx0LmVuY3J5cHRlZFJvdW5kMVNlc3Npb24pKTtcbiAgICBhc3NlcnQub2soc2Vzc2lvblBheWxvYWQuZHNnU2Vzc2lvbiwgJ2RzZ1Nlc3Npb24gc2hvdWxkIGJlIHBlcnNpc3RlZCBmb3Igcm91bmQgMicpO1xuICAgIGFzc2VydC5vayhzZXNzaW9uUGF5bG9hZC51c2VyTXNnUGF5bG9hZCwgJ3VzZXJNc2dQYXlsb2FkIHNob3VsZCBiZSBwZXJzaXN0ZWQgZm9yIHJvdW5kIDInKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB1c2UgdjIgZW5jcnlwdGlvbiB3aGVuIGVuY3J5cHRlZFBydiBpcyBhIHYyIGVudmVsb3BlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGVuY3J5cHQgPSBzaW5vblxuICAgICAgLnN0dWIoKVxuICAgICAgLmNhbGxzRmFrZSgoaW5wdXQ6IHN0cmluZywgYWRhdGE6IHN0cmluZykgPT4gUHJvbWlzZS5yZXNvbHZlKEpTT04uc3RyaW5naWZ5KHsgdjogMiwgaW5wdXQsIGFkYXRhIH0pKSk7XG4gICAgY29uc3QgZGVzdHJveSA9IHNpbm9uLnN0dWIoKTtcbiAgICBjb25zdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbiA9IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh7IGVuY3J5cHQsIGRlc3Ryb3kgfSk7XG4gICAgbW9ja0JpdGdvLmNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uID0gY3JlYXRlRW5jcnlwdGlvblNlc3Npb247XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kMVNoYXJlKHtcbiAgICAgIHR4UmVxdWVzdCxcbiAgICAgIHBydjogdXNlcktleVNoYXJlLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICBlbmNyeXB0ZWRQcnY6IEpTT04uc3RyaW5naWZ5KHsgdjogMiB9KSxcbiAgICB9KTtcblxuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRPbmNlKGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoY3JlYXRlRW5jcnlwdGlvblNlc3Npb24uZ2V0Q2FsbCgwKS5hcmdzWzBdLCB3YWxsZXRQYXNzcGhyYXNlKTtcbiAgICBzaW5vbi5hc3NlcnQubm90Q2FsbGVkKG1vY2tCaXRnby5lbmNyeXB0IGFzIHNpbm9uLlNpbm9uU3R1Yik7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZFR3aWNlKGVuY3J5cHQpO1xuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRPbmNlKGRlc3Ryb3kpO1xuXG4gICAgY29uc3QgZW5jcnlwdGVkUm91bmQxU2Vzc2lvbiA9IEpTT04ucGFyc2UocmVzdWx0LmVuY3J5cHRlZFJvdW5kMVNlc3Npb24pO1xuICAgIGNvbnN0IGVuY3J5cHRlZFVzZXJHcGdQcnZLZXkgPSBKU09OLnBhcnNlKHJlc3VsdC5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5KTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW5jcnlwdGVkUm91bmQxU2Vzc2lvbi52LCAyKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW5jcnlwdGVkUm91bmQxU2Vzc2lvbi5hZGF0YSwgYE1QU19EU0dfU0lHTklOR19ST1VORDFfU1RBVEU6JHtleHBlY3RlZEFkYXRhfWApO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LnYsIDIpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LmFkYXRhLCBgTVBTX0RTR19TSUdOSU5HX1VTRVJfR1BHX0tFWToke2V4cGVjdGVkQWRhdGF9YCk7XG5cbiAgICBjb25zdCBzZXNzaW9uUGF5bG9hZCA9IEpTT04ucGFyc2UoZW5jcnlwdGVkUm91bmQxU2Vzc2lvbi5pbnB1dCk7XG4gICAgYXNzZXJ0Lm9rKHNlc3Npb25QYXlsb2FkLmRzZ1Nlc3Npb24sICdkc2dTZXNzaW9uIHNob3VsZCBiZSBwZXJzaXN0ZWQgZm9yIHJvdW5kIDInKTtcbiAgICBhc3NlcnQub2soc2Vzc2lvblBheWxvYWQudXNlck1zZ1BheWxvYWQsICd1c2VyTXNnUGF5bG9hZCBzaG91bGQgYmUgcGVyc2lzdGVkIGZvciByb3VuZCAyJyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdXNlIFNKQ0wgZW5jcnlwdGlvbiB3aGVuIGVuY3J5cHRlZFBydiBpcyBhIHYxIGJsb2InLCBhc3luYyAoKSA9PiB7XG4gICAgbW9ja0JpdGdvLmNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uID0gc2lub24uc3R1YigpO1xuICAgIGNvbnN0IGVuY3J5cHRlZFBydiA9IHNqY2wuZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUoe1xuICAgICAgdHhSZXF1ZXN0LFxuICAgICAgcHJ2OiB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIGVuY3J5cHRlZFBydixcbiAgICB9KTtcblxuICAgIHNpbm9uLmFzc2VydC5ub3RDYWxsZWQobW9ja0JpdGdvLmNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uIGFzIHNpbm9uLlNpbm9uU3R1Yik7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZFR3aWNlKG1vY2tCaXRnby5lbmNyeXB0IGFzIHNpbm9uLlNpbm9uU3R1Yik7XG4gICAgYXNzZXJ0Lm9rKEpTT04ucGFyc2UocmVzdWx0LmVuY3J5cHRlZFJvdW5kMVNlc3Npb24pLmN0LCAnZW5jcnlwdGVkUm91bmQxU2Vzc2lvbiBzaG91bGQgYmUgYW4gU0pDTCBKU09OIGJsb2InKTtcbiAgICBhc3NlcnQub2soSlNPTi5wYXJzZShyZXN1bHQuZW5jcnlwdGVkVXNlckdwZ1BydktleSkuY3QsICdlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5IHNob3VsZCBiZSBhbiBTSkNMIEpTT04gYmxvYicpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHByb3BhZ2F0ZSB0aGUgdHgtb25seSBndWFyZCB3aGVuIHRyYW5zYWN0aW9ucyBhcmUgbWlzc2luZycsIGFzeW5jICgpID0+IHtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUoe1xuICAgICAgICAgIHR4UmVxdWVzdDogeyAuLi50eFJlcXVlc3QsIHRyYW5zYWN0aW9uczogdW5kZWZpbmVkIH0gYXMgdW5rbm93biBhcyBUeFJlcXVlc3QsXG4gICAgICAgICAgcHJ2OiB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIH0pLFxuICAgICAgL1VuYWJsZSB0byBmaW5kIHRyYW5zYWN0aW9ucyBpbiB0eFJlcXVlc3QvXG4gICAgKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ0VkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lS2V5R2VuUm91bmQxU2hhcmUnLCAoKSA9PiB7XG4gIGxldCBlZGRzYU1QQ3YyVXRpbHM6IEVkZHNhTVBDdjJVdGlscztcbiAgbGV0IG1vY2tCaXRnbzogQml0R29CYXNlO1xuICBsZXQgdXNlckdwZ0tleVBhaXI6IHBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuICBsZXQgYmFja3VwR3BnS2V5UGFpcjogcGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gIGxldCBiaXRnb0dwZ0tleVBhaXI6IHBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuXG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuXG4gIGJlZm9yZSgnZ2VuZXJhdGUgR1BHIGtleSBwYWlycycsIGFzeW5jICgpID0+IHtcbiAgICB1c2VyR3BnS2V5UGFpciA9IGF3YWl0IGdlbmVyYXRlR1BHS2V5UGFpcignZWQyNTUxOScpO1xuICAgIGJhY2t1cEdwZ0tleVBhaXIgPSBhd2FpdCBnZW5lcmF0ZUdQR0tleVBhaXIoJ2VkMjU1MTknKTtcbiAgICBiaXRnb0dwZ0tleVBhaXIgPSBhd2FpdCBnZW5lcmF0ZUdQR0tleVBhaXIoJ2VkMjU1MTknKTtcbiAgfSk7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgY29uc3Qgc2pjbEVuY3J5cHQgPSAocGFyYW1zOiB7IHBhc3N3b3JkOiBzdHJpbmc7IGlucHV0OiBzdHJpbmc7IGFkYXRhPzogc3RyaW5nIH0pID0+IHtcbiAgICAgIGNvbnN0IHNhbHQgPSByYW5kb21CeXRlcyg4KTtcbiAgICAgIGNvbnN0IGl2ID0gcmFuZG9tQnl0ZXMoMTYpO1xuICAgICAgcmV0dXJuIHNqY2wuZW5jcnlwdChwYXJhbXMucGFzc3dvcmQsIHBhcmFtcy5pbnB1dCwge1xuICAgICAgICBzYWx0OiBbYnl0ZXNUb1dvcmQoc2FsdC5zdWJhcnJheSgwLCA0KSksIGJ5dGVzVG9Xb3JkKHNhbHQuc3ViYXJyYXkoNCkpXSxcbiAgICAgICAgaXY6IFtcbiAgICAgICAgICBieXRlc1RvV29yZChpdi5zdWJhcnJheSgwLCA0KSksXG4gICAgICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoNCwgOCkpLFxuICAgICAgICAgIGJ5dGVzVG9Xb3JkKGl2LnN1YmFycmF5KDgsIDEyKSksXG4gICAgICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoMTIsIDE2KSksXG4gICAgICAgIF0sXG4gICAgICAgIGFkYXRhOiBwYXJhbXMuYWRhdGEsXG4gICAgICB9KTtcbiAgICB9O1xuICAgIG1vY2tCaXRnbyA9IHtcbiAgICAgIGVuY3J5cHQ6IHNpbm9uLnN0dWIoKS5jYWxsc0Zha2Uoc2pjbEVuY3J5cHQpLFxuICAgICAgZW5jcnlwdEFzeW5jOiBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKGFzeW5jIChwYXJhbXMpID0+IHNqY2xFbmNyeXB0KHBhcmFtcykpLFxuICAgICAgZGVjcnlwdDogc2lub24uc3R1YigpLmNhbGxzRmFrZSgocGFyYW1zKSA9PiBzamNsLmRlY3J5cHQocGFyYW1zLnBhc3N3b3JkLCBwYXJhbXMuaW5wdXQpKSxcbiAgICAgIGRlY3J5cHRBc3luYzogc2lub24uc3R1YigpLmNhbGxzRmFrZShhc3luYyAocGFyYW1zKSA9PiBzamNsLmRlY3J5cHQocGFyYW1zLnBhc3N3b3JkLCBwYXJhbXMuaW5wdXQpKSxcbiAgICAgIGdldEVudjogc2lub24uc3R1YigpLnJldHVybnMoJ21vY2snKSxcbiAgICB9IGFzIHVua25vd24gYXMgQml0R29CYXNlO1xuXG4gICAgY29uc3QgbW9ja0NvaW4gPSB7XG4gICAgICBnZXRNUENBbGdvcml0aG06IHNpbm9uLnN0dWIoKS5yZXR1cm5zKCdlZGRzYScpLFxuICAgIH0gYXMgdW5rbm93biBhcyBJQmFzZUNvaW47XG5cbiAgICBlZGRzYU1QQ3YyVXRpbHMgPSBuZXcgRWRkc2FNUEN2MlV0aWxzKG1vY2tCaXRnbywgbW9ja0NvaW4pO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHByb2R1Y2UgdmFsaWQgc2lnbmVkTXNnMSBhbmQgZW5jcnlwdGVkIHJvdW5kLTEgc2Vzc2lvbicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5ID0gc2pjbC5lbmNyeXB0KHdhbGxldFBhc3NwaHJhc2UsIHVzZXJHcGdLZXlQYWlyLnByaXZhdGVLZXkpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVLZXlHZW5Sb3VuZDFTaGFyZSh7XG4gICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgIGJpdGdvR3BnUHViS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgY291bnRlclBhcnR5R3BnUHViS2V5OiBiYWNrdXBHcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICB9KTtcblxuICAgIGFzc2VydC5vayhyZXN1bHQuc2lnbmVkTXNnMS5tZXNzYWdlLCAnc2lnbmVkTXNnMS5tZXNzYWdlIHNob3VsZCBiZSBzZXQnKTtcbiAgICBhc3NlcnQub2soXG4gICAgICByZXN1bHQuc2lnbmVkTXNnMS5zaWduYXR1cmUuaW5jbHVkZXMoJ0JFR0lOIFBHUCBTSUdOQVRVUkUnKSxcbiAgICAgICdzaWduZWRNc2cxLnNpZ25hdHVyZSBzaG91bGQgYmUgUEdQIGFybW9yZWQnXG4gICAgKTtcbiAgICBhc3NlcnQub2soSlNPTi5wYXJzZShyZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbikuY3QsICdlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uIHNob3VsZCBiZSBhbiBTSkNMIEpTT04gYmxvYicpO1xuICB9KTtcblxuICBpdCgnZW5jcnlwdGVkUm91bmQxU2Vzc2lvbiBzaG91bGQgb25seSBiZSBkZWNyeXB0YWJsZSB3aXRoIGNvcnJlY3Qgd2FsbGV0UGFzc3BocmFzZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5ID0gc2pjbC5lbmNyeXB0KHdhbGxldFBhc3NwaHJhc2UsIHVzZXJHcGdLZXlQYWlyLnByaXZhdGVLZXkpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVLZXlHZW5Sb3VuZDFTaGFyZSh7XG4gICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgIGJpdGdvR3BnUHViS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgY291bnRlclBhcnR5R3BnUHViS2V5OiBiYWNrdXBHcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlY3J5cHRlZCA9IHNqY2wuZGVjcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCByZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbik7XG4gICAgY29uc3Qgc2Vzc2lvbiA9IEpTT04ucGFyc2UoZGVjcnlwdGVkKTtcbiAgICBhc3NlcnQub2soc2Vzc2lvbi5ka2dTZXNzaW9uLCAnZGtnU2Vzc2lvbiBzaG91bGQgYmUgcGVyc2lzdGVkJyk7XG4gICAgYXNzZXJ0Lm9rKHNlc3Npb24ub3duTXNnUGF5bG9hZCwgJ293bk1zZ1BheWxvYWQgc2hvdWxkIGJlIHBlcnNpc3RlZCcpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eXBlb2Ygc2Vzc2lvbi5vd25Nc2dGcm9tLCAnbnVtYmVyJywgJ293bk1zZ0Zyb20gc2hvdWxkIGJlIGEgbnVtYmVyJyk7XG5cbiAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgKCkgPT4gc2pjbC5kZWNyeXB0KCd3cm9uZ3Bhc3NwaHJhc2UnLCByZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbiksXG4gICAgICAnc2hvdWxkIHRocm93IG9uIHdyb25nIHBhc3NwaHJhc2UnXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZXN0b3JlIERLRyBzZXNzaW9uIGFuZCBoYW5kbGUgcm91bmQtMiBtZXNzYWdlcyBhZnRlciByb3VuZCAxJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGVuY3J5cHRlZFVzZXJHcGdQcnZLZXkgPSBzamNsLmVuY3J5cHQod2FsbGV0UGFzc3BocmFzZSwgdXNlckdwZ0tleVBhaXIucHJpdmF0ZUtleSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZUtleUdlblJvdW5kMVNoYXJlKHtcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgYml0Z29HcGdQdWJLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBjb3VudGVyUGFydHlHcGdQdWJLZXk6IGJhY2t1cEdwZ0tleVBhaXIucHVibGljS2V5LFxuICAgIH0pO1xuXG4gICAgY29uc3QgZGVjcnlwdGVkID0gc2pjbC5kZWNyeXB0KHdhbGxldFBhc3NwaHJhc2UsIHJlc3VsdC5lbmNyeXB0ZWRSb3VuZDFTZXNzaW9uKTtcbiAgICBjb25zdCB7IGRrZ1Nlc3Npb24sIG93bk1zZ1BheWxvYWQsIG93bk1zZ0Zyb20gfSA9IEpTT04ucGFyc2UoZGVjcnlwdGVkKSBhcyB7XG4gICAgICBka2dTZXNzaW9uOiBzdHJpbmc7XG4gICAgICBvd25Nc2dQYXlsb2FkOiBzdHJpbmc7XG4gICAgICBvd25Nc2dGcm9tOiBudW1iZXI7XG4gICAgfTtcblxuICAgIGNvbnN0IHJlc3RvcmVkRGtnID0gbmV3IEVkZHNhTVBTRGtnLkRLRygzLCAyLCBNUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuICAgIGF3YWl0IHJlc3RvcmVkRGtnLnJlc3RvcmVTZXNzaW9uKGRrZ1Nlc3Npb24pO1xuXG4gICAgY29uc3Qgb3duTXNnMTogTVBTVHlwZXMuRGVzZXJpYWxpemVkTWVzc2FnZSA9IHtcbiAgICAgIGZyb206IG93bk1zZ0Zyb20sXG4gICAgICBwYXlsb2FkOiBuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbShvd25Nc2dQYXlsb2FkLCAnYmFzZTY0JykpLFxuICAgIH07XG4gICAgYXNzZXJ0Lm9rKG93bk1zZzEucGF5bG9hZC5sZW5ndGggPiAwLCAncmVzdG9yZWQgcGF5bG9hZCBzaG91bGQgYmUgbm9uLWVtcHR5Jyk7XG5cbiAgICBjb25zdCB1c2VyR3BnS2V5ID0gYXdhaXQgcGdwLnJlYWRLZXkoeyBhcm1vcmVkS2V5OiB1c2VyR3BnS2V5UGFpci5wdWJsaWNLZXkgfSk7XG4gICAgY29uc3QgcmF3Qnl0ZXMgPSBhd2FpdCBNUFNDb21tcy52ZXJpZnlNcHNNZXNzYWdlKHJlc3VsdC5zaWduZWRNc2cxLCB1c2VyR3BnS2V5KTtcbiAgICBhc3NlcnQub2socmF3Qnl0ZXMubGVuZ3RoID4gMCwgJ3NpZ25lZE1zZzEgc2hvdWxkIHZlcmlmeSBhZ2FpbnN0IHVzZXIgR1BHIGtleScpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCBpbnZhbGlkIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXknLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZUtleUdlblJvdW5kMVNoYXJlKHtcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHNqY2wuZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCAnbm90LWEtZ3BnLWtleScpLFxuICAgICAgICAgIGJpdGdvR3BnUHViS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgICAgIGNvdW50ZXJQYXJ0eUdwZ1B1YktleTogYmFja3VwR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICAgIH0pLFxuICAgICAgJ3Nob3VsZCB0aHJvdyB3aGVuIEdQRyBrZXkgY2Fubm90IGJlIHBhcnNlZCdcbiAgICApO1xuICB9KTtcblxuICBpdCgnVVNFUiBhbmQgQkFDS1VQIHBhcnR5SWQgcHJvZHVjZSBkaWZmZXJlbnQgZW5jcnlwdGVkIHNlc3Npb24gc3RhdGUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdXNlckVuY3J5cHRlZEdwZ1BydktleSA9IHNqY2wuZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCB1c2VyR3BnS2V5UGFpci5wcml2YXRlS2V5KTtcblxuICAgIGNvbnN0IHVzZXJSZXN1bHQgPSBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZUtleUdlblJvdW5kMVNoYXJlKHtcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiB1c2VyRW5jcnlwdGVkR3BnUHJ2S2V5LFxuICAgICAgYml0Z29HcGdQdWJLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBjb3VudGVyUGFydHlHcGdQdWJLZXk6IGJhY2t1cEdwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgcGFydHlJZDogTVBDdjJQYXJ0aWVzRW51bS5VU0VSLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYmFja3VwRW5jcnlwdGVkR3BnUHJ2S2V5MiA9IHNqY2wuZW5jcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCBiYWNrdXBHcGdLZXlQYWlyLnByaXZhdGVLZXkpO1xuICAgIGNvbnN0IGJhY2t1cFJlc3VsdCA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lS2V5R2VuUm91bmQxU2hhcmUoe1xuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IGJhY2t1cEVuY3J5cHRlZEdwZ1BydktleTIsXG4gICAgICBiaXRnb0dwZ1B1YktleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgIGNvdW50ZXJQYXJ0eUdwZ1B1YktleTogdXNlckdwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgcGFydHlJZDogTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVAsXG4gICAgfSk7XG5cbiAgICBjb25zdCB1c2VyU2Vzc2lvbiA9IEpTT04ucGFyc2Uoc2pjbC5kZWNyeXB0KHdhbGxldFBhc3NwaHJhc2UsIHVzZXJSZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbikpO1xuICAgIGNvbnN0IGJhY2t1cFNlc3Npb24gPSBKU09OLnBhcnNlKHNqY2wuZGVjcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCBiYWNrdXBSZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbikpO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHVzZXJTZXNzaW9uLm93bk1zZ0Zyb20sIE1QQ3YyUGFydGllc0VudW0uVVNFUik7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJhY2t1cFNlc3Npb24ub3duTXNnRnJvbSwgTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVApO1xuICAgIGFzc2VydC5ub3RTdHJpY3RFcXVhbCh1c2VyU2Vzc2lvbi5ka2dTZXNzaW9uLCBiYWNrdXBTZXNzaW9uLmRrZ1Nlc3Npb24sICdTZXNzaW9ucyBzaG91bGQgZGlmZmVyIGJldHdlZW4gcGFydGllcycpO1xuXG4gICAgLy8gU2Vzc2lvbnMgZW5jcnlwdGVkIHdpdGggcGFydHktYm91bmQgYWRhdGEg4oCUIHRhbXBlcmVkIGFkYXRhIGZhaWxzIENDTSB0YWcgY2hlY2tcbiAgICBjb25zdCB0YW1wZXJlZFNlc3Npb24gPSAoKCkgPT4ge1xuICAgICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZSh1c2VyUmVzdWx0LmVuY3J5cHRlZFJvdW5kMVNlc3Npb24pO1xuICAgICAgcGFyc2VkLmFkYXRhID0gZW5jb2RlVVJJQ29tcG9uZW50KGBNUFNfREtHX0tFWUdFTl9ST1VORDFfU1RBVEU6JHtNUEN2MlBhcnRpZXNFbnVtLkJBQ0tVUH1gKTtcbiAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShwYXJzZWQpO1xuICAgIH0pKCk7XG4gICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICgpID0+IHNqY2wuZGVjcnlwdCh3YWxsZXRQYXNzcGhyYXNlLCB0YW1wZXJlZFNlc3Npb24pLFxuICAgICAgJ3Nob3VsZCBmYWlsIHRvIGRlY3J5cHQgd2l0aCB3cm9uZyBwYXJ0eSBhZGF0YSdcbiAgICApO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnRWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDJTaGFyZScsICgpID0+IHtcbiAgbGV0IGVkZHNhTVBDdjJVdGlsczogRWRkc2FNUEN2MlV0aWxzO1xuICBsZXQgbW9ja0JpdGdvOiBCaXRHb0Jhc2U7XG4gIGxldCB1c2VyS2V5U2hhcmU6IEJ1ZmZlcjtcbiAgbGV0IGJpdGdvS2V5U2hhcmU6IEJ1ZmZlcjtcbiAgbGV0IGJpdGdvR3BnS2V5UGFpcjogcGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gIGxldCBiaXRnb0dwZ1ByaXZLZXk6IHBncC5Qcml2YXRlS2V5O1xuXG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuICBjb25zdCBzaWduYWJsZUhleCA9ICdkZWFkYmVlZic7XG4gIGNvbnN0IGRlcml2YXRpb25QYXRoID0gJ20vMC8wJztcbiAgY29uc3QgZXhwZWN0ZWRBZGF0YSA9IGAke3NpZ25hYmxlSGV4fToke2Rlcml2YXRpb25QYXRofWA7XG5cbiAgY29uc3QgYmFzZVR4UmVxdWVzdDogVHhSZXF1ZXN0ID0ge1xuICAgIHR4UmVxdWVzdElkOiAndHhyZXEtZWRkc2Etcm91bmQyJyxcbiAgICB3YWxsZXRJZDogJ3dhbGxldC1lZGRzYS1yb3VuZDInLFxuICAgIGVudGVycHJpc2VJZDogJ2VudGVycHJpc2UtZWRkc2Etcm91bmQyJyxcbiAgICBhcGlWZXJzaW9uOiAnZnVsbCcsXG4gICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICB7XG4gICAgICAgIHVuc2lnbmVkVHg6IHtcbiAgICAgICAgICBzaWduYWJsZUhleCxcbiAgICAgICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgICBzZXJpYWxpemVkVHhIZXg6IHNpZ25hYmxlSGV4LFxuICAgICAgICB9LFxuICAgICAgICBzaWduYXR1cmVTaGFyZXM6IFtdLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGludGVudDogeyBpbnRlbnRUeXBlOiAncGF5bWVudCcgfSxcbiAgICB1bnNpZ25lZFR4czogW10sXG4gIH0gYXMgdW5rbm93biBhcyBUeFJlcXVlc3Q7XG5cbiAgYmVmb3JlKCdnZW5lcmF0ZSBFZERTQSBrZXkgc2hhcmVzIGFuZCBHUEcga2V5cycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZywgLCBiaXRnb0RrZ10gPSBhd2FpdCBNUFNVdGlsLmdlbmVyYXRlRWREc2FES0dLZXlTaGFyZXMoKTtcbiAgICB1c2VyS2V5U2hhcmUgPSB1c2VyRGtnLmdldEtleVNoYXJlKCk7XG4gICAgYml0Z29LZXlTaGFyZSA9IGJpdGdvRGtnLmdldEtleVNoYXJlKCk7XG5cbiAgICBiaXRnb0dwZ0tleVBhaXIgPSBhd2FpdCBnZW5lcmF0ZUdQR0tleVBhaXIoJ2VkMjU1MTknKTtcbiAgICBiaXRnb0dwZ1ByaXZLZXkgPSBhd2FpdCBwZ3AucmVhZFByaXZhdGVLZXkoeyBhcm1vcmVkS2V5OiBiaXRnb0dwZ0tleVBhaXIucHJpdmF0ZUtleSB9KTtcbiAgfSk7XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgbW9ja0JpdGdvID0ge1xuICAgICAgZW5jcnlwdDogc2lub24uc3R1YigpLmNhbGxzRmFrZShhc3luYyAocGFyYW1zKSA9PiB7XG4gICAgICAgIGNvbnN0IHNhbHQgPSByYW5kb21CeXRlcyg4KTtcbiAgICAgICAgY29uc3QgaXYgPSByYW5kb21CeXRlcygxNik7XG4gICAgICAgIHJldHVybiBzamNsLmVuY3J5cHQocGFyYW1zLnBhc3N3b3JkLCBwYXJhbXMuaW5wdXQsIHtcbiAgICAgICAgICBzYWx0OiBbYnl0ZXNUb1dvcmQoc2FsdC5zdWJhcnJheSgwLCA0KSksIGJ5dGVzVG9Xb3JkKHNhbHQuc3ViYXJyYXkoNCkpXSxcbiAgICAgICAgICBpdjogW1xuICAgICAgICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoMCwgNCkpLFxuICAgICAgICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoNCwgOCkpLFxuICAgICAgICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoOCwgMTIpKSxcbiAgICAgICAgICAgIGJ5dGVzVG9Xb3JkKGl2LnN1YmFycmF5KDEyLCAxNikpLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgYWRhdGE6IHBhcmFtcy5hZGF0YSxcbiAgICAgICAgfSk7XG4gICAgICB9KSxcbiAgICAgIGRlY3J5cHQ6IHNpbm9uLnN0dWIoKS5jYWxsc0Zha2UoYXN5bmMgKHBhcmFtcykgPT4gc2pjbC5kZWNyeXB0KHBhcmFtcy5wYXNzd29yZCwgcGFyYW1zLmlucHV0KSksXG4gICAgfSBhcyB1bmtub3duIGFzIEJpdEdvQmFzZTtcblxuICAgIGNvbnN0IG1vY2tDb2luID0ge1xuICAgICAgZ2V0TVBDQWxnb3JpdGhtOiBzaW5vbi5zdHViKCkucmV0dXJucygnZWRkc2EnKSxcbiAgICB9IGFzIHVua25vd24gYXMgSUJhc2VDb2luO1xuXG4gICAgZWRkc2FNUEN2MlV0aWxzID0gbmV3IEVkZHNhTVBDdjJVdGlscyhtb2NrQml0Z28sIG1vY2tDb2luKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBjcmVhdGUgYSByb3VuZC0yIHNoYXJlIGZyb20gb2ZmbGluZSByb3VuZCAxJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJvdW5kMSA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUoe1xuICAgICAgdHhSZXF1ZXN0OiBiYXNlVHhSZXF1ZXN0LFxuICAgICAgcHJ2OiB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IG1lc3NhZ2VCdWZmZXIgPSBCdWZmZXIuZnJvbShzaWduYWJsZUhleCwgJ2hleCcpO1xuICAgIGNvbnN0IGJpdGdvRHNnID0gbmV3IEVkZHNhTVBTRHNnLkRTRyhNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBhd2FpdCBiaXRnb0RzZy5pbml0RHNnKGJpdGdvS2V5U2hhcmUsIG1lc3NhZ2VCdWZmZXIsIGRlcml2YXRpb25QYXRoLCBNUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuXG4gICAgY29uc3QgdHhSZXF1ZXN0Um91bmQxID0gYXdhaXQgc2lnbkJpdGdvRWRkc2FSb3VuZDEoXG4gICAgICBiaXRnb0RzZyxcbiAgICAgIGNsb25lVHhSZXF1ZXN0V2l0aEVtcHR5U2lnbmF0dXJlU2hhcmVzKGJhc2VUeFJlcXVlc3QpLFxuICAgICAgcm91bmQxLnNpZ25hdHVyZVNoYXJlUm91bmQxLFxuICAgICAgcm91bmQxLnVzZXJHcGdQdWJLZXksXG4gICAgICBiaXRnb0dwZ1ByaXZLZXlcbiAgICApO1xuXG4gICAgY29uc3Qgcm91bmQyID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDJTaGFyZSh7XG4gICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdFJvdW5kMSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHJvdW5kMS5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgZW5jcnlwdGVkUm91bmQxU2Vzc2lvbjogcm91bmQxLmVuY3J5cHRlZFJvdW5kMVNlc3Npb24sXG4gICAgfSk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocm91bmQyLnNpZ25hdHVyZVNoYXJlUm91bmQyLmZyb20sIFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocm91bmQyLnNpZ25hdHVyZVNoYXJlUm91bmQyLnRvLCBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08pO1xuXG4gICAgY29uc3QgcGFyc2VkU2hhcmUgPSBkZWNvZGVXaXRoQ29kZWMoXG4gICAgICBFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJJbnB1dCxcbiAgICAgIEpTT04ucGFyc2Uocm91bmQyLnNpZ25hdHVyZVNoYXJlUm91bmQyLnNoYXJlKSxcbiAgICAgICdFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJJbnB1dCdcbiAgICApO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChwYXJzZWRTaGFyZS50eXBlLCAncm91bmQySW5wdXQnKTtcbiAgICBhc3NlcnQub2socGFyc2VkU2hhcmUuZGF0YS5tc2cyLm1lc3NhZ2UsICdtc2cyLm1lc3NhZ2Ugc2hvdWxkIGJlIHNldCcpO1xuICAgIGFzc2VydC5vayhwYXJzZWRTaGFyZS5kYXRhLm1zZzIuc2lnbmF0dXJlLCAnbXNnMi5zaWduYXR1cmUgc2hvdWxkIGJlIHNldCcpO1xuXG4gICAgY29uc3QgZW5jcnlwdGVkUm91bmQyU2Vzc2lvbiA9IEpTT04ucGFyc2Uocm91bmQyLmVuY3J5cHRlZFJvdW5kMlNlc3Npb24pO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgIGRlY29kZVVSSUNvbXBvbmVudChlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uLmFkYXRhKSxcbiAgICAgIGBNUFNfRFNHX1NJR05JTkdfUk9VTkQyX1NUQVRFOiR7ZXhwZWN0ZWRBZGF0YX1gXG4gICAgKTtcblxuICAgIGNvbnN0IHNlc3Npb25QYXlsb2FkID0gSlNPTi5wYXJzZShzamNsLmRlY3J5cHQod2FsbGV0UGFzc3BocmFzZSwgcm91bmQyLmVuY3J5cHRlZFJvdW5kMlNlc3Npb24pKTtcbiAgICBhc3NlcnQub2soc2Vzc2lvblBheWxvYWQuZHNnU2Vzc2lvbiwgJ2RzZ1Nlc3Npb24gc2hvdWxkIGJlIHBlcnNpc3RlZCBmb3Igcm91bmQgMycpO1xuICAgIGFzc2VydC5vayhzZXNzaW9uUGF5bG9hZC51c2VyTXNnUGF5bG9hZCwgJ3VzZXJNc2dQYXlsb2FkIHNob3VsZCBiZSBwZXJzaXN0ZWQgZm9yIHJvdW5kIDMnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB1c2UgdjIgZGVjcnlwdGlvbiB3aGVuIGVuY3J5cHRlZFJvdW5kMVNlc3Npb24gaXMgYSB2MiBlbnZlbG9wZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBlbmNyeXB0ID0gc2lub25cbiAgICAgIC5zdHViKClcbiAgICAgIC5jYWxsc0Zha2UoKGlucHV0OiBzdHJpbmcsIGFkYXRhOiBzdHJpbmcpID0+IFByb21pc2UucmVzb2x2ZShKU09OLnN0cmluZ2lmeSh7IHY6IDIsIGlucHV0LCBhZGF0YSB9KSkpO1xuICAgIGNvbnN0IGRlc3Ryb3kgPSBzaW5vbi5zdHViKCk7XG4gICAgY29uc3QgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24gPSBzaW5vbi5zdHViKCkucmVzb2x2ZXMoeyBlbmNyeXB0LCBkZXN0cm95IH0pO1xuICAgIG1vY2tCaXRnby5jcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbiA9IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uO1xuXG4gICAgY29uc3Qgcm91bmQxID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDFTaGFyZSh7XG4gICAgICB0eFJlcXVlc3Q6IGJhc2VUeFJlcXVlc3QsXG4gICAgICBwcnY6IHVzZXJLZXlTaGFyZS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgZW5jcnlwdGVkUHJ2OiBKU09OLnN0cmluZ2lmeSh7IHY6IDIgfSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCBiaXRnb0RzZyA9IG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5CSVRHTyk7XG4gICAgYXdhaXQgYml0Z29Ec2cuaW5pdERzZyhiaXRnb0tleVNoYXJlLCBtZXNzYWdlQnVmZmVyLCBkZXJpdmF0aW9uUGF0aCwgTVBDdjJQYXJ0aWVzRW51bS5VU0VSKTtcblxuICAgIGNvbnN0IHR4UmVxdWVzdFJvdW5kMSA9IGF3YWl0IHNpZ25CaXRnb0VkZHNhUm91bmQxKFxuICAgICAgYml0Z29Ec2csXG4gICAgICBjbG9uZVR4UmVxdWVzdFdpdGhFbXB0eVNpZ25hdHVyZVNoYXJlcyhiYXNlVHhSZXF1ZXN0KSxcbiAgICAgIHJvdW5kMS5zaWduYXR1cmVTaGFyZVJvdW5kMSxcbiAgICAgIHJvdW5kMS51c2VyR3BnUHViS2V5LFxuICAgICAgYml0Z29HcGdQcml2S2V5XG4gICAgKTtcblxuICAgIGNvbnN0IGRlY3J5cHQgPSBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKGFzeW5jIChwYXJhbXM6IHsgaW5wdXQ6IHN0cmluZyB9KSA9PiB7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IEpTT04ucGFyc2UocGFyYW1zLmlucHV0KTtcbiAgICAgIHJldHVybiBlbnZlbG9wZS5pbnB1dDtcbiAgICB9KTtcbiAgICBtb2NrQml0Z28uZGVjcnlwdCA9IGRlY3J5cHQ7XG5cbiAgICBjb25zdCByb3VuZDIgPSBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kMlNoYXJlKHtcbiAgICAgIHR4UmVxdWVzdDogdHhSZXF1ZXN0Um91bmQxLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleTogcm91bmQxLmVuY3J5cHRlZFVzZXJHcGdQcnZLZXksXG4gICAgICBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uOiByb3VuZDEuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbixcbiAgICB9KTtcblxuICAgIHNpbm9uLmFzc2VydC5jYWxsZWQobW9ja0JpdGdvLmRlY3J5cHQgYXMgc2lub24uU2lub25TdHViKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocm91bmQyLnNpZ25hdHVyZVNoYXJlUm91bmQyLmZyb20sIFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSKTtcblxuICAgIGNvbnN0IGVuY3J5cHRlZFJvdW5kMlNlc3Npb24gPSBKU09OLnBhcnNlKHJvdW5kMi5lbmNyeXB0ZWRSb3VuZDJTZXNzaW9uKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW5jcnlwdGVkUm91bmQyU2Vzc2lvbi52LCAyKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW5jcnlwdGVkUm91bmQyU2Vzc2lvbi5hZGF0YSwgYE1QU19EU0dfU0lHTklOR19ST1VORDJfU1RBVEU6JHtleHBlY3RlZEFkYXRhfWApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCB0YW1wZXJlZCBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uIGFkYXRhJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG90aGVyVHhSZXF1ZXN0OiBUeFJlcXVlc3QgPSB7XG4gICAgICAuLi5iYXNlVHhSZXF1ZXN0LFxuICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICB1bnNpZ25lZFR4OiB7XG4gICAgICAgICAgICBzaWduYWJsZUhleDogJ2NhZmViYWJlJyxcbiAgICAgICAgICAgIGRlcml2YXRpb25QYXRoOiAnbS8xLzInLFxuICAgICAgICAgICAgc2VyaWFsaXplZFR4SGV4OiAnY2FmZWJhYmUnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSBhcyB1bmtub3duIGFzIFR4UmVxdWVzdDtcblxuICAgIGNvbnN0IHJvdW5kMU90aGVyID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDFTaGFyZSh7XG4gICAgICB0eFJlcXVlc3Q6IG90aGVyVHhSZXF1ZXN0LFxuICAgICAgcHJ2OiB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJvdW5kMSA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUoe1xuICAgICAgdHhSZXF1ZXN0OiBiYXNlVHhSZXF1ZXN0LFxuICAgICAgcHJ2OiB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IG1lc3NhZ2VCdWZmZXIgPSBCdWZmZXIuZnJvbShzaWduYWJsZUhleCwgJ2hleCcpO1xuICAgIGNvbnN0IGJpdGdvRHNnID0gbmV3IEVkZHNhTVBTRHNnLkRTRyhNUEN2MlBhcnRpZXNFbnVtLkJJVEdPKTtcbiAgICBhd2FpdCBiaXRnb0RzZy5pbml0RHNnKGJpdGdvS2V5U2hhcmUsIG1lc3NhZ2VCdWZmZXIsIGRlcml2YXRpb25QYXRoLCBNUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuXG4gICAgY29uc3QgdHhSZXF1ZXN0Um91bmQxID0gYXdhaXQgc2lnbkJpdGdvRWRkc2FSb3VuZDEoXG4gICAgICBiaXRnb0RzZyxcbiAgICAgIGNsb25lVHhSZXF1ZXN0V2l0aEVtcHR5U2lnbmF0dXJlU2hhcmVzKGJhc2VUeFJlcXVlc3QpLFxuICAgICAgcm91bmQxLnNpZ25hdHVyZVNoYXJlUm91bmQxLFxuICAgICAgcm91bmQxLnVzZXJHcGdQdWJLZXksXG4gICAgICBiaXRnb0dwZ1ByaXZLZXlcbiAgICApO1xuXG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kMlNoYXJlKHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdFJvdW5kMSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHJvdW5kMS5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICAgIGVuY3J5cHRlZFJvdW5kMVNlc3Npb246IHJvdW5kMU90aGVyLmVuY3J5cHRlZFJvdW5kMVNlc3Npb24sXG4gICAgICAgIH0pLFxuICAgICAgL0FkYXRhIGRvZXMgbm90IG1hdGNoIGN5cGhlcnRleHQgYWRhdGEvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWplY3QgdGFtcGVyZWQgZW5jcnlwdGVkVXNlckdwZ1BydktleSBhZGF0YScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvdGhlclR4UmVxdWVzdDogVHhSZXF1ZXN0ID0ge1xuICAgICAgLi4uYmFzZVR4UmVxdWVzdCxcbiAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgc2lnbmFibGVIZXg6ICdjYWZlYmFiZScsXG4gICAgICAgICAgICBkZXJpdmF0aW9uUGF0aDogJ20vMS8yJyxcbiAgICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogJ2NhZmViYWJlJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogW10sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0gYXMgdW5rbm93biBhcyBUeFJlcXVlc3Q7XG5cbiAgICBjb25zdCByb3VuZDFPdGhlciA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUoe1xuICAgICAgdHhSZXF1ZXN0OiBvdGhlclR4UmVxdWVzdCxcbiAgICAgIHBydjogdXNlcktleVNoYXJlLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgfSk7XG5cbiAgICBjb25zdCByb3VuZDEgPSBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kMVNoYXJlKHtcbiAgICAgIHR4UmVxdWVzdDogYmFzZVR4UmVxdWVzdCxcbiAgICAgIHBydjogdXNlcktleVNoYXJlLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgfSk7XG5cbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyID0gQnVmZmVyLmZyb20oc2lnbmFibGVIZXgsICdoZXgnKTtcbiAgICBjb25zdCBiaXRnb0RzZyA9IG5ldyBFZGRzYU1QU0RzZy5EU0coTVBDdjJQYXJ0aWVzRW51bS5CSVRHTyk7XG4gICAgYXdhaXQgYml0Z29Ec2cuaW5pdERzZyhiaXRnb0tleVNoYXJlLCBtZXNzYWdlQnVmZmVyLCBkZXJpdmF0aW9uUGF0aCwgTVBDdjJQYXJ0aWVzRW51bS5VU0VSKTtcblxuICAgIGNvbnN0IHR4UmVxdWVzdFJvdW5kMSA9IGF3YWl0IHNpZ25CaXRnb0VkZHNhUm91bmQxKFxuICAgICAgYml0Z29Ec2csXG4gICAgICBjbG9uZVR4UmVxdWVzdFdpdGhFbXB0eVNpZ25hdHVyZVNoYXJlcyhiYXNlVHhSZXF1ZXN0KSxcbiAgICAgIHJvdW5kMS5zaWduYXR1cmVTaGFyZVJvdW5kMSxcbiAgICAgIHJvdW5kMS51c2VyR3BnUHViS2V5LFxuICAgICAgYml0Z29HcGdQcml2S2V5XG4gICAgKTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDJTaGFyZSh7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RSb3VuZDEsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiByb3VuZDFPdGhlci5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICAgIGVuY3J5cHRlZFJvdW5kMVNlc3Npb246IHJvdW5kMS5lbmNyeXB0ZWRSb3VuZDFTZXNzaW9uLFxuICAgICAgICB9KSxcbiAgICAgIC9BZGF0YSBkb2VzIG5vdCBtYXRjaCBjeXBoZXJ0ZXh0IGFkYXRhL1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IHdoZW4gQml0R28gc2lnbmF0dXJlIHNoYXJlIGlzIG1pc3NpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgcm91bmQxID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDFTaGFyZSh7XG4gICAgICB0eFJlcXVlc3Q6IGJhc2VUeFJlcXVlc3QsXG4gICAgICBwcnY6IHVzZXJLZXlTaGFyZS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYmFzZVRyYW5zYWN0aW9uID0gYXNzZXJ0U2luZ2xlVHJhbnNhY3Rpb24oYmFzZVR4UmVxdWVzdCk7XG4gICAgY29uc3QgdHhSZXF1ZXN0Tm9CaXRnb1NoYXJlOiBUeFJlcXVlc3QgPSB7XG4gICAgICAuLi5iYXNlVHhSZXF1ZXN0LFxuICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICAuLi5iYXNlVHJhbnNhY3Rpb24sXG4gICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbcm91bmQxLnNpZ25hdHVyZVNoYXJlUm91bmQxXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDJTaGFyZSh7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3ROb0JpdGdvU2hhcmUsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiByb3VuZDEuZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgICBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uOiByb3VuZDEuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbixcbiAgICAgICAgfSksXG4gICAgICAvTWlzc2luZyBCaXRHbyByb3VuZDFPdXRwdXQgc2lnbmF0dXJlIHNoYXJlL1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcHJvcGFnYXRlIHRoZSB0eC1vbmx5IGd1YXJkIHdoZW4gdHJhbnNhY3Rpb25zIGFyZSBtaXNzaW5nJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJvdW5kMSA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQxU2hhcmUoe1xuICAgICAgdHhSZXF1ZXN0OiBiYXNlVHhSZXF1ZXN0LFxuICAgICAgcHJ2OiB1c2VyS2V5U2hhcmUudG9TdHJpbmcoJ2Jhc2U2NCcpLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICB9KTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDJTaGFyZSh7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB7IC4uLmJhc2VUeFJlcXVlc3QsIHRyYW5zYWN0aW9uczogdW5kZWZpbmVkIH0gYXMgdW5rbm93biBhcyBUeFJlcXVlc3QsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiByb3VuZDEuZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgICBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uOiByb3VuZDEuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbixcbiAgICAgICAgfSksXG4gICAgICAvVW5hYmxlIHRvIGZpbmQgdHJhbnNhY3Rpb25zIGluIHR4UmVxdWVzdC9cbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCB3aGVuIHRyYW5zYWN0aW9ucyBhcnJheSBpcyBlbXB0eScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByb3VuZDEgPSBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kMVNoYXJlKHtcbiAgICAgIHR4UmVxdWVzdDogYmFzZVR4UmVxdWVzdCxcbiAgICAgIHBydjogdXNlcktleVNoYXJlLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgfSk7XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQyU2hhcmUoe1xuICAgICAgICAgIHR4UmVxdWVzdDogeyAuLi5iYXNlVHhSZXF1ZXN0LCB0cmFuc2FjdGlvbnM6IFtdIH0sXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiByb3VuZDEuZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgICBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uOiByb3VuZDEuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbixcbiAgICAgICAgfSksXG4gICAgICAvVW5hYmxlIHRvIGZpbmQgdHJhbnNhY3Rpb25zIGluIHR4UmVxdWVzdC9cbiAgICApO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnRWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDNTaGFyZScsICgpID0+IHtcbiAgbGV0IGVkZHNhTVBDdjJVdGlsczogRWRkc2FNUEN2MlV0aWxzO1xuICBsZXQgbW9ja0JpdGdvOiBCaXRHb0Jhc2U7XG4gIGxldCB1c2VyS2V5U2hhcmU6IEJ1ZmZlcjtcbiAgbGV0IGJpdGdvS2V5U2hhcmU6IEJ1ZmZlcjtcbiAgbGV0IGJpdGdvR3BnS2V5UGFpcjogcGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gIGxldCBiaXRnb0dwZ1ByaXZLZXk6IHBncC5Qcml2YXRlS2V5O1xuXG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuICBjb25zdCBzaWduYWJsZUhleCA9ICdkZWFkYmVlZic7XG4gIGNvbnN0IGRlcml2YXRpb25QYXRoID0gJ20vMC8wJztcblxuICBjb25zdCBiYXNlVHhSZXF1ZXN0OiBUeFJlcXVlc3QgPSB7XG4gICAgdHhSZXF1ZXN0SWQ6ICd0eHJlcS1lZGRzYS1yb3VuZDMnLFxuICAgIHdhbGxldElkOiAnd2FsbGV0LWVkZHNhLXJvdW5kMycsXG4gICAgZW50ZXJwcmlzZUlkOiAnZW50ZXJwcmlzZS1lZGRzYS1yb3VuZDMnLFxuICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgIHtcbiAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgIHNpZ25hYmxlSGV4LFxuICAgICAgICAgIGRlcml2YXRpb25QYXRoLFxuICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogc2lnbmFibGVIZXgsXG4gICAgICAgIH0sXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlczogW10sXG4gICAgICB9LFxuICAgIF0sXG4gICAgaW50ZW50OiB7IGludGVudFR5cGU6ICdwYXltZW50JyB9LFxuICAgIHVuc2lnbmVkVHhzOiBbXSxcbiAgfSBhcyB1bmtub3duIGFzIFR4UmVxdWVzdDtcblxuICBiZWZvcmUoJ2dlbmVyYXRlIEVkRFNBIGtleSBzaGFyZXMgYW5kIEdQRyBrZXlzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IFt1c2VyRGtnLCAsIGJpdGdvRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgIHVzZXJLZXlTaGFyZSA9IHVzZXJEa2cuZ2V0S2V5U2hhcmUoKTtcbiAgICBiaXRnb0tleVNoYXJlID0gYml0Z29Ea2cuZ2V0S2V5U2hhcmUoKTtcblxuICAgIGJpdGdvR3BnS2V5UGFpciA9IGF3YWl0IGdlbmVyYXRlR1BHS2V5UGFpcignZWQyNTUxOScpO1xuICAgIGJpdGdvR3BnUHJpdktleSA9IGF3YWl0IHBncC5yZWFkUHJpdmF0ZUtleSh7IGFybW9yZWRLZXk6IGJpdGdvR3BnS2V5UGFpci5wcml2YXRlS2V5IH0pO1xuICB9KTtcblxuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICBtb2NrQml0Z28gPSB7XG4gICAgICBlbmNyeXB0OiBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKGFzeW5jIChwYXJhbXMpID0+IHtcbiAgICAgICAgY29uc3Qgc2FsdCA9IHJhbmRvbUJ5dGVzKDgpO1xuICAgICAgICBjb25zdCBpdiA9IHJhbmRvbUJ5dGVzKDE2KTtcbiAgICAgICAgcmV0dXJuIHNqY2wuZW5jcnlwdChwYXJhbXMucGFzc3dvcmQsIHBhcmFtcy5pbnB1dCwge1xuICAgICAgICAgIHNhbHQ6IFtieXRlc1RvV29yZChzYWx0LnN1YmFycmF5KDAsIDQpKSwgYnl0ZXNUb1dvcmQoc2FsdC5zdWJhcnJheSg0KSldLFxuICAgICAgICAgIGl2OiBbXG4gICAgICAgICAgICBieXRlc1RvV29yZChpdi5zdWJhcnJheSgwLCA0KSksXG4gICAgICAgICAgICBieXRlc1RvV29yZChpdi5zdWJhcnJheSg0LCA4KSksXG4gICAgICAgICAgICBieXRlc1RvV29yZChpdi5zdWJhcnJheSg4LCAxMikpLFxuICAgICAgICAgICAgYnl0ZXNUb1dvcmQoaXYuc3ViYXJyYXkoMTIsIDE2KSksXG4gICAgICAgICAgXSxcbiAgICAgICAgICBhZGF0YTogcGFyYW1zLmFkYXRhLFxuICAgICAgICB9KTtcbiAgICAgIH0pLFxuICAgICAgZGVjcnlwdDogc2lub24uc3R1YigpLmNhbGxzRmFrZShhc3luYyAocGFyYW1zKSA9PiBzamNsLmRlY3J5cHQocGFyYW1zLnBhc3N3b3JkLCBwYXJhbXMuaW5wdXQpKSxcbiAgICB9IGFzIHVua25vd24gYXMgQml0R29CYXNlO1xuXG4gICAgY29uc3QgbW9ja0NvaW4gPSB7XG4gICAgICBnZXRNUENBbGdvcml0aG06IHNpbm9uLnN0dWIoKS5yZXR1cm5zKCdlZGRzYScpLFxuICAgIH0gYXMgdW5rbm93biBhcyBJQmFzZUNvaW47XG5cbiAgICBlZGRzYU1QQ3YyVXRpbHMgPSBuZXcgRWRkc2FNUEN2MlV0aWxzKG1vY2tCaXRnbywgbW9ja0NvaW4pO1xuICB9KTtcblxuICBhc3luYyBmdW5jdGlvbiBjcmVhdGVSb3VuZDJGbG93KFxuICAgIHR4UmVxdWVzdDogVHhSZXF1ZXN0LFxuICAgIGVuY3J5cHRlZFBydj86IHN0cmluZ1xuICApOiBQcm9taXNlPHtcbiAgICByb3VuZDE6IHtcbiAgICAgIHNpZ25hdHVyZVNoYXJlUm91bmQxOiBTaWduYXR1cmVTaGFyZVJlY29yZDtcbiAgICAgIHVzZXJHcGdQdWJLZXk6IHN0cmluZztcbiAgICAgIGVuY3J5cHRlZFJvdW5kMVNlc3Npb246IHN0cmluZztcbiAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHN0cmluZztcbiAgICB9O1xuICAgIHJvdW5kMjoge1xuICAgICAgc2lnbmF0dXJlU2hhcmVSb3VuZDI6IFNpZ25hdHVyZVNoYXJlUmVjb3JkO1xuICAgICAgZW5jcnlwdGVkUm91bmQyU2Vzc2lvbjogc3RyaW5nO1xuICAgIH07XG4gICAgdHhSZXF1ZXN0Um91bmQxOiBUeFJlcXVlc3Q7XG4gICAgdHhSZXF1ZXN0Um91bmQyOiBUeFJlcXVlc3Q7XG4gICAgbWVzc2FnZUJ1ZmZlcjogQnVmZmVyO1xuICB9PiB7XG4gICAgY29uc3Qgcm91bmQxID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDFTaGFyZSh7XG4gICAgICB0eFJlcXVlc3QsXG4gICAgICBwcnY6IHVzZXJLZXlTaGFyZS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgZW5jcnlwdGVkUHJ2LFxuICAgIH0pO1xuXG4gICAgY29uc3QgdHJhbnNhY3Rpb24gPSBhc3NlcnRTaW5nbGVUcmFuc2FjdGlvbih0eFJlcXVlc3QpO1xuICAgIGNvbnN0IG1lc3NhZ2VCdWZmZXIgPSBCdWZmZXIuZnJvbSh0cmFuc2FjdGlvbi51bnNpZ25lZFR4LnNpZ25hYmxlSGV4LCAnaGV4Jyk7XG4gICAgY29uc3QgYml0Z29Ec2cgPSBuZXcgRWRkc2FNUFNEc2cuRFNHKE1QQ3YyUGFydGllc0VudW0uQklUR08pO1xuICAgIGF3YWl0IGJpdGdvRHNnLmluaXREc2coYml0Z29LZXlTaGFyZSwgbWVzc2FnZUJ1ZmZlciwgdHJhbnNhY3Rpb24udW5zaWduZWRUeC5kZXJpdmF0aW9uUGF0aCwgTVBDdjJQYXJ0aWVzRW51bS5VU0VSKTtcblxuICAgIGNvbnN0IHR4UmVxdWVzdFJvdW5kMSA9IGF3YWl0IHNpZ25CaXRnb0VkZHNhUm91bmQxKFxuICAgICAgYml0Z29Ec2csXG4gICAgICBjbG9uZVR4UmVxdWVzdFdpdGhFbXB0eVNpZ25hdHVyZVNoYXJlcyh0eFJlcXVlc3QpLFxuICAgICAgcm91bmQxLnNpZ25hdHVyZVNoYXJlUm91bmQxLFxuICAgICAgcm91bmQxLnVzZXJHcGdQdWJLZXksXG4gICAgICBiaXRnb0dwZ1ByaXZLZXlcbiAgICApO1xuXG4gICAgY29uc3Qgcm91bmQyID0gYXdhaXQgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDJTaGFyZSh7XG4gICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdFJvdW5kMSxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHJvdW5kMS5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgZW5jcnlwdGVkUm91bmQxU2Vzc2lvbjogcm91bmQxLmVuY3J5cHRlZFJvdW5kMVNlc3Npb24sXG4gICAgfSk7XG5cbiAgICBjb25zdCByb3VuZDFUcmFuc2FjdGlvbiA9IGFzc2VydFNpbmdsZVRyYW5zYWN0aW9uKHR4UmVxdWVzdFJvdW5kMSk7XG4gICAgY29uc3QgdHhSZXF1ZXN0Um91bmQyID0gYXdhaXQgc2lnbkJpdGdvRWRkc2FSb3VuZDIoXG4gICAgICBiaXRnb0RzZyxcbiAgICAgIHtcbiAgICAgICAgLi4udHhSZXF1ZXN0Um91bmQxLFxuICAgICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi5yb3VuZDFUcmFuc2FjdGlvbixcbiAgICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogWy4uLnJvdW5kMVRyYW5zYWN0aW9uLnNpZ25hdHVyZVNoYXJlc10sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgICByb3VuZDIuc2lnbmF0dXJlU2hhcmVSb3VuZDIsXG4gICAgICByb3VuZDEudXNlckdwZ1B1YktleSxcbiAgICAgIGJpdGdvR3BnUHJpdktleVxuICAgICk7XG5cbiAgICByZXR1cm4geyByb3VuZDEsIHJvdW5kMiwgdHhSZXF1ZXN0Um91bmQxLCB0eFJlcXVlc3RSb3VuZDIsIG1lc3NhZ2VCdWZmZXIgfTtcbiAgfVxuXG4gIGl0KCdzaG91bGQgY3JlYXRlIGEgcm91bmQtMyBzaGFyZSBmcm9tIG9mZmxpbmUgcm91bmQgMicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB7IHJvdW5kMSwgcm91bmQyLCB0eFJlcXVlc3RSb3VuZDIgfSA9IGF3YWl0IGNyZWF0ZVJvdW5kMkZsb3coYmFzZVR4UmVxdWVzdCk7XG5cbiAgICBjb25zdCByb3VuZDMgPSBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kM1NoYXJlKHtcbiAgICAgIHR4UmVxdWVzdDogdHhSZXF1ZXN0Um91bmQyLFxuICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleTogcm91bmQxLmVuY3J5cHRlZFVzZXJHcGdQcnZLZXksXG4gICAgICBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uOiByb3VuZDIuZW5jcnlwdGVkUm91bmQyU2Vzc2lvbixcbiAgICB9KTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyb3VuZDMuc2lnbmF0dXJlU2hhcmVSb3VuZDMuZnJvbSwgU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyb3VuZDMuc2lnbmF0dXJlU2hhcmVSb3VuZDMudG8sIFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyk7XG5cbiAgICBjb25zdCBwYXJzZWRTaGFyZSA9IGRlY29kZVdpdGhDb2RlYyhcbiAgICAgIEVkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kM0lucHV0LFxuICAgICAgSlNPTi5wYXJzZShyb3VuZDMuc2lnbmF0dXJlU2hhcmVSb3VuZDMuc2hhcmUpLFxuICAgICAgJ0VkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kM0lucHV0J1xuICAgICk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZFNoYXJlLnR5cGUsICdyb3VuZDNJbnB1dCcpO1xuICAgIGFzc2VydC5vayhwYXJzZWRTaGFyZS5kYXRhLm1zZzMubWVzc2FnZSwgJ21zZzMubWVzc2FnZSBzaG91bGQgYmUgc2V0Jyk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZFNoYXJlLmRhdGEubXNnMy5zaWduYXR1cmUsICdtc2czLnNpZ25hdHVyZSBzaG91bGQgYmUgc2V0Jyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdXNlIHYyIGRlY3J5cHRpb24gd2hlbiBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uIGlzIGEgdjIgZW52ZWxvcGUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZW5jcnlwdCA9IHNpbm9uXG4gICAgICAuc3R1YigpXG4gICAgICAuY2FsbHNGYWtlKChpbnB1dDogc3RyaW5nLCBhZGF0YTogc3RyaW5nKSA9PiBQcm9taXNlLnJlc29sdmUoSlNPTi5zdHJpbmdpZnkoeyB2OiAyLCBpbnB1dCwgYWRhdGEgfSkpKTtcbiAgICBjb25zdCBkZXN0cm95ID0gc2lub24uc3R1YigpO1xuICAgIGNvbnN0IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uID0gc2lub24uc3R1YigpLnJlc29sdmVzKHsgZW5jcnlwdCwgZGVzdHJveSB9KTtcbiAgICBtb2NrQml0Z28uY3JlYXRlRW5jcnlwdGlvblNlc3Npb24gPSBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbjtcblxuICAgIGNvbnN0IGRlY3J5cHQgPSBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKGFzeW5jIChwYXJhbXM6IHsgaW5wdXQ6IHN0cmluZyB9KSA9PiB7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IEpTT04ucGFyc2UocGFyYW1zLmlucHV0KTtcbiAgICAgIHJldHVybiBlbnZlbG9wZS5pbnB1dDtcbiAgICB9KTtcbiAgICBtb2NrQml0Z28uZGVjcnlwdCA9IGRlY3J5cHQ7XG5cbiAgICBjb25zdCB7IHJvdW5kMSwgcm91bmQyLCB0eFJlcXVlc3RSb3VuZDIgfSA9IGF3YWl0IGNyZWF0ZVJvdW5kMkZsb3coYmFzZVR4UmVxdWVzdCwgSlNPTi5zdHJpbmdpZnkoeyB2OiAyIH0pKTtcblxuICAgIGNvbnN0IHJvdW5kMyA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQzU2hhcmUoe1xuICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RSb3VuZDIsXG4gICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgYml0Z29QdWJsaWNHcGdLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiByb3VuZDEuZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgIGVuY3J5cHRlZFJvdW5kMlNlc3Npb246IHJvdW5kMi5lbmNyeXB0ZWRSb3VuZDJTZXNzaW9uLFxuICAgIH0pO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKChtb2NrQml0Z28uZGVjcnlwdCBhcyBzaW5vbi5TaW5vblN0dWIpLmNhbGxDb3VudCwgNCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJvdW5kMy5zaWduYXR1cmVTaGFyZVJvdW5kMy5mcm9tLCBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUik7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IHRhbXBlcmVkIGVuY3J5cHRlZFJvdW5kMlNlc3Npb24gYWRhdGEnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgb3RoZXJUeFJlcXVlc3Q6IFR4UmVxdWVzdCA9IHtcbiAgICAgIC4uLmJhc2VUeFJlcXVlc3QsXG4gICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHVuc2lnbmVkVHg6IHtcbiAgICAgICAgICAgIHNpZ25hYmxlSGV4OiAnY2FmZWJhYmUnLFxuICAgICAgICAgICAgZGVyaXZhdGlvblBhdGg6ICdtLzEvMicsXG4gICAgICAgICAgICBzZXJpYWxpemVkVHhIZXg6ICdjYWZlYmFiZScsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBzaWduYXR1cmVTaGFyZXM6IFtdLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9IGFzIHVua25vd24gYXMgVHhSZXF1ZXN0O1xuXG4gICAgY29uc3Qgb3RoZXJGbG93ID0gYXdhaXQgY3JlYXRlUm91bmQyRmxvdyhvdGhlclR4UmVxdWVzdCk7XG4gICAgY29uc3QgeyByb3VuZDEsIHR4UmVxdWVzdFJvdW5kMiB9ID0gYXdhaXQgY3JlYXRlUm91bmQyRmxvdyhiYXNlVHhSZXF1ZXN0KTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgZWRkc2FNUEN2MlV0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDNTaGFyZSh7XG4gICAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RSb3VuZDIsXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiByb3VuZDEuZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgICBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uOiBvdGhlckZsb3cucm91bmQyLmVuY3J5cHRlZFJvdW5kMlNlc3Npb24sXG4gICAgICAgIH0pLFxuICAgICAgL0FkYXRhIGRvZXMgbm90IG1hdGNoIGN5cGhlcnRleHQgYWRhdGEvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWplY3QgdGFtcGVyZWQgZW5jcnlwdGVkVXNlckdwZ1BydktleSBhZGF0YScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvdGhlclR4UmVxdWVzdDogVHhSZXF1ZXN0ID0ge1xuICAgICAgLi4uYmFzZVR4UmVxdWVzdCxcbiAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgc2lnbmFibGVIZXg6ICdjYWZlYmFiZScsXG4gICAgICAgICAgICBkZXJpdmF0aW9uUGF0aDogJ20vMS8yJyxcbiAgICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogJ2NhZmViYWJlJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogW10sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0gYXMgdW5rbm93biBhcyBUeFJlcXVlc3Q7XG5cbiAgICBjb25zdCBvdGhlckZsb3cgPSBhd2FpdCBjcmVhdGVSb3VuZDJGbG93KG90aGVyVHhSZXF1ZXN0KTtcbiAgICBjb25zdCB7IHJvdW5kMiwgdHhSZXF1ZXN0Um91bmQyIH0gPSBhd2FpdCBjcmVhdGVSb3VuZDJGbG93KGJhc2VUeFJlcXVlc3QpO1xuXG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kM1NoYXJlKHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdFJvdW5kMixcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IG90aGVyRmxvdy5yb3VuZDEuZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgICBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uOiByb3VuZDIuZW5jcnlwdGVkUm91bmQyU2Vzc2lvbixcbiAgICAgICAgfSksXG4gICAgICAvQWRhdGEgZG9lcyBub3QgbWF0Y2ggY3lwaGVydGV4dCBhZGF0YS9cbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCB3aGVuIEJpdEdvIHJvdW5kLTIgc2lnbmF0dXJlIHNoYXJlIGlzIG1pc3NpbmcnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgeyByb3VuZDEsIHJvdW5kMiwgdHhSZXF1ZXN0Um91bmQxIH0gPSBhd2FpdCBjcmVhdGVSb3VuZDJGbG93KGJhc2VUeFJlcXVlc3QpO1xuXG4gICAgY29uc3Qgcm91bmQxVHJhbnNhY3Rpb24gPSBhc3NlcnRTaW5nbGVUcmFuc2FjdGlvbih0eFJlcXVlc3RSb3VuZDEpO1xuICAgIGNvbnN0IHR4UmVxdWVzdE5vQml0Z29Sb3VuZDJTaGFyZTogVHhSZXF1ZXN0ID0ge1xuICAgICAgLi4udHhSZXF1ZXN0Um91bmQxLFxuICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICAuLi5yb3VuZDFUcmFuc2FjdGlvbixcbiAgICAgICAgICBzaWduYXR1cmVTaGFyZXM6IFsuLi5yb3VuZDFUcmFuc2FjdGlvbi5zaWduYXR1cmVTaGFyZXMsIHJvdW5kMi5zaWduYXR1cmVTaGFyZVJvdW5kMl0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQzU2hhcmUoe1xuICAgICAgICAgIHR4UmVxdWVzdDogdHhSZXF1ZXN0Tm9CaXRnb1JvdW5kMlNoYXJlLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgICAgYml0Z29QdWJsaWNHcGdLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleTogcm91bmQxLmVuY3J5cHRlZFVzZXJHcGdQcnZLZXksXG4gICAgICAgICAgZW5jcnlwdGVkUm91bmQyU2Vzc2lvbjogcm91bmQyLmVuY3J5cHRlZFJvdW5kMlNlc3Npb24sXG4gICAgICAgIH0pLFxuICAgICAgL01pc3NpbmcgQml0R28gcm91bmQyT3V0cHV0IHNpZ25hdHVyZSBzaGFyZS9cbiAgICApO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHByb3BhZ2F0ZSB0aGUgdHgtb25seSBndWFyZCB3aGVuIHRyYW5zYWN0aW9ucyBhcmUgbWlzc2luZycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB7IHJvdW5kMSwgcm91bmQyIH0gPSBhd2FpdCBjcmVhdGVSb3VuZDJGbG93KGJhc2VUeFJlcXVlc3QpO1xuXG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICBlZGRzYU1QQ3YyVXRpbHMuY3JlYXRlT2ZmbGluZVJvdW5kM1NoYXJlKHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IHsgLi4uYmFzZVR4UmVxdWVzdCwgdHJhbnNhY3Rpb25zOiB1bmRlZmluZWQgfSBhcyB1bmtub3duIGFzIFR4UmVxdWVzdCxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleVBhaXIucHVibGljS2V5LFxuICAgICAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHJvdW5kMS5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICAgIGVuY3J5cHRlZFJvdW5kMlNlc3Npb246IHJvdW5kMi5lbmNyeXB0ZWRSb3VuZDJTZXNzaW9uLFxuICAgICAgICB9KSxcbiAgICAgIC9VbmFibGUgdG8gZmluZCB0cmFuc2FjdGlvbnMgaW4gdHhSZXF1ZXN0L1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IHdoZW4gdHJhbnNhY3Rpb25zIGFycmF5IGlzIGVtcHR5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgcm91bmQxLCByb3VuZDIgfSA9IGF3YWl0IGNyZWF0ZVJvdW5kMkZsb3coYmFzZVR4UmVxdWVzdCk7XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGVkZHNhTVBDdjJVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQzU2hhcmUoe1xuICAgICAgICAgIHR4UmVxdWVzdDogeyAuLi5iYXNlVHhSZXF1ZXN0LCB0cmFuc2FjdGlvbnM6IFtdIH0sXG4gICAgICAgICAgd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiByb3VuZDEuZW5jcnlwdGVkVXNlckdwZ1BydktleSxcbiAgICAgICAgICBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uOiByb3VuZDIuZW5jcnlwdGVkUm91bmQyU2Vzc2lvbixcbiAgICAgICAgfSksXG4gICAgICAvVW5hYmxlIHRvIGZpbmQgdHJhbnNhY3Rpb25zIGluIHR4UmVxdWVzdC9cbiAgICApO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnZ2V0Qml0Z29TaWduYXR1cmVTaGFyZScsICgpID0+IHtcbiAgY29uc3Qgcm91bmQxT3V0cHV0U2hhcmU6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgc2hhcmU6IEpTT04uc3RyaW5naWZ5KHsgdHlwZTogJ3JvdW5kMU91dHB1dCcsIGRhdGE6IHt9IH0pLFxuICB9O1xuICBjb25zdCByb3VuZDJPdXRwdXRTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7XG4gICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICBzaGFyZTogSlNPTi5zdHJpbmdpZnkoeyB0eXBlOiAncm91bmQyT3V0cHV0JywgZGF0YToge30gfSksXG4gIH07XG5cbiAgaXQoJ3NlbGVjdHMgdGhlIHJlcXVlc3RlZCBCaXRHbyByb3VuZCBvdXRwdXQgd2hlbiBtdWx0aXBsZSByb3VuZCBvdXRwdXRzIGFyZSBwcmVzZW50JywgKCkgPT4ge1xuICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlcyA9IFtyb3VuZDFPdXRwdXRTaGFyZSwgcm91bmQyT3V0cHV0U2hhcmVdO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgZ2V0Qml0Z29TaWduYXR1cmVTaGFyZShzaWduYXR1cmVTaGFyZXMsIFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLCAncm91bmQyT3V0cHV0JyksXG4gICAgICByb3VuZDJPdXRwdXRTaGFyZVxuICAgICk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgZ2V0Qml0Z29TaWduYXR1cmVTaGFyZShzaWduYXR1cmVTaGFyZXMsIFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLCAncm91bmQxT3V0cHV0JyksXG4gICAgICByb3VuZDFPdXRwdXRTaGFyZVxuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdza2lwcyBtYWxmb3JtZWQgc2hhcmUgcmVjb3JkcyB3aGlsZSBzZWxlY3RpbmcgdGhlIHJlcXVlc3RlZCBCaXRHbyByb3VuZCBvdXRwdXQnLCAoKSA9PiB7XG4gICAgY29uc3QgbWFsZm9ybWVkU2hhcmU6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgc2hhcmU6ICdub3QtanNvbicsXG4gICAgfTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgIGdldEJpdGdvU2lnbmF0dXJlU2hhcmUoW21hbGZvcm1lZFNoYXJlLCByb3VuZDJPdXRwdXRTaGFyZV0sIFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLCAncm91bmQyT3V0cHV0JyksXG4gICAgICByb3VuZDJPdXRwdXRTaGFyZVxuICAgICk7XG4gIH0pO1xufSk7XG5cbnR5cGUgVHhSZXF1ZXN0VHJhbnNhY3Rpb24gPSBOb25OdWxsYWJsZTxUeFJlcXVlc3RbJ3RyYW5zYWN0aW9ucyddPltudW1iZXJdO1xuXG5mdW5jdGlvbiBhc3NlcnRTaW5nbGVUcmFuc2FjdGlvbih0eFJlcXVlc3Q6IFR4UmVxdWVzdCk6IFR4UmVxdWVzdFRyYW5zYWN0aW9uIHtcbiAgYXNzZXJ0Lm9rKHR4UmVxdWVzdC50cmFuc2FjdGlvbnMsICd0eFJlcXVlc3QgbXVzdCBpbmNsdWRlIHRyYW5zYWN0aW9ucycpO1xuICBhc3NlcnQuc3RyaWN0RXF1YWwodHhSZXF1ZXN0LnRyYW5zYWN0aW9ucy5sZW5ndGgsIDEsICd0eFJlcXVlc3QgbXVzdCBoYXZlIGV4YWN0bHkgb25lIHRyYW5zYWN0aW9uJyk7XG4gIHJldHVybiB0eFJlcXVlc3QudHJhbnNhY3Rpb25zWzBdO1xufVxuXG5mdW5jdGlvbiBjbG9uZVR4UmVxdWVzdFdpdGhFbXB0eVNpZ25hdHVyZVNoYXJlcyh0eFJlcXVlc3Q6IFR4UmVxdWVzdCk6IFR4UmVxdWVzdCB7XG4gIGNvbnN0IHRyYW5zYWN0aW9uID0gYXNzZXJ0U2luZ2xlVHJhbnNhY3Rpb24odHhSZXF1ZXN0KTtcbiAgcmV0dXJuIHtcbiAgICAuLi50eFJlcXVlc3QsXG4gICAgdHJhbnNhY3Rpb25zOiBbeyAuLi50cmFuc2FjdGlvbiwgc2lnbmF0dXJlU2hhcmVzOiBbXSB9XSxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2lnbkJpdGdvRWRkc2FSb3VuZDEoXG4gIGJpdGdvRHNnOiBFZGRzYU1QU0RzZy5EU0csXG4gIHR4UmVxdWVzdDogVHhSZXF1ZXN0LFxuICB1c2VyUm91bmQxU2hhcmU6IFNpZ25hdHVyZVNoYXJlUmVjb3JkLFxuICB1c2VyR3BnUHViS2V5QXJtb3JlZDogc3RyaW5nLFxuICBiaXRnb0dwZ1ByaXZLZXk6IHBncC5Qcml2YXRlS2V5XG4pOiBQcm9taXNlPFR4UmVxdWVzdD4ge1xuICBjb25zdCB0cmFuc2FjdGlvbiA9IGFzc2VydFNpbmdsZVRyYW5zYWN0aW9uKHR4UmVxdWVzdCk7XG4gIHRyYW5zYWN0aW9uLnNpZ25hdHVyZVNoYXJlcy5wdXNoKHVzZXJSb3VuZDFTaGFyZSk7XG5cbiAgY29uc3QgYml0Z29Nc2cxID0gYml0Z29Ec2cuZ2V0Rmlyc3RNZXNzYWdlKCk7XG5cbiAgY29uc3QgcGFyc2VkVXNlclNoYXJlID0gZGVjb2RlV2l0aENvZGVjKFxuICAgIEVkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMUlucHV0LFxuICAgIEpTT04ucGFyc2UodXNlclJvdW5kMVNoYXJlLnNoYXJlKSxcbiAgICAnRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxSW5wdXQnXG4gICk7XG4gIGNvbnN0IHVzZXJHcGdLZXkgPSBhd2FpdCBwZ3AucmVhZEtleSh7IGFybW9yZWRLZXk6IHVzZXJHcGdQdWJLZXlBcm1vcmVkIH0pO1xuICBjb25zdCB1c2VyUmF3TXNnMUJ5dGVzID0gYXdhaXQgTVBTQ29tbXMudmVyaWZ5TXBzTWVzc2FnZShwYXJzZWRVc2VyU2hhcmUuZGF0YS5tc2cxLCB1c2VyR3BnS2V5KTtcbiAgY29uc3QgdXNlck1zZzEgPSB7XG4gICAgZnJvbTogTVBDdjJQYXJ0aWVzRW51bS5VU0VSLFxuICAgIHBheWxvYWQ6IG5ldyBVaW50OEFycmF5KHVzZXJSYXdNc2cxQnl0ZXMpLFxuICB9O1xuXG4gIGNvbnN0IFtiaXRnb01zZzJdID0gYml0Z29Ec2cuaGFuZGxlSW5jb21pbmdNZXNzYWdlcyhbYml0Z29Nc2cxLCB1c2VyTXNnMV0pO1xuICBhc3NlcnQub2soYml0Z29Nc2cyLCAnQml0R28gRFNHIHByb2R1Y2VkIG5vIHJvdW5kLTIgb3V0cHV0Jyk7XG4gIChiaXRnb0RzZyBhcyBFZGRzYU1QU0RzZy5EU0cgJiB7IHJvdW5kMk1lc3NhZ2U/OiBNUFNUeXBlcy5EZXNlcmlhbGl6ZWRNZXNzYWdlIH0pLnJvdW5kMk1lc3NhZ2UgPSBiaXRnb01zZzI7XG5cbiAgY29uc3QgYml0Z29TaWduZWRNc2cxID0gYXdhaXQgTVBTQ29tbXMuZGV0YWNoU2lnbk1wc01lc3NhZ2UoQnVmZmVyLmZyb20oYml0Z29Nc2cxLnBheWxvYWQpLCBiaXRnb0dwZ1ByaXZLZXkpO1xuICBjb25zdCByb3VuZDFPdXRwdXQ6IEVkZHNhTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMU91dHB1dCA9IHtcbiAgICB0eXBlOiAncm91bmQxT3V0cHV0JyxcbiAgICBkYXRhOiB7IG1zZzE6IGJpdGdvU2lnbmVkTXNnMSB9LFxuICB9O1xuXG4gIHRyYW5zYWN0aW9uLnNpZ25hdHVyZVNoYXJlcy5wdXNoKHtcbiAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgIHNoYXJlOiBKU09OLnN0cmluZ2lmeShyb3VuZDFPdXRwdXQpLFxuICB9KTtcblxuICByZXR1cm4gdHhSZXF1ZXN0O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzaWduQml0Z29FZGRzYVJvdW5kMihcbiAgYml0Z29Ec2c6IEVkZHNhTVBTRHNnLkRTRyxcbiAgdHhSZXF1ZXN0OiBUeFJlcXVlc3QsXG4gIHVzZXJSb3VuZDJTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQsXG4gIHVzZXJHcGdQdWJLZXlBcm1vcmVkOiBzdHJpbmcsXG4gIGJpdGdvR3BnUHJpdktleTogcGdwLlByaXZhdGVLZXlcbik6IFByb21pc2U8VHhSZXF1ZXN0PiB7XG4gIGNvbnN0IHRyYW5zYWN0aW9uID0gYXNzZXJ0U2luZ2xlVHJhbnNhY3Rpb24odHhSZXF1ZXN0KTtcbiAgdHJhbnNhY3Rpb24uc2lnbmF0dXJlU2hhcmVzLnB1c2godXNlclJvdW5kMlNoYXJlKTtcblxuICBjb25zdCB1c2VyR3BnS2V5ID0gYXdhaXQgcGdwLnJlYWRLZXkoeyBhcm1vcmVkS2V5OiB1c2VyR3BnUHViS2V5QXJtb3JlZCB9KTtcbiAgY29uc3QgYml0Z29Nc2cyID0gKGJpdGdvRHNnIGFzIEVkZHNhTVBTRHNnLkRTRyAmIHsgcm91bmQyTWVzc2FnZT86IE1QU1R5cGVzLkRlc2VyaWFsaXplZE1lc3NhZ2UgfSkucm91bmQyTWVzc2FnZTtcbiAgYXNzZXJ0Lm9rKGJpdGdvTXNnMiwgJ0JpdEdvIERTRyBpcyBtaXNzaW5nIHRoZSBjYWNoZWQgcm91bmQtMiBvdXRwdXQnKTtcblxuICBjb25zdCBwYXJzZWRVc2VyUm91bmQyU2hhcmUgPSBkZWNvZGVXaXRoQ29kZWMoXG4gICAgRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQySW5wdXQsXG4gICAgSlNPTi5wYXJzZSh1c2VyUm91bmQyU2hhcmUuc2hhcmUpLFxuICAgICdFZGRzYU1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJJbnB1dCdcbiAgKTtcbiAgY29uc3QgdXNlclJhd01zZzJCeXRlcyA9IGF3YWl0IE1QU0NvbW1zLnZlcmlmeU1wc01lc3NhZ2UocGFyc2VkVXNlclJvdW5kMlNoYXJlLmRhdGEubXNnMiwgdXNlckdwZ0tleSk7XG4gIGNvbnN0IHVzZXJNc2cyID0ge1xuICAgIGZyb206IE1QQ3YyUGFydGllc0VudW0uVVNFUixcbiAgICBwYXlsb2FkOiBuZXcgVWludDhBcnJheSh1c2VyUmF3TXNnMkJ5dGVzKSxcbiAgfTtcblxuICBjb25zdCBiaXRnb1NpZ25lZE1zZzIgPSBhd2FpdCBNUFNDb21tcy5kZXRhY2hTaWduTXBzTWVzc2FnZShCdWZmZXIuZnJvbShiaXRnb01zZzIucGF5bG9hZCksIGJpdGdvR3BnUHJpdktleSk7XG4gIGNvbnN0IHJvdW5kMk91dHB1dDogRWRkc2FNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQyT3V0cHV0ID0ge1xuICAgIHR5cGU6ICdyb3VuZDJPdXRwdXQnLFxuICAgIGRhdGE6IHsgbXNnMjogYml0Z29TaWduZWRNc2cyIH0sXG4gIH07XG5cbiAgdHJhbnNhY3Rpb24uc2lnbmF0dXJlU2hhcmVzLnB1c2goe1xuICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgc2hhcmU6IEpTT04uc3RyaW5naWZ5KHJvdW5kMk91dHB1dCksXG4gIH0pO1xuXG4gIGJpdGdvRHNnLmhhbmRsZUluY29taW5nTWVzc2FnZXMoW2JpdGdvTXNnMiwgdXNlck1zZzJdKTtcblxuICByZXR1cm4gdHhSZXF1ZXN0O1xufVxuXG5kZXNjcmliZSgnRWRkc2FNUEN2MlV0aWxzLnNpZ25FZGRzYU1QQ3YyVHNzVXNpbmdFeHRlcm5hbFNpZ25lcicsICgpID0+IHtcbiAgbGV0IHNhbmRib3g6IHNpbm9uLlNpbm9uU2FuZGJveDtcbiAgbGV0IGVkZHNhTVBDdjJVdGlsczogRWRkc2FNUEN2MlV0aWxzO1xuICBsZXQgbW9ja0JpdGdvOiBCaXRHb0Jhc2U7XG4gIGxldCBiaXRnb0dwZ0tleVBhaXI6IHBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuICBsZXQgYml0Z29HcGdQdWJLZXk6IHBncC5LZXk7XG5cbiAgY29uc3Qgd2FsbGV0SWQgPSAnYWJjMTIzd2FsbGV0JztcbiAgY29uc3QgdHhSZXF1ZXN0SWQgPSAndHhyZXEtMDAxJztcbiAgY29uc3QgZW50ZXJwcmlzZUlkID0gJ2VudC0wMDEnO1xuXG4gIGNvbnN0IG1vY2tUeFJlcXVlc3Q6IFR4UmVxdWVzdCA9IHtcbiAgICB0eFJlcXVlc3RJZCxcbiAgICB3YWxsZXRJZCxcbiAgICBlbnRlcnByaXNlSWQsXG4gICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAge1xuICAgICAgICB1bnNpZ25lZFR4OiB7XG4gICAgICAgICAgc2lnbmFibGVIZXg6ICdkZWFkYmVlZicsXG4gICAgICAgICAgZGVyaXZhdGlvblBhdGg6ICdtLzAnLFxuICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogJ2RlYWRiZWVmJyxcbiAgICAgICAgfSxcbiAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICAgICAgc2hhcmU6IEpTT04uc3RyaW5naWZ5KHsgdHlwZTogJ3JvdW5kMU91dHB1dCcsIGRhdGE6IHt9IH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIF0sXG4gICAgaW50ZW50OiB7IGludGVudFR5cGU6ICdwYXltZW50JyB9LFxuICAgIHVuc2lnbmVkVHhzOiBbXSxcbiAgfSBhcyB1bmtub3duIGFzIFR4UmVxdWVzdDtcblxuICBjb25zdCBtb2NrVHhSZXF1ZXN0VHJhbnNhY3Rpb24gPSBhc3NlcnRTaW5nbGVUcmFuc2FjdGlvbihtb2NrVHhSZXF1ZXN0KTtcbiAgY29uc3QgbW9ja1R4UmVxdWVzdFJvdW5kMjogVHhSZXF1ZXN0ID0ge1xuICAgIC4uLm1vY2tUeFJlcXVlc3QsXG4gICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICB7XG4gICAgICAgIC4uLm1vY2tUeFJlcXVlc3RUcmFuc2FjdGlvbixcbiAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICAgICAgc2hhcmU6IEpTT04uc3RyaW5naWZ5KHsgdHlwZTogJ3JvdW5kMk91dHB1dCcsIGRhdGE6IHt9IH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIF0sXG4gIH07XG5cbiAgY29uc3QgZHVtbXlTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7XG4gICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICBzaGFyZTogSlNPTi5zdHJpbmdpZnkoeyB0eXBlOiAncm91bmQxSW5wdXQnLCBkYXRhOiB7fSB9KSxcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgY2hhaW4gY29tcGF0aWJsZSB3aXRoOiBiaXRnby5wb3N0KHVybCkuc2VuZChib2R5KS5yZXN1bHQoKVxuICBjb25zdCBtYWtlUG9zdENoYWluID0gKHJlc3BvbnNlOiBUeFJlcXVlc3QpOiBCaXRHb1JlcXVlc3Q8VHhSZXF1ZXN0PiA9PlxuICAgICh7IHNlbmQ6ICgpID0+ICh7IHJlc3VsdDogc2lub24uc3R1YigpLnJlc29sdmVzKHJlc3BvbnNlKSB9KSB9IGFzIHVua25vd24gYXMgQml0R29SZXF1ZXN0PFR4UmVxdWVzdD4pO1xuXG4gIC8vIFJldHVybnMgYSBjaGFpbiBjb21wYXRpYmxlIHdpdGg6IGJpdGdvLmdldCh1cmwpLnF1ZXJ5KHBhcmFtcykucmV0cnkobikucmVzdWx0KClcbiAgY29uc3QgbWFrZUdldENoYWluID0gKHR4UmVxdWVzdHM6IFR4UmVxdWVzdFtdKTogQml0R29SZXF1ZXN0PHsgdHhSZXF1ZXN0czogVHhSZXF1ZXN0W10gfT4gPT5cbiAgICAoe1xuICAgICAgcXVlcnk6ICgpID0+ICh7XG4gICAgICAgIHJldHJ5OiAoKSA9PiAoeyByZXN1bHQ6IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh7IHR4UmVxdWVzdHMgfSkgfSksXG4gICAgICB9KSxcbiAgICB9IGFzIHVua25vd24gYXMgQml0R29SZXF1ZXN0PHsgdHhSZXF1ZXN0czogVHhSZXF1ZXN0W10gfT4pO1xuXG4gIGJlZm9yZShhc3luYyAoKSA9PiB7XG4gICAgYml0Z29HcGdLZXlQYWlyID0gYXdhaXQgZ2VuZXJhdGVHUEdLZXlQYWlyKCdlZDI1NTE5Jyk7XG4gICAgYml0Z29HcGdQdWJLZXkgPSBhd2FpdCBwZ3AucmVhZEtleSh7IGFybW9yZWRLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXkgfSk7XG4gIH0pO1xuXG4gIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xuICAgIHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG5cbiAgICAvLyBGdWxsIG1vY2sgb2YgdGhlIEJpdEdvIEhUVFAgY2xpZW50IChjb25zaXN0ZW50IHdpdGggb3RoZXIgc2RrLWNvcmUgdGVzdHMgc3VjaCBhc1xuICAgIC8vIHRva2VuQXBwcm92YWwudHMgYW5kIHdhbGxldHNFdm1LZXlyaW5nLnRzKS4gIE1vZHVsZS1sZXZlbCBzdHVicyBvbiB0c3NDb21tb24gZnVuY3Rpb25zXG4gICAgLy8gZG8gbm90IHdvcmsgdW5kZXIgdHN4IDQueCAoRVNNIGxpdmUgYmluZGluZ3MpLCBzbyB3ZSBtb2NrIGF0IHRoZSBiaXRnbyBvYmplY3QgbGV2ZWwuXG4gICAgbW9ja0JpdGdvID0ge1xuICAgICAgZ2V0RW52OiBzaW5vbi5zdHViKCkucmV0dXJucygndGVzdCcpLFxuICAgICAgc2V0UmVxdWVzdFRyYWNlcjogc2lub24uc3R1YigpLFxuICAgICAgdXJsOiBzaW5vbi5zdHViKCkuY2FsbHNGYWtlKChwYXRoOiBzdHJpbmcpID0+IGBodHRwczovL3Rlc3QuYml0Z28uY29tJHtwYXRofWApLFxuICAgICAgcG9zdDogc2lub24uc3R1YigpLFxuICAgICAgZ2V0OiBzaW5vbi5zdHViKCksXG4gICAgfSBhcyB1bmtub3duIGFzIEJpdEdvQmFzZTtcblxuICAgIGNvbnN0IG1vY2tDb2luID0ge1xuICAgICAgZ2V0TVBDQWxnb3JpdGhtOiBzaW5vbi5zdHViKCkucmV0dXJucygnZWRkc2EnKSxcbiAgICB9IGFzIHVua25vd24gYXMgSUJhc2VDb2luO1xuXG4gICAgY29uc3QgbW9ja1dhbGxldCA9IHtcbiAgICAgIGlkOiBzaW5vbi5zdHViKCkucmV0dXJucyh3YWxsZXRJZCksXG4gICAgICBrZXlJZHM6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKFsndXNlcktleUlkJywgJ2JhY2t1cEtleUlkJywgJ2JpdGdvS2V5SWQnXSksXG4gICAgICBtdWx0aXNpZ1R5cGVWZXJzaW9uOiBzaW5vbi5zdHViKCkucmV0dXJucygnTVBDdjInKSxcbiAgICB9IGFzIHVua25vd24gYXMgSVdhbGxldDtcblxuICAgIGVkZHNhTVBDdjJVdGlscyA9IG5ldyBFZGRzYU1QQ3YyVXRpbHMobW9ja0JpdGdvLCBtb2NrQ29pbiwgbW9ja1dhbGxldCk7XG5cbiAgICBzYW5kYm94LnN0dWIoZWRkc2FNUEN2MlV0aWxzLCAncGlja0JpdGdvUHViR3BnS2V5Rm9yU2lnbmluZycpLnJlc29sdmVzKGJpdGdvR3BnUHViS2V5KTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICBzYW5kYm94LnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBjYWxsIGFsbCAzIGdlbmVyYXRvcnMgYW5kIHJldHVybiB0aGUgZmluYWwgdHggcmVxdWVzdCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBmaW5hbFR4UmVxdWVzdCA9IHsgLi4ubW9ja1R4UmVxdWVzdCwgdHhSZXF1ZXN0SWQgfTtcblxuICAgIC8vIHNlbmRTaWduYXR1cmVTaGFyZVYyIGlzIGNhbGxlZCAzIHRpbWVzIChvbmUgcGVyIHJvdW5kKSwgc2VuZFR4UmVxdWVzdCBvbmNlIOKAlCBhbGwgdXNlIGJpdGdvLnBvc3RcbiAgICAobW9ja0JpdGdvLnBvc3QgYXMgc2lub24uU2lub25TdHViKVxuICAgICAgLm9uQ2FsbCgwKVxuICAgICAgLnJldHVybnMobWFrZVBvc3RDaGFpbihtb2NrVHhSZXF1ZXN0KSkgLy8gcm91bmQgMSBzaWduXG4gICAgICAub25DYWxsKDEpXG4gICAgICAucmV0dXJucyhtYWtlUG9zdENoYWluKG1vY2tUeFJlcXVlc3RSb3VuZDIpKSAvLyByb3VuZCAyIHNpZ25cbiAgICAgIC5vbkNhbGwoMilcbiAgICAgIC5yZXR1cm5zKG1ha2VQb3N0Q2hhaW4obW9ja1R4UmVxdWVzdFJvdW5kMikpIC8vIHJvdW5kIDMgc2lnblxuICAgICAgLm9uQ2FsbCgzKVxuICAgICAgLnJldHVybnMobWFrZVBvc3RDaGFpbihmaW5hbFR4UmVxdWVzdCkpOyAvLyBzZW5kVHhSZXF1ZXN0IChzZW5kKVxuXG4gICAgY29uc3QgZW5jcnlwdGVkUm91bmQxU2Vzc2lvbiA9ICdlbmNyeXB0ZWQtcjEtc2Vzc2lvbic7XG4gICAgY29uc3QgZW5jcnlwdGVkUm91bmQyU2Vzc2lvbiA9ICdlbmNyeXB0ZWQtcjItc2Vzc2lvbic7XG4gICAgY29uc3QgZW5jcnlwdGVkVXNlckdwZ1BydktleSA9ICdlbmNyeXB0ZWQtZ3BnLWtleSc7XG4gICAgY29uc3QgdXNlckdwZ1B1YktleSA9IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXk7XG5cbiAgICBjb25zdCByb3VuZDFTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7IC4uLmR1bW15U2hhcmUgfTtcbiAgICBjb25zdCByb3VuZDJTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7IC4uLmR1bW15U2hhcmUsIHNoYXJlOiBKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdyb3VuZDJJbnB1dCcgfSkgfTtcbiAgICBjb25zdCByb3VuZDNTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7IC4uLmR1bW15U2hhcmUsIHNoYXJlOiBKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdyb3VuZDNJbnB1dCcgfSkgfTtcblxuICAgIGNvbnN0IHJvdW5kMUdlbmVyYXRvciA9IHNpbm9uXG4gICAgICAuc3R1YigpXG4gICAgICAucmVzb2x2ZXMoeyBzaWduYXR1cmVTaGFyZVJvdW5kMTogcm91bmQxU2hhcmUsIHVzZXJHcGdQdWJLZXksIGVuY3J5cHRlZFJvdW5kMVNlc3Npb24sIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXkgfSk7XG4gICAgY29uc3Qgcm91bmQyR2VuZXJhdG9yID0gc2lub24uc3R1YigpLnJlc29sdmVzKHsgc2lnbmF0dXJlU2hhcmVSb3VuZDI6IHJvdW5kMlNoYXJlLCBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uIH0pO1xuICAgIGNvbnN0IHJvdW5kM0dlbmVyYXRvciA9IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh7IHNpZ25hdHVyZVNoYXJlUm91bmQzOiByb3VuZDNTaGFyZSB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGVkZHNhTVBDdjJVdGlscy5zaWduRWRkc2FNUEN2MlRzc1VzaW5nRXh0ZXJuYWxTaWduZXIoXG4gICAgICB7IHR4UmVxdWVzdDogbW9ja1R4UmVxdWVzdCwgcmVxSWQ6IG5ldyBSZXF1ZXN0VHJhY2VyKCkgfSxcbiAgICAgIHJvdW5kMUdlbmVyYXRvciBhcyB1bmtub3duIGFzIEN1c3RvbUVkZHNhTVBDdjJTaWduaW5nUm91bmQxR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICAgICAgcm91bmQyR2VuZXJhdG9yIGFzIHVua25vd24gYXMgQ3VzdG9tRWRkc2FNUEN2MlNpZ25pbmdSb3VuZDJHZW5lcmF0aW5nRnVuY3Rpb24sXG4gICAgICByb3VuZDNHZW5lcmF0b3IgYXMgdW5rbm93biBhcyBDdXN0b21FZGRzYU1QQ3YyU2lnbmluZ1JvdW5kM0dlbmVyYXRpbmdGdW5jdGlvblxuICAgICk7XG5cbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKHJlc3VsdCwgZmluYWxUeFJlcXVlc3QpO1xuXG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2Uocm91bmQxR2VuZXJhdG9yKTtcbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkV2l0aChyb3VuZDFHZW5lcmF0b3IsIHsgdHhSZXF1ZXN0OiBtb2NrVHhSZXF1ZXN0IH0pO1xuXG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2Uocm91bmQyR2VuZXJhdG9yKTtcbiAgICBjb25zdCByb3VuZDJDYWxsID0gcm91bmQyR2VuZXJhdG9yLmdldENhbGwoMCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJvdW5kMkNhbGwuYXJnc1swXS50eFJlcXVlc3QsIG1vY2tUeFJlcXVlc3QpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyb3VuZDJDYWxsLmFyZ3NbMF0uZW5jcnlwdGVkUm91bmQxU2Vzc2lvbiwgZW5jcnlwdGVkUm91bmQxU2Vzc2lvbik7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJvdW5kMkNhbGwuYXJnc1swXS5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LCBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5KTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocm91bmQyQ2FsbC5hcmdzWzBdLmJpdGdvUHVibGljR3BnS2V5LCBiaXRnb0dwZ1B1YktleS5hcm1vcigpKTtcblxuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRPbmNlKHJvdW5kM0dlbmVyYXRvcik7XG4gICAgY29uc3Qgcm91bmQzQ2FsbCA9IHJvdW5kM0dlbmVyYXRvci5nZXRDYWxsKDApO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyb3VuZDNDYWxsLmFyZ3NbMF0udHhSZXF1ZXN0LCBtb2NrVHhSZXF1ZXN0Um91bmQyKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocm91bmQzQ2FsbC5hcmdzWzBdLmVuY3J5cHRlZFJvdW5kMlNlc3Npb24sIGVuY3J5cHRlZFJvdW5kMlNlc3Npb24pO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyb3VuZDNDYWxsLmFyZ3NbMF0uZW5jcnlwdGVkVXNlckdwZ1BydktleSwgZW5jcnlwdGVkVXNlckdwZ1BydktleSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJvdW5kM0NhbGwuYXJnc1swXS5iaXRnb1B1YmxpY0dwZ0tleSwgYml0Z29HcGdQdWJLZXkuYXJtb3IoKSk7XG5cbiAgICAvLyAzIHNlbmRTaWduYXR1cmVTaGFyZVYyIGNhbGxzICsgMSBzZW5kVHhSZXF1ZXN0ID0gNCBQT1NUIGNhbGxzIHRvdGFsXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKChtb2NrQml0Z28ucG9zdCBhcyBzaW5vbi5TaW5vblN0dWIpLmNhbGxDb3VudCwgNCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVzb2x2ZSB0eFJlcXVlc3QgYnkgSUQgc3RyaW5nIHVzaW5nIGdldFR4UmVxdWVzdCcsIGFzeW5jICgpID0+IHtcbiAgICAvLyBnZXRUeFJlcXVlc3QgdXNlcyBiaXRnby5nZXQ7IHNlbmRTaWduYXR1cmVTaGFyZVYyICjDlzMpICsgc2VuZFR4UmVxdWVzdCB1c2UgYml0Z28ucG9zdFxuICAgIChtb2NrQml0Z28uZ2V0IGFzIHNpbm9uLlNpbm9uU3R1YikucmV0dXJucyhtYWtlR2V0Q2hhaW4oW21vY2tUeFJlcXVlc3RdKSk7XG4gICAgKG1vY2tCaXRnby5wb3N0IGFzIHNpbm9uLlNpbm9uU3R1YilcbiAgICAgIC5vbkNhbGwoMClcbiAgICAgIC5yZXR1cm5zKG1ha2VQb3N0Q2hhaW4obW9ja1R4UmVxdWVzdCkpXG4gICAgICAub25DYWxsKDEpXG4gICAgICAucmV0dXJucyhtYWtlUG9zdENoYWluKG1vY2tUeFJlcXVlc3RSb3VuZDIpKVxuICAgICAgLm9uQ2FsbCgyKVxuICAgICAgLnJldHVybnMobWFrZVBvc3RDaGFpbihtb2NrVHhSZXF1ZXN0Um91bmQyKSlcbiAgICAgIC5vbkNhbGwoMylcbiAgICAgIC5yZXR1cm5zKG1ha2VQb3N0Q2hhaW4obW9ja1R4UmVxdWVzdCkpO1xuXG4gICAgY29uc3Qgcm91bmQxR2VuZXJhdG9yID0gc2lub24uc3R1YigpLnJlc29sdmVzKHtcbiAgICAgIHNpZ25hdHVyZVNoYXJlUm91bmQxOiBkdW1teVNoYXJlLFxuICAgICAgdXNlckdwZ1B1YktleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgIGVuY3J5cHRlZFJvdW5kMVNlc3Npb246ICdyMScsXG4gICAgICBlbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5OiAna2V5JyxcbiAgICB9KTtcbiAgICBjb25zdCByb3VuZDJHZW5lcmF0b3IgPSBzaW5vbi5zdHViKCkucmVzb2x2ZXMoeyBzaWduYXR1cmVTaGFyZVJvdW5kMjogZHVtbXlTaGFyZSwgZW5jcnlwdGVkUm91bmQyU2Vzc2lvbjogJ3IyJyB9KTtcbiAgICBjb25zdCByb3VuZDNHZW5lcmF0b3IgPSBzaW5vbi5zdHViKCkucmVzb2x2ZXMoeyBzaWduYXR1cmVTaGFyZVJvdW5kMzogZHVtbXlTaGFyZSB9KTtcblxuICAgIGF3YWl0IGVkZHNhTVBDdjJVdGlscy5zaWduRWRkc2FNUEN2MlRzc1VzaW5nRXh0ZXJuYWxTaWduZXIoXG4gICAgICB7IHR4UmVxdWVzdDogdHhSZXF1ZXN0SWQsIHJlcUlkOiBuZXcgUmVxdWVzdFRyYWNlcigpIH0sXG4gICAgICByb3VuZDFHZW5lcmF0b3IgYXMgdW5rbm93biBhcyBDdXN0b21FZGRzYU1QQ3YyU2lnbmluZ1JvdW5kMUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgICAgIHJvdW5kMkdlbmVyYXRvciBhcyB1bmtub3duIGFzIEN1c3RvbUVkZHNhTVBDdjJTaWduaW5nUm91bmQyR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICAgICAgcm91bmQzR2VuZXJhdG9yIGFzIHVua25vd24gYXMgQ3VzdG9tRWRkc2FNUEN2MlNpZ25pbmdSb3VuZDNHZW5lcmF0aW5nRnVuY3Rpb25cbiAgICApO1xuXG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UobW9ja0JpdGdvLmdldCBhcyBzaW5vbi5TaW5vblN0dWIpO1xuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRXaXRoKHJvdW5kMUdlbmVyYXRvciwgeyB0eFJlcXVlc3Q6IG1vY2tUeFJlcXVlc3QgfSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgd2hlbiByb3VuZCAyIHR4UmVxdWVzdCBpcyBtaXNzaW5nIHNpZ25hdHVyZVNoYXJlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByb3VuZDJOb1NoYXJlczogVHhSZXF1ZXN0ID0ge1xuICAgICAgLi4ubW9ja1R4UmVxdWVzdCxcbiAgICAgIHRyYW5zYWN0aW9uczogW3sgLi4ubW9ja1R4UmVxdWVzdFRyYW5zYWN0aW9uLCBzaWduYXR1cmVTaGFyZXM6IHVuZGVmaW5lZCBhcyB1bmtub3duIGFzIFtdIH1dLFxuICAgIH07XG5cbiAgICAobW9ja0JpdGdvLnBvc3QgYXMgc2lub24uU2lub25TdHViKVxuICAgICAgLm9uQ2FsbCgwKVxuICAgICAgLnJldHVybnMobWFrZVBvc3RDaGFpbihtb2NrVHhSZXF1ZXN0KSlcbiAgICAgIC5vbkNhbGwoMSlcbiAgICAgIC5yZXR1cm5zKG1ha2VQb3N0Q2hhaW4ocm91bmQyTm9TaGFyZXMpKTtcblxuICAgIGNvbnN0IHJvdW5kMUdlbmVyYXRvciA9IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh7XG4gICAgICBzaWduYXR1cmVTaGFyZVJvdW5kMTogZHVtbXlTaGFyZSxcbiAgICAgIHVzZXJHcGdQdWJLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uOiAncjEnLFxuICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleTogJ2tleScsXG4gICAgfSk7XG4gICAgY29uc3Qgcm91bmQyR2VuZXJhdG9yID0gc2lub24uc3R1YigpLnJlc29sdmVzKHsgc2lnbmF0dXJlU2hhcmVSb3VuZDI6IGR1bW15U2hhcmUsIGVuY3J5cHRlZFJvdW5kMlNlc3Npb246ICdyMicgfSk7XG4gICAgY29uc3Qgcm91bmQzR2VuZXJhdG9yID0gc2lub24uc3R1YigpLnJlc29sdmVzKHsgc2lnbmF0dXJlU2hhcmVSb3VuZDM6IGR1bW15U2hhcmUgfSk7XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIGVkZHNhTVBDdjJVdGlscy5zaWduRWRkc2FNUEN2MlRzc1VzaW5nRXh0ZXJuYWxTaWduZXIoXG4gICAgICAgICAgeyB0eFJlcXVlc3Q6IG1vY2tUeFJlcXVlc3QsIHJlcUlkOiBuZXcgUmVxdWVzdFRyYWNlcigpIH0sXG4gICAgICAgICAgcm91bmQxR2VuZXJhdG9yIGFzIHVua25vd24gYXMgQ3VzdG9tRWRkc2FNUEN2MlNpZ25pbmdSb3VuZDFHZW5lcmF0aW5nRnVuY3Rpb24sXG4gICAgICAgICAgcm91bmQyR2VuZXJhdG9yIGFzIHVua25vd24gYXMgQ3VzdG9tRWRkc2FNUEN2MlNpZ25pbmdSb3VuZDJHZW5lcmF0aW5nRnVuY3Rpb24sXG4gICAgICAgICAgcm91bmQzR2VuZXJhdG9yIGFzIHVua25vd24gYXMgQ3VzdG9tRWRkc2FNUEN2MlNpZ25pbmdSb3VuZDNHZW5lcmF0aW5nRnVuY3Rpb25cbiAgICAgICAgKSxcbiAgICAgIC9NaXNzaW5nIHNpZ25hdHVyZSBzaGFyZXMgaW4gcm91bmQgMiB0eFJlcXVlc3QvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBwYXNzIGFybW9yZWQgQml0R28gcHVibGljIEdQRyBrZXkgdG8gcm91bmQgMiBhbmQgcm91bmQgMyBnZW5lcmF0b3JzJywgYXN5bmMgKCkgPT4ge1xuICAgIChtb2NrQml0Z28ucG9zdCBhcyBzaW5vbi5TaW5vblN0dWIpXG4gICAgICAub25DYWxsKDApXG4gICAgICAucmV0dXJucyhtYWtlUG9zdENoYWluKG1vY2tUeFJlcXVlc3QpKVxuICAgICAgLm9uQ2FsbCgxKVxuICAgICAgLnJldHVybnMobWFrZVBvc3RDaGFpbihtb2NrVHhSZXF1ZXN0Um91bmQyKSlcbiAgICAgIC5vbkNhbGwoMilcbiAgICAgIC5yZXR1cm5zKG1ha2VQb3N0Q2hhaW4obW9ja1R4UmVxdWVzdFJvdW5kMikpXG4gICAgICAub25DYWxsKDMpXG4gICAgICAucmV0dXJucyhtYWtlUG9zdENoYWluKG1vY2tUeFJlcXVlc3QpKTtcblxuICAgIGNvbnN0IHJvdW5kMUdlbmVyYXRvciA9IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh7XG4gICAgICBzaWduYXR1cmVTaGFyZVJvdW5kMTogZHVtbXlTaGFyZSxcbiAgICAgIHVzZXJHcGdQdWJLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uOiAncjEnLFxuICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleTogJ2tleScsXG4gICAgfSk7XG4gICAgY29uc3Qgcm91bmQyR2VuZXJhdG9yID0gc2lub24uc3R1YigpLnJlc29sdmVzKHsgc2lnbmF0dXJlU2hhcmVSb3VuZDI6IGR1bW15U2hhcmUsIGVuY3J5cHRlZFJvdW5kMlNlc3Npb246ICdyMicgfSk7XG4gICAgY29uc3Qgcm91bmQzR2VuZXJhdG9yID0gc2lub24uc3R1YigpLnJlc29sdmVzKHsgc2lnbmF0dXJlU2hhcmVSb3VuZDM6IGR1bW15U2hhcmUgfSk7XG5cbiAgICBhd2FpdCBlZGRzYU1QQ3YyVXRpbHMuc2lnbkVkZHNhTVBDdjJUc3NVc2luZ0V4dGVybmFsU2lnbmVyKFxuICAgICAgeyB0eFJlcXVlc3Q6IG1vY2tUeFJlcXVlc3QsIHJlcUlkOiBuZXcgUmVxdWVzdFRyYWNlcigpIH0sXG4gICAgICByb3VuZDFHZW5lcmF0b3IgYXMgdW5rbm93biBhcyBDdXN0b21FZGRzYU1QQ3YyU2lnbmluZ1JvdW5kMUdlbmVyYXRpbmdGdW5jdGlvbixcbiAgICAgIHJvdW5kMkdlbmVyYXRvciBhcyB1bmtub3duIGFzIEN1c3RvbUVkZHNhTVBDdjJTaWduaW5nUm91bmQyR2VuZXJhdGluZ0Z1bmN0aW9uLFxuICAgICAgcm91bmQzR2VuZXJhdG9yIGFzIHVua25vd24gYXMgQ3VzdG9tRWRkc2FNUEN2MlNpZ25pbmdSb3VuZDNHZW5lcmF0aW5nRnVuY3Rpb25cbiAgICApO1xuXG4gICAgY29uc3QgYXJtb3JlZEtleSA9IGJpdGdvR3BnUHViS2V5LmFybW9yKCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgcm91bmQyR2VuZXJhdG9yLmdldENhbGwoMCkuYXJnc1swXS5iaXRnb1B1YmxpY0dwZ0tleSxcbiAgICAgIGFybW9yZWRLZXksXG4gICAgICAncm91bmQgMiBzaG91bGQgcmVjZWl2ZSBhcm1vcmVkIEJpdEdvIEdQRyBrZXknXG4gICAgKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICByb3VuZDNHZW5lcmF0b3IuZ2V0Q2FsbCgwKS5hcmdzWzBdLmJpdGdvUHVibGljR3BnS2V5LFxuICAgICAgYXJtb3JlZEtleSxcbiAgICAgICdyb3VuZCAzIHNob3VsZCByZWNlaXZlIGFybW9yZWQgQml0R28gR1BHIGtleSdcbiAgICApO1xuICB9KTtcbn0pO1xuXG5mdW5jdGlvbiBieXRlc1RvV29yZChieXRlcz86IFVpbnQ4QXJyYXkgfCBudW1iZXJbXSk6IG51bWJlciB7XG4gIGlmICghKGJ5dGVzIGluc3RhbmNlb2YgVWludDhBcnJheSkgfHwgYnl0ZXMubGVuZ3RoICE9PSA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdieXRlcyBtdXN0IGJlIGEgVWludDhBcnJheSB3aXRoIGxlbmd0aCA0Jyk7XG4gIH1cblxuICByZXR1cm4gYnl0ZXMucmVkdWNlKChudW0sIGJ5dGUpID0+IG51bSAqIDB4MTAwICsgYnl0ZSwgMCk7XG59XG5cbmRlc2NyaWJlKCdFRERTQVV0aWxzLmlzRWRkc2FNcGNWMVNpZ25pbmdNYXRlcmlhbCcsICgpID0+IHtcbiAgY29uc3QgUEFTU1BIUkFTRSA9ICd0ZXN0LXBhc3NwaHJhc2UnO1xuXG4gIGNvbnN0IE1QQ3YxX01BVEVSSUFMX0JBQ0tVUCA9IHtcbiAgICB1U2hhcmU6IHsgaTogMSwgdDogMiwgbjogMywgeTogJ2FhYmJjYycsIHNlZWQ6ICdkZWFkYmVlZjAxMjM0NTY3JywgY2hhaW5jb2RlOiAnMDAnIH0sXG4gICAgYml0Z29ZU2hhcmU6IHsgaTogMywgajogMSwgeTogJ2FhYmJjYycsIHU6ICdiaXRnby11LXZhbHVlJywgY2hhaW5jb2RlOiAnMDAnIH0sXG4gICAgYmFja3VwWVNoYXJlOiB7IGk6IDIsIGo6IDEsIHk6ICdhYWJiY2MnLCB1OiAnYmFja3VwLXUtdmFsdWUnLCBjaGFpbmNvZGU6ICcwMCcgfSxcbiAgfTtcblxuICBjb25zdCBNUEN2MV9NQVRFUklBTF9VU0VSID0ge1xuICAgIHVTaGFyZTogeyBpOiAyLCB0OiAyLCBuOiAzLCB5OiAnYWFiYmNjJywgc2VlZDogJ2RlYWRiZWVmMDEyMzQ1NjcnLCBjaGFpbmNvZGU6ICcwMCcgfSxcbiAgICBiaXRnb1lTaGFyZTogeyBpOiAzLCBqOiAyLCB5OiAnYWFiYmNjJywgdTogJ2JpdGdvLXUtdmFsdWUnLCBjaGFpbmNvZGU6ICcwMCcgfSxcbiAgICB1c2VyWVNoYXJlOiB7IGk6IDEsIGo6IDIsIHk6ICdhYWJiY2MnLCB1OiAndXNlci11LXZhbHVlJywgY2hhaW5jb2RlOiAnMDAnIH0sXG4gIH07XG5cbiAgY29uc3QgTVBDdjJfQ0JPUl9CWVRFUyA9IEJ1ZmZlci5mcm9tKFsweGQ5LCAweDAxLCAweDA0LCAweGEzLCAweDYxLCAweDc4LCAweDE4LCAweDAwXSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gIGxldCBtb2NrQml0Z286IEJpdEdvQmFzZTtcbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgLy8gc2RrLWNvcmUgaGFzIG5vIGRldkRlcGVuZGVuY3kgb24gc2RrLWFwaS9hcmdvbjIsIHNvIHYyIGVudmVsb3BlcyBhcmUgc2ltdWxhdGVkIGhlcmUuXG4gICAgLy8gUmVhbCBiaXRnby5kZWNyeXB0IHJvdXRlcyB2MiB0byBBcmdvbjJpZDsgdGhlIHN0dWIgcmV0dXJucyBNUEN2MiBDQk9SIHBsYWludGV4dCBpbnN0ZWFkLlxuICAgIG1vY2tCaXRnbyA9IHtcbiAgICAgIGRlY3J5cHQ6IHNpbm9uLnN0dWIoKS5jYWxsc0Zha2UoYXN5bmMgKHBhcmFtczogeyBpbnB1dDogc3RyaW5nOyBwYXNzd29yZDogc3RyaW5nIH0pID0+IHtcbiAgICAgICAgaWYgKGlzVjJFbnZlbG9wZShwYXJhbXMuaW5wdXQpKSB7XG4gICAgICAgICAgcmV0dXJuIE1QQ3YyX0NCT1JfQllURVM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNqY2wuZGVjcnlwdChwYXJhbXMucGFzc3dvcmQsIHBhcmFtcy5pbnB1dCk7XG4gICAgICB9KSxcbiAgICB9IGFzIHVua25vd24gYXMgQml0R29CYXNlO1xuICB9KTtcblxuICBpdCgncmV0dXJucyB0cnVlIGZvciBNUEN2MSBTSkNMLWVuY3J5cHRlZCBrZXljYXJkIHdpdGggYmFja3VwWVNoYXJlICsgY29ycmVjdCBwYXNzcGhyYXNlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGVuY3J5cHRlZCA9IHNqY2wuZW5jcnlwdChQQVNTUEhSQVNFLCBKU09OLnN0cmluZ2lmeShNUEN2MV9NQVRFUklBTF9CQUNLVVApKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgRUREU0FVdGlscy5pc0VkZHNhTXBjVjFTaWduaW5nTWF0ZXJpYWwoZW5jcnlwdGVkLCBQQVNTUEhSQVNFKSwgdHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdyZXR1cm5zIHRydWUgZm9yIE1QQ3YxIFNKQ0wtZW5jcnlwdGVkIGtleWNhcmQgd2l0aCB1c2VyWVNoYXJlICsgY29ycmVjdCBwYXNzcGhyYXNlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGVuY3J5cHRlZCA9IHNqY2wuZW5jcnlwdChQQVNTUEhSQVNFLCBKU09OLnN0cmluZ2lmeShNUEN2MV9NQVRFUklBTF9VU0VSKSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IEVERFNBVXRpbHMuaXNFZGRzYU1wY1YxU2lnbmluZ01hdGVyaWFsKGVuY3J5cHRlZCwgUEFTU1BIUkFTRSksIHRydWUpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyBmYWxzZSBmb3IgTVBDdjIgQ0JPUiBjb250ZW50IHdyYXBwZWQgaW4gU0pDTCBlbnZlbG9wZSArIGNvcnJlY3QgcGFzc3BocmFzZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBlbmNyeXB0ZWQgPSBzamNsLmVuY3J5cHQoUEFTU1BIUkFTRSwgTVBDdjJfQ0JPUl9CWVRFUyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IEVERFNBVXRpbHMuaXNFZGRzYU1wY1YxU2lnbmluZ01hdGVyaWFsKGVuY3J5cHRlZCwgUEFTU1BIUkFTRSksIGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3JldHVybnMgZmFsc2UgZm9yIE1QQ3YyIEFyZ29uMmlkIGVudmVsb3BlICh2MikgKyBjb3JyZWN0IHBhc3NwaHJhc2UgKGZvcndhcmQtY29tcGF0KScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBmYWtlVjJFbnZlbG9wZSA9IEpTT04uc3RyaW5naWZ5KHsgdjogMiwgbTogNjU1MzYsIHQ6IDMsIHA6IDQsIHNhbHQ6ICdBQUFBJywgaXY6ICdBQUFBJywgY3Q6ICdBQUFBJyB9KTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgRUREU0FVdGlscy5pc0VkZHNhTXBjVjFTaWduaW5nTWF0ZXJpYWwoZmFrZVYyRW52ZWxvcGUsIFBBU1NQSFJBU0UsIG1vY2tCaXRnbyksIGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyBvbiB3cm9uZyBwYXNzcGhyYXNlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGVuY3J5cHRlZCA9IHNqY2wuZW5jcnlwdChQQVNTUEhSQVNFLCBKU09OLnN0cmluZ2lmeShNUEN2MV9NQVRFUklBTF9CQUNLVVApKTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgIEVERFNBVXRpbHMuaXNFZGRzYU1wY1YxU2lnbmluZ01hdGVyaWFsKGVuY3J5cHRlZCwgJ3dyb25nLXBhc3NwaHJhc2UnKSxcbiAgICAgIC9jY206IHRhZyBkb2Vzbid0IG1hdGNoL1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdyZXR1cm5zIGZhbHNlIHdoZW4gbmVpdGhlciBiYWNrdXBZU2hhcmUudSBub3IgdXNlcllTaGFyZS51IGlzIHByZXNlbnQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcGFydGlhbCA9IHsgdVNoYXJlOiB7IHNlZWQ6ICdhYmMnIH0sIGJpdGdvWVNoYXJlOiB7IHU6ICd4eXonIH0gfTtcbiAgICBjb25zdCBlbmNyeXB0ZWQgPSBzamNsLmVuY3J5cHQoUEFTU1BIUkFTRSwgSlNPTi5zdHJpbmdpZnkocGFydGlhbCkpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChhd2FpdCBFRERTQVV0aWxzLmlzRWRkc2FNcGNWMVNpZ25pbmdNYXRlcmlhbChlbmNyeXB0ZWQsIFBBU1NQSFJBU0UpLCBmYWxzZSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdzaWduUmVjb3ZlcnlFZGRzYU1QQ3YyJywgKCkgPT4ge1xuICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzAvMCc7XG5cbiAgaXQoJ3Nob3VsZCByZXR1cm4gYSA2NC1ieXRlIHNpZ25hdHVyZSB0aGF0IHZlcmlmaWVzIGFnYWluc3QgdGhlIGRlcml2ZWQgcHVibGljIGtleScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZywgYmFja3VwRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbSgnZGVhZGJlZWYnLCAnaGV4Jyk7XG4gICAgY29uc3QgY29tbW9uS2V5Q2hhaW4gPSB1c2VyRGtnLmdldENvbW1vbktleWNoYWluKCk7XG5cbiAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBFRERTQVV0aWxzLnNpZ25SZWNvdmVyeUVkZHNhTVBDdjIoXG4gICAgICBtZXNzYWdlLFxuICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICB1c2VyRGtnLmdldEtleVNoYXJlKCksXG4gICAgICBiYWNrdXBEa2cuZ2V0S2V5U2hhcmUoKSxcbiAgICAgIGNvbW1vbktleUNoYWluXG4gICAgKTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaWduYXR1cmUubGVuZ3RoLCA2NCk7XG5cbiAgICBjb25zdCBtcGMgPSBhd2FpdCBnZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgY29uc3QgZGVyaXZlZEtleWNoYWluID0gbXBjLmRlcml2ZVVuaGFyZGVuZWQoY29tbW9uS2V5Q2hhaW4sIGRlcml2YXRpb25QYXRoKTtcbiAgICBjb25zdCBwdWJsaWNLZXlCeXRlcyA9IEJ1ZmZlci5mcm9tKGRlcml2ZWRLZXljaGFpbi5zbGljZSgwLCA2NCksICdoZXgnKTtcbiAgICBjb25zdCBvayA9IGVkMjU1MTkudmVyaWZ5KG5ldyBVaW50OEFycmF5KHNpZ25hdHVyZSksIG5ldyBVaW50OEFycmF5KG1lc3NhZ2UpLCBuZXcgVWludDhBcnJheShwdWJsaWNLZXlCeXRlcykpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChvaywgdHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIHdoZW4gdmVyaWZ5aW5nIHRoZSBzaWduYXR1cmUgYWdhaW5zdCBhIGRpZmZlcmVudCBtZXNzYWdlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IFt1c2VyRGtnLCBiYWNrdXBEa2ddID0gYXdhaXQgTVBTVXRpbC5nZW5lcmF0ZUVkRHNhREtHS2V5U2hhcmVzKCk7XG4gICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdkZWFkYmVlZicsICdoZXgnKTtcbiAgICBjb25zdCBjb21tb25LZXlDaGFpbiA9IHVzZXJEa2cuZ2V0Q29tbW9uS2V5Y2hhaW4oKTtcblxuICAgIGNvbnN0IHNpZ25hdHVyZSA9IGF3YWl0IEVERFNBVXRpbHMuc2lnblJlY292ZXJ5RWRkc2FNUEN2MihcbiAgICAgIG1lc3NhZ2UsXG4gICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgIHVzZXJEa2cuZ2V0S2V5U2hhcmUoKSxcbiAgICAgIGJhY2t1cERrZy5nZXRLZXlTaGFyZSgpLFxuICAgICAgY29tbW9uS2V5Q2hhaW5cbiAgICApO1xuXG4gICAgY29uc3QgZGlmZmVyZW50TWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdjYWZlYmFiZScsICdoZXgnKTtcbiAgICBjb25zdCBtcGMgPSBhd2FpdCBnZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgY29uc3QgZGVyaXZlZEtleWNoYWluID0gbXBjLmRlcml2ZVVuaGFyZGVuZWQoY29tbW9uS2V5Q2hhaW4sIGRlcml2YXRpb25QYXRoKTtcbiAgICBjb25zdCBwdWJsaWNLZXlCeXRlcyA9IEJ1ZmZlci5mcm9tKGRlcml2ZWRLZXljaGFpbi5zbGljZSgwLCA2NCksICdoZXgnKTtcbiAgICBjb25zdCBvayA9IGVkMjU1MTkudmVyaWZ5KFxuICAgICAgbmV3IFVpbnQ4QXJyYXkoc2lnbmF0dXJlKSxcbiAgICAgIG5ldyBVaW50OEFycmF5KGRpZmZlcmVudE1lc3NhZ2UpLFxuICAgICAgbmV3IFVpbnQ4QXJyYXkocHVibGljS2V5Qnl0ZXMpXG4gICAgKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwob2ssIGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIGEgd3JvbmcgY29tbW9uS2V5Q2hhaW4gaXMgcHJvdmlkZWQgKHZlcmlmaWNhdGlvbiBtaXNtYXRjaCknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgW3VzZXJEa2csIGJhY2t1cERrZ10gPSBhd2FpdCBNUFNVdGlsLmdlbmVyYXRlRWREc2FES0dLZXlTaGFyZXMoKTtcbiAgICBjb25zdCBbd3JvbmdEa2ddID0gYXdhaXQgTVBTVXRpbC5nZW5lcmF0ZUVkRHNhREtHS2V5U2hhcmVzKCk7XG4gICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdkZWFkYmVlZicsICdoZXgnKTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgRUREU0FVdGlscy5zaWduUmVjb3ZlcnlFZGRzYU1QQ3YyKFxuICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICAgICAgdXNlckRrZy5nZXRLZXlTaGFyZSgpLFxuICAgICAgICAgIGJhY2t1cERrZy5nZXRLZXlTaGFyZSgpLFxuICAgICAgICAgIHdyb25nRGtnLmdldENvbW1vbktleWNoYWluKCkgLy8ga2V5IGNoYWluIGZyb20gYSBkaWZmZXJlbnQgd2FsbGV0XG4gICAgICAgICksXG4gICAgICAvRWREU0EgTVBDdjIgcmVjb3Zlcnkgc2lnbmF0dXJlIHZlcmlmaWNhdGlvbiBmYWlsZWQvXG4gICAgKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ2dldEVkZHNhU2lnbmluZ01hdGVyaWFsJywgKCkgPT4ge1xuICBjb25zdCBQQVNTUEhSQVNFID0gJ3Rlc3QtcGFzc3BocmFzZSc7XG5cbiAgY29uc3QgTVBDdjFfTUFURVJJQUwgPSB7XG4gICAgdVNoYXJlOiB7IGk6IDEsIHQ6IDIsIG46IDMsIHk6ICdhYWJiY2MnLCBzZWVkOiAnZGVhZGJlZWYwMTIzNDU2NycsIGNoYWluY29kZTogJzAwJyB9LFxuICAgIGJpdGdvWVNoYXJlOiB7IGk6IDMsIGo6IDEsIHk6ICdhYWJiY2MnLCB1OiAnYml0Z28tdS12YWx1ZScsIGNoYWluY29kZTogJzAwJyB9LFxuICAgIGJhY2t1cFlTaGFyZTogeyBpOiAyLCBqOiAxLCB5OiAnYWFiYmNjJywgdTogJ2JhY2t1cC11LXZhbHVlJywgY2hhaW5jb2RlOiAnMDAnIH0sXG4gIH07XG5cbiAgaXQoJ3JldHVybnMgeyB2ZXJzaW9uOiB2MSwgdXNlclBydiB9IGZvciBNUEN2MSBKU09OIGtleWNhcmQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZW5jcnlwdGVkID0gc2pjbC5lbmNyeXB0KFBBU1NQSFJBU0UsIEpTT04uc3RyaW5naWZ5KE1QQ3YxX01BVEVSSUFMKSk7XG4gICAgY29uc3QgZGVjcnlwdFN0dWIgPSBzaW5vbi5zdHViKCkucmVzb2x2ZXMoSlNPTi5zdHJpbmdpZnkoTVBDdjFfTUFURVJJQUwpKTtcbiAgICBjb25zdCBtb2NrQml0Z28gPSB7IGRlY3J5cHQ6IGRlY3J5cHRTdHViIH0gYXMgdW5rbm93biBhcyBCaXRHb0Jhc2U7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnZXRFZGRzYVNpZ25pbmdNYXRlcmlhbChlbmNyeXB0ZWQsIFBBU1NQSFJBU0UsIG1vY2tCaXRnbyk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LnZlcnNpb24sICd2MScpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbCgocmVzdWx0IGFzIHsgdmVyc2lvbjogJ3YxJzsgdXNlclBydjogc3RyaW5nIH0pLnVzZXJQcnYsIEpTT04uc3RyaW5naWZ5KE1QQ3YxX01BVEVSSUFMKSk7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UoZGVjcnlwdFN0dWIpO1xuICAgIHNpbm9uLmFzc2VydC5jYWxsZWRXaXRoTWF0Y2goZGVjcnlwdFN0dWIsIHsgaW5wdXQ6IHNpbm9uLm1hdGNoLnN0cmluZywgcGFzc3dvcmQ6IFBBU1NQSFJBU0UgfSk7XG4gIH0pO1xuXG4gIGl0KCdyZXR1cm5zIHsgdmVyc2lvbjogdjIsIGVuY3J5cHRlZFVzZXJLZXkgfSBmb3IgTVBDdjIgQ0JPUiBrZXljYXJkJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IE1QQ3YyX0NCT1JfQllURVMgPSBCdWZmZXIuZnJvbShbMHhkOSwgMHgwMSwgMHgwNCwgMHhhMywgMHg2MSwgMHg3OCwgMHgxOCwgMHgwMF0pLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICBjb25zdCBlbmNyeXB0ZWQgPSBzamNsLmVuY3J5cHQoUEFTU1BIUkFTRSwgTVBDdjJfQ0JPUl9CWVRFUyk7XG4gICAgY29uc3Qgbm9ybWFsaXplZEtleSA9IGVuY3J5cHRlZC5yZXBsYWNlKC9cXHMvZywgJycpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2V0RWRkc2FTaWduaW5nTWF0ZXJpYWwoZW5jcnlwdGVkLCBQQVNTUEhSQVNFKTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQudmVyc2lvbiwgJ3YyJyk7XG4gICAgYXNzZXJ0Lm9rKCdlbmNyeXB0ZWRVc2VyS2V5JyBpbiByZXN1bHQpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbCgocmVzdWx0IGFzIHsgdmVyc2lvbjogJ3YyJzsgZW5jcnlwdGVkVXNlcktleTogc3RyaW5nIH0pLmVuY3J5cHRlZFVzZXJLZXksIG5vcm1hbGl6ZWRLZXkpO1xuICB9KTtcblxuICBpdCgndGhyb3dzIHdpdGggY29udGV4dCBtZXNzYWdlIHdoZW4gZGVjcnlwdGlvbiBmYWlscycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBlbmNyeXB0ZWQgPSBzamNsLmVuY3J5cHQoUEFTU1BIUkFTRSwgSlNPTi5zdHJpbmdpZnkoTVBDdjFfTUFURVJJQUwpKTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+IGdldEVkZHNhU2lnbmluZ01hdGVyaWFsKGVuY3J5cHRlZCwgJ3dyb25nLXBhc3NwaHJhc2UnKSxcbiAgICAgIC9FcnJvciBkZWNyeXB0aW5nIHVzZXIga2V5Y2hhaW4vXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3JldHVybnMgdjEgdmlhIHNqY2wgZmFsbGJhY2sgd2hlbiBiaXRnbyBpcyBvbWl0dGVkJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGVuY3J5cHRlZCA9IHNqY2wuZW5jcnlwdChQQVNTUEhSQVNFLCBKU09OLnN0cmluZ2lmeShNUEN2MV9NQVRFUklBTCkpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdldEVkZHNhU2lnbmluZ01hdGVyaWFsKGVuY3J5cHRlZCwgUEFTU1BIUkFTRSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlc3VsdC52ZXJzaW9uLCAndjEnKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoKHJlc3VsdCBhcyB7IHZlcnNpb246ICd2MSc7IHVzZXJQcnY6IHN0cmluZyB9KS51c2VyUHJ2LCBKU09OLnN0cmluZ2lmeShNUEN2MV9NQVRFUklBTCkpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnaXNFZGRzYVNpZ25pbmdNYXRlcmlhbCcsICgpID0+IHtcbiAgaXQoJ3JldHVybnMgdHJ1ZSBmb3IgYSB2YWxpZCB2MSBzaGFwZScsICgpID0+IHtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNFZGRzYVNpZ25pbmdNYXRlcmlhbCh7IHZlcnNpb246ICd2MScsIHVzZXJQcnY6ICd7fScgfSksIHRydWUpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyB0cnVlIGZvciBhIHZhbGlkIHYyIHNoYXBlJywgKCkgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc0VkZHNhU2lnbmluZ01hdGVyaWFsKHsgdmVyc2lvbjogJ3YyJywgZW5jcnlwdGVkVXNlcktleTogJ2FiYzEyMycgfSksIHRydWUpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyBmYWxzZSBmb3IgYSB2MSBzaGFwZSB3aXRoIGEgbm9uLXN0cmluZyB1c2VyUHJ2JywgKCkgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc0VkZHNhU2lnbmluZ01hdGVyaWFsKHsgdmVyc2lvbjogJ3YxJywgdXNlclBydjogMTIzIH0pLCBmYWxzZSk7XG4gIH0pO1xuXG4gIGl0KCdyZXR1cm5zIGZhbHNlIGZvciBhIHYyIHNoYXBlIHdpdGggYSBub24tc3RyaW5nIGVuY3J5cHRlZFVzZXJLZXknLCAoKSA9PiB7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzRWRkc2FTaWduaW5nTWF0ZXJpYWwoeyB2ZXJzaW9uOiAndjInLCBlbmNyeXB0ZWRVc2VyS2V5OiAxMjMgfSksIGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3JldHVybnMgZmFsc2UgZm9yIGFuIHVucmVjb2duaXplZCB2ZXJzaW9uIHZhbHVlJywgKCkgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc0VkZHNhU2lnbmluZ01hdGVyaWFsKHsgdmVyc2lvbjogJ3YzJywgdXNlclBydjogJ3t9JyB9KSwgZmFsc2UpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyBmYWxzZSBmb3IgYW4gb2JqZWN0IG1pc3NpbmcgYSB2ZXJzaW9uIGZpZWxkJywgKCkgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc0VkZHNhU2lnbmluZ01hdGVyaWFsKHsgdXNlclBydjogJ3t9JyB9KSwgZmFsc2UpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyBmYWxzZSBmb3IgbnVsbCcsICgpID0+IHtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNFZGRzYVNpZ25pbmdNYXRlcmlhbChudWxsKSwgZmFsc2UpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyBmYWxzZSBmb3IgdW5kZWZpbmVkJywgKCkgPT4ge1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc0VkZHNhU2lnbmluZ01hdGVyaWFsKHVuZGVmaW5lZCksIGZhbHNlKTtcbiAgfSk7XG5cbiAgaXQoJ3JldHVybnMgZmFsc2UgZm9yIHByaW1pdGl2ZSB2YWx1ZXMnLCAoKSA9PiB7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzRWRkc2FTaWduaW5nTWF0ZXJpYWwoJ2Egc3RyaW5nJyksIGZhbHNlKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNFZGRzYVNpZ25pbmdNYXRlcmlhbCg0MiksIGZhbHNlKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNFZGRzYVNpZ25pbmdNYXRlcmlhbCh0cnVlKSwgZmFsc2UpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyBmYWxzZSBmb3IgYW4gQXJyYXlCdWZmZXIgKHJlZ3Jlc3Npb246IFdSVyBvcGVuU1NMQnl0ZXMgY29sbGlzaW9uKScsICgpID0+IHtcbiAgICAvLyBXUlcncyBnZW5lcmljIEVsZWN0cm9uICdyZWNvdmVyJyBJUEMgaGFuZGxlciBwYXNzZXMgb3BlblNTTEJ5dGVzIGFzIGEgc2Vjb25kXG4gICAgLy8gcG9zaXRpb25hbCBhcmd1bWVudCB0byBldmVyeSBjb2luJ3MgcmVjb3ZlcigpLCBjb2xsaWRpbmcgd2l0aCBwcmVjb21wdXRlZE1hdGVyaWFsXG4gICAgLy8gb24gY29pbnMgdGhhdCBhY2NlcHQgaXQuIFRoaXMgbXVzdCBiZSByZWplY3RlZCByYXRoZXIgdGhhbiBtaXNyZWFkIGFzIHNpZ25pbmcgbWF0ZXJpYWwuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzRWRkc2FTaWduaW5nTWF0ZXJpYWwobmV3IEFycmF5QnVmZmVyKDgpKSwgZmFsc2UpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnc2lnbkVkZHNhTXBjVjJSZWNvdmVyeVR4JywgKCkgPT4ge1xuICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzAvMCc7XG4gIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuXG4gIGNvbnN0IG1ha2VEZWNyeXB0Qml0Z28gPSAodXNlcktleUJhc2U2NDogc3RyaW5nLCBiYWNrdXBLZXlCYXNlNjQ6IHN0cmluZyk6IEJpdEdvQmFzZSA9PlxuICAgICh7XG4gICAgICBkZWNyeXB0OiBzaW5vbi5zdHViKCkub25GaXJzdENhbGwoKS5yZXNvbHZlcyh1c2VyS2V5QmFzZTY0KS5vblNlY29uZENhbGwoKS5yZXNvbHZlcyhiYWNrdXBLZXlCYXNlNjQpLFxuICAgIH0gYXMgdW5rbm93biBhcyBCaXRHb0Jhc2UpO1xuXG4gIGl0KCdyZXR1cm5zIGEgNjQtYnl0ZSBzaWduYXR1cmUgdGhhdCB2ZXJpZmllcyBhZ2FpbnN0IHRoZSBkZXJpdmVkIHB1YmxpYyBrZXknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgW3VzZXJEa2csIGJhY2t1cERrZ10gPSBhd2FpdCBNUFNVdGlsLmdlbmVyYXRlRWREc2FES0dLZXlTaGFyZXMoKTtcbiAgICBjb25zdCBtZXNzYWdlID0gQnVmZmVyLmZyb20oJ2RlYWRiZWVmJywgJ2hleCcpO1xuICAgIGNvbnN0IGNvbW1vbktleUNoYWluID0gdXNlckRrZy5nZXRDb21tb25LZXljaGFpbigpO1xuICAgIGNvbnN0IG1vY2tCaXRnbyA9IG1ha2VEZWNyeXB0Qml0Z28oXG4gICAgICB1c2VyRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgIGJhY2t1cERrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKS50b1N0cmluZygnYmFzZTY0JylcbiAgICApO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2lnbkVkZHNhTXBjVjJSZWNvdmVyeVR4KHtcbiAgICAgIG1lc3NhZ2UsXG4gICAgICB1c2VyS2V5OiAnZW5jcnlwdGVkLXVzZXIta2V5JyxcbiAgICAgIGJhY2t1cEtleTogJ2VuY3J5cHRlZC1iYWNrdXAta2V5JyxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICBiaXRnb0tleTogY29tbW9uS2V5Q2hhaW4sXG4gICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgIGJpdGdvOiBtb2NrQml0Z28sXG4gICAgfSk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0Lmxlbmd0aCwgNjQpO1xuICAgIGNvbnN0IG1wYyA9IGF3YWl0IGdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICBjb25zdCBkZXJpdmVkS2V5Y2hhaW4gPSBtcGMuZGVyaXZlVW5oYXJkZW5lZChjb21tb25LZXlDaGFpbiwgZGVyaXZhdGlvblBhdGgpO1xuICAgIGNvbnN0IHB1YmxpY0tleUJ5dGVzID0gQnVmZmVyLmZyb20oZGVyaXZlZEtleWNoYWluLnNsaWNlKDAsIDY0KSwgJ2hleCcpO1xuICAgIGNvbnN0IG9rID0gZWQyNTUxOS52ZXJpZnkobmV3IFVpbnQ4QXJyYXkocmVzdWx0KSwgbmV3IFVpbnQ4QXJyYXkobWVzc2FnZSksIG5ldyBVaW50OEFycmF5KHB1YmxpY0tleUJ5dGVzKSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKG9rLCB0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIGNvbW1vbktleUNoYWluIGRvZXMgbm90IG1hdGNoIGJpdGdvS2V5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IFt1c2VyRGtnLCBiYWNrdXBEa2ddID0gYXdhaXQgTVBTVXRpbC5nZW5lcmF0ZUVkRHNhREtHS2V5U2hhcmVzKCk7XG4gICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdkZWFkYmVlZicsICdoZXgnKTtcbiAgICBjb25zdCBtb2NrQml0Z28gPSBtYWtlRGVjcnlwdEJpdGdvKFxuICAgICAgdXNlckRrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICBiYWNrdXBEa2cuZ2V0UmVkdWNlZEtleVNoYXJlKCkudG9TdHJpbmcoJ2Jhc2U2NCcpXG4gICAgKTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgc2lnbkVkZHNhTXBjVjJSZWNvdmVyeVR4KHtcbiAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgIHVzZXJLZXk6ICdlbmNyeXB0ZWQtdXNlci1rZXknLFxuICAgICAgICAgIGJhY2t1cEtleTogJ2VuY3J5cHRlZC1iYWNrdXAta2V5JyxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICAgIGJpdGdvS2V5OiAnYmJiYicucmVwZWF0KDMyKSxcbiAgICAgICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgICBiaXRnbzogbW9ja0JpdGdvLFxuICAgICAgICB9KSxcbiAgICAgIC9jb21tb25LZXlDaGFpbiBmcm9tIGtleWNhcmQgZG9lcyBub3QgbWF0Y2ggYml0Z29LZXkvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Bhc3NlcyB1c2VyS2V5LCBiYWNrdXBLZXksIHBhc3NwaHJhc2UsIGFuZCBiaXRnbyB0byBnZXRFZGRzYU1wY1YyUmVjb3ZlcnlLZXlTaGFyZXNGcm9tUmVkdWNlZEtleScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBbdXNlckRrZywgYmFja3VwRGtnXSA9IGF3YWl0IE1QU1V0aWwuZ2VuZXJhdGVFZERzYURLR0tleVNoYXJlcygpO1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbSgnZGVhZGJlZWYnLCAnaGV4Jyk7XG4gICAgY29uc3QgZGVjcnlwdFN0dWIgPSBzaW5vblxuICAgICAgLnN0dWIoKVxuICAgICAgLm9uRmlyc3RDYWxsKClcbiAgICAgIC5yZXNvbHZlcyh1c2VyRGtnLmdldFJlZHVjZWRLZXlTaGFyZSgpLnRvU3RyaW5nKCdiYXNlNjQnKSlcbiAgICAgIC5vblNlY29uZENhbGwoKVxuICAgICAgLnJlc29sdmVzKGJhY2t1cERrZy5nZXRSZWR1Y2VkS2V5U2hhcmUoKS50b1N0cmluZygnYmFzZTY0JykpO1xuICAgIGNvbnN0IG1vY2tCaXRnbyA9IHsgZGVjcnlwdDogZGVjcnlwdFN0dWIgfSBhcyB1bmtub3duIGFzIEJpdEdvQmFzZTtcblxuICAgIGF3YWl0IHNpZ25FZGRzYU1wY1YyUmVjb3ZlcnlUeCh7XG4gICAgICBtZXNzYWdlLFxuICAgICAgdXNlcktleTogJ3Uta2V5JyxcbiAgICAgIGJhY2t1cEtleTogJ2Ita2V5JyxcbiAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICBiaXRnb0tleTogdXNlckRrZy5nZXRDb21tb25LZXljaGFpbigpLFxuICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICBiaXRnbzogbW9ja0JpdGdvLFxuICAgIH0pO1xuXG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZFdpdGgoZGVjcnlwdFN0dWIuZmlyc3RDYWxsLCB7IGlucHV0OiAndS1rZXknLCBwYXNzd29yZDogd2FsbGV0UGFzc3BocmFzZSB9KTtcbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkV2l0aChkZWNyeXB0U3R1Yi5zZWNvbmRDYWxsLCB7IGlucHV0OiAnYi1rZXknLCBwYXNzd29yZDogd2FsbGV0UGFzc3BocmFzZSB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ0VkZHNhTVBDdjJVdGlscy5jcmVhdGVLZXljaGFpbnNXaXRoRXh0ZXJuYWxTaWduZXInLCBmdW5jdGlvbiAoKSB7XG4gIGxldCB1dGlsczogRWRkc2FNUEN2MlV0aWxzO1xuICBsZXQgY2FsbGJhY2tzOiBFZGRzYU1QQ3YyS2V5R2VuQ2FsbGJhY2tzO1xuICBjb25zdCBlbnRlcnByaXNlID0gJ2VudGVycHJpc2UtaWQnO1xuICBjb25zdCBzZXNzaW9uSWQgPSAnc2Vzc2lvbi0wMDEnO1xuICBjb25zdCBjb21tb25LZXljaGFpbiA9ICdjb21tb24ta2V5Y2hhaW4taGV4JztcblxuICBjb25zdCB1c2VyU3RhdGUgPSB7IGVuY3J5cHRlZERhdGE6ICd1LWRhdGEnLCBlbmNyeXB0ZWREYXRhS2V5OiAndS1kYXRhLWtleScgfTtcbiAgY29uc3QgYmFja3VwU3RhdGUgPSB7IGVuY3J5cHRlZERhdGE6ICdiLWRhdGEnLCBlbmNyeXB0ZWREYXRhS2V5OiAnYi1kYXRhLWtleScgfTtcbiAgY29uc3QgdXNlclNpZ25lZE1zZzE6IE1QU1R5cGVzLk1QU1NpZ25lZE1lc3NhZ2UgPSB7IG1lc3NhZ2U6ICd1bXNnMScsIHNpZ25hdHVyZTogJ3VzaWcxJyB9O1xuICBjb25zdCBiYWNrdXBTaWduZWRNc2cxOiBNUFNUeXBlcy5NUFNTaWduZWRNZXNzYWdlID0geyBtZXNzYWdlOiAnYm1zZzEnLCBzaWduYXR1cmU6ICdic2lnMScgfTtcbiAgY29uc3QgdXNlclNpZ25lZE1zZzI6IE1QU1R5cGVzLk1QU1NpZ25lZE1lc3NhZ2UgPSB7IG1lc3NhZ2U6ICd1bXNnMicsIHNpZ25hdHVyZTogJ3VzaWcyJyB9O1xuICBjb25zdCBiYWNrdXBTaWduZWRNc2cyOiBNUFNUeXBlcy5NUFNTaWduZWRNZXNzYWdlID0geyBtZXNzYWdlOiAnYm1zZzInLCBzaWduYXR1cmU6ICdic2lnMicgfTtcbiAgY29uc3QgYml0Z29Nc2cxOiBNUFNUeXBlcy5NUFNTaWduZWRNZXNzYWdlID0geyBtZXNzYWdlOiAnYml0Z28tbXNnMScsIHNpZ25hdHVyZTogJ2JpdGdvLXNpZzEnIH07XG4gIGNvbnN0IGJpdGdvTXNnMjogTVBTVHlwZXMuTVBTU2lnbmVkTWVzc2FnZSA9IHsgbWVzc2FnZTogJ2JpdGdvLW1zZzInLCBzaWduYXR1cmU6ICdiaXRnby1zaWcyJyB9O1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIGNhbGxiYWNrcyA9IHtcbiAgICAgIGluaXRpYWxpemVDYWxsYmFjazogc2lub24uc3R1YigpLnJlc29sdmVzKHtcbiAgICAgICAgdXNlckdwZ1B1YmxpY0tleTogJ3VzZXItZ3BnLXB1YicsXG4gICAgICAgIGJhY2t1cEdwZ1B1YmxpY0tleTogJ2JhY2t1cC1ncGctcHViJyxcbiAgICAgICAgdXNlclN0YXRlLFxuICAgICAgICBiYWNrdXBTdGF0ZSxcbiAgICAgIH0pLFxuICAgICAgcm91bmQxQ2FsbGJhY2s6IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh7XG4gICAgICAgIHVzZXJTaWduZWRNc2cxLFxuICAgICAgICBiYWNrdXBTaWduZWRNc2cxLFxuICAgICAgICB1c2VyU3RhdGUsXG4gICAgICAgIGJhY2t1cFN0YXRlLFxuICAgICAgfSksXG4gICAgICByb3VuZDJDYWxsYmFjazogc2lub24uc3R1YigpLnJlc29sdmVzKHtcbiAgICAgICAgdXNlclNpZ25lZE1zZzIsXG4gICAgICAgIGJhY2t1cFNpZ25lZE1zZzIsXG4gICAgICAgIHVzZXJTdGF0ZSxcbiAgICAgICAgYmFja3VwU3RhdGUsXG4gICAgICB9KSxcbiAgICAgIGZpbmFsaXplQ2FsbGJhY2s6IHNpbm9uLnN0dWIoKS5yZXNvbHZlcyh7IGNvbW1vbktleWNoYWluIH0pLFxuICAgIH07XG5cbiAgICBjb25zdCBtb2NrQml0R28gPSB7XG4gICAgICBnZXRFbnY6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKCdkZXYnKSxcbiAgICB9IGFzIGFueTtcblxuICAgIGNvbnN0IG1vY2tLZXljaGFpbnMgPSB7XG4gICAgICBhZGQ6IHNpbm9uXG4gICAgICAgIC5zdHViKClcbiAgICAgICAgLmNhbGxzRmFrZSgocGFyYW1zOiBhbnkpID0+IFByb21pc2UucmVzb2x2ZSh7IGlkOiBgJHtwYXJhbXMuc291cmNlfS1rZXktaWRgLCBjb21tb25LZXljaGFpbiwgaXNNUEN2MjogdHJ1ZSB9KSksXG4gICAgfTtcblxuICAgIGNvbnN0IG1vY2tDb2luID0ge1xuICAgICAga2V5Y2hhaW5zOiBzaW5vbi5zdHViKCkucmV0dXJucyhtb2NrS2V5Y2hhaW5zKSxcbiAgICB9IGFzIGFueTtcblxuICAgIHV0aWxzID0gbmV3IEVkZHNhTVBDdjJVdGlscyhtb2NrQml0R28sIG1vY2tDb2luKTtcblxuICAgIHNpbm9uLnN0dWIodXRpbHMsICdnZXRCaXRnb0dwZ1B1YmtleUJhc2VkT25GZWF0dXJlRmxhZ3MnIGFzIGFueSkucmVzb2x2ZXMoeyBlZGRzYU1wY3YyUHVibGljS2V5OiBudWxsIH0pO1xuICAgICh1dGlscyBhcyBhbnkpLmJpdGdvRWRkc2FNcGN2MlB1YmxpY0dwZ0tleSA9IHsgYXJtb3I6ICgpID0+ICctLS0tLUJFR0lOIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS1cXG4nIH07XG5cbiAgICBzaW5vbi5zdHViKHV0aWxzLCAnc2VuZEtleUdlbmVyYXRpb25Sb3VuZDEnKS5yZXNvbHZlcyh7XG4gICAgICBzZXNzaW9uSWQ6IHNlc3Npb25JZCBhcyBhbnksXG4gICAgICBiaXRnb01zZzEsXG4gICAgfSk7XG4gICAgc2lub24uc3R1Yih1dGlscywgJ3NlbmRLZXlHZW5lcmF0aW9uUm91bmQyJykucmVzb2x2ZXMoe1xuICAgICAgc2Vzc2lvbklkOiBzZXNzaW9uSWQgYXMgYW55LFxuICAgICAgY29tbW9uUHVibGljS2V5Y2hhaW46IGNvbW1vbktleWNoYWluIGFzIGFueSxcbiAgICAgIGJpdGdvTXNnMixcbiAgICB9KTtcbiAgICBzaW5vbi5zdHViKHV0aWxzIGFzIGFueSwgJ2FkZEJpdGdvS2V5Y2hhaW4nKS5yZXNvbHZlcyh7IGlkOiAnYml0Z28ta2V5LWlkJywgY29tbW9uS2V5Y2hhaW4sIGlzTVBDdjI6IHRydWUgfSk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2lub24ucmVzdG9yZSgpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGludm9rZSBjYWxsYmFja3MgaW4gb3JkZXIgYW5kIHJldHVybiBrZXljaGFpbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qga2V5Y2hhaW5zID0gYXdhaXQgdXRpbHMuY3JlYXRlS2V5Y2hhaW5zV2l0aEV4dGVybmFsU2lnbmVyKHsgZW50ZXJwcmlzZSwgY2FsbGJhY2tzIH0pO1xuXG4gICAgYXNzZXJ0Lm9rKGtleWNoYWlucy51c2VyS2V5Y2hhaW4pO1xuICAgIGFzc2VydC5vayhrZXljaGFpbnMuYmFja3VwS2V5Y2hhaW4pO1xuICAgIGFzc2VydC5vayhrZXljaGFpbnMuYml0Z29LZXljaGFpbik7XG5cbiAgICBzaW5vbi5hc3NlcnQuY2FsbGVkT25jZShjYWxsYmFja3MuaW5pdGlhbGl6ZUNhbGxiYWNrIGFzIHNpbm9uLlNpbm9uU3R1Yik7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UoY2FsbGJhY2tzLnJvdW5kMUNhbGxiYWNrIGFzIHNpbm9uLlNpbm9uU3R1Yik7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UoY2FsbGJhY2tzLnJvdW5kMkNhbGxiYWNrIGFzIHNpbm9uLlNpbm9uU3R1Yik7XG4gICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2UoY2FsbGJhY2tzLmZpbmFsaXplQ2FsbGJhY2sgYXMgc2lub24uU2lub25TdHViKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBwYXNzIHJvdW5kMSByZXNwb25zZSB0byByb3VuZDJDYWxsYmFjaycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCB1dGlscy5jcmVhdGVLZXljaGFpbnNXaXRoRXh0ZXJuYWxTaWduZXIoeyBlbnRlcnByaXNlLCBjYWxsYmFja3MgfSk7XG5cbiAgICBjb25zdCByb3VuZDJBcmdzID0gKGNhbGxiYWNrcy5yb3VuZDJDYWxsYmFjayBhcyBzaW5vbi5TaW5vblN0dWIpLmZpcnN0Q2FsbC5hcmdzWzBdO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocm91bmQyQXJncy5iaXRnb01zZzEsIGJpdGdvTXNnMSk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChyb3VuZDJBcmdzLnVzZXJTaWduZWRNc2cxLCB1c2VyU2lnbmVkTXNnMSk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChyb3VuZDJBcmdzLmJhY2t1cFNpZ25lZE1zZzEsIGJhY2t1cFNpZ25lZE1zZzEpO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocm91bmQyQXJncy51c2VyU3RhdGUsIHVzZXJTdGF0ZSk7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChyb3VuZDJBcmdzLmJhY2t1cFN0YXRlLCBiYWNrdXBTdGF0ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcGFzcyByb3VuZDIgcmVzcG9uc2UgdG8gZmluYWxpemVDYWxsYmFjaycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCB1dGlscy5jcmVhdGVLZXljaGFpbnNXaXRoRXh0ZXJuYWxTaWduZXIoeyBlbnRlcnByaXNlLCBjYWxsYmFja3MgfSk7XG5cbiAgICBjb25zdCBmaW5hbGl6ZUFyZ3MgPSAoY2FsbGJhY2tzLmZpbmFsaXplQ2FsbGJhY2sgYXMgc2lub24uU2lub25TdHViKS5maXJzdENhbGwuYXJnc1swXTtcbiAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGZpbmFsaXplQXJncy5iaXRnb01zZzIsIGJpdGdvTXNnMik7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGZpbmFsaXplQXJncy5iaXRnb0NvbW1vbktleWNoYWluLCBjb21tb25LZXljaGFpbik7XG4gICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbChmaW5hbGl6ZUFyZ3MudXNlclN0YXRlLCB1c2VyU3RhdGUpO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoZmluYWxpemVBcmdzLmJhY2t1cFN0YXRlLCBiYWNrdXBTdGF0ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVnaXN0ZXIga2V5Y2hhaW5zIHdpdGggaXNNUEN2MjogdHJ1ZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBhd2FpdCB1dGlscy5jcmVhdGVLZXljaGFpbnNXaXRoRXh0ZXJuYWxTaWduZXIoeyBlbnRlcnByaXNlLCBjYWxsYmFja3MgfSk7XG5cbiAgICBjb25zdCBtb2NrS2V5Y2hhaW5zID0gKHV0aWxzIGFzIGFueSkuYmFzZUNvaW4ua2V5Y2hhaW5zKCk7XG4gICAgY29uc3QgYWRkQ2FsbHMgPSAobW9ja0tleWNoYWlucy5hZGQgYXMgc2lub24uU2lub25TdHViKS5nZXRDYWxscygpO1xuICAgIGFzc2VydC5vayhhZGRDYWxscy5sZW5ndGggPj0gMiwgJ2tleWNoYWlucy5hZGQgc2hvdWxkIGJlIGNhbGxlZCBmb3IgdXNlciBhbmQgYmFja3VwJyk7XG4gICAgZm9yIChjb25zdCBjYWxsIG9mIGFkZENhbGxzKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoY2FsbC5hcmdzWzBdLmlzTVBDdjIsIHRydWUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGNhbGwuYXJnc1swXS5rZXlUeXBlLCAndHNzJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoY2FsbC5hcmdzWzBdLmNvbW1vbktleWNoYWluLCBjb21tb25LZXljaGFpbik7XG4gICAgfVxuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlamVjdCB3aGVuIGZpbmFsaXplQ2FsbGJhY2sgcmV0dXJucyBtaXNtYXRjaGVkIGNvbW1vbktleWNoYWluJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIChjYWxsYmFja3MuZmluYWxpemVDYWxsYmFjayBhcyBzaW5vbi5TaW5vblN0dWIpLnJlc29sdmVzKHsgY29tbW9uS2V5Y2hhaW46ICdkaWZmZXJlbnQta2V5Y2hhaW4nIH0pO1xuXG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PiB1dGlscy5jcmVhdGVLZXljaGFpbnNXaXRoRXh0ZXJuYWxTaWduZXIoeyBlbnRlcnByaXNlLCBjYWxsYmFja3MgfSksXG4gICAgICAvQ29tbW9uIGtleWNoYWlucyBkbyBub3QgbWF0Y2gvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWplY3Qgd2hlbiByb3VuZDIgcmV0dXJucyBtaXNtYXRjaGVkIHNlc3Npb25JZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAodXRpbHMuc2VuZEtleUdlbmVyYXRpb25Sb3VuZDIgYXMgc2lub24uU2lub25TdHViKS5yZXNvbHZlcyh7XG4gICAgICBzZXNzaW9uSWQ6ICdkaWZmZXJlbnQtc2Vzc2lvbicgYXMgYW55LFxuICAgICAgY29tbW9uUHVibGljS2V5Y2hhaW46IGNvbW1vbktleWNoYWluIGFzIGFueSxcbiAgICAgIGJpdGdvTXNnMixcbiAgICB9KTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT4gdXRpbHMuY3JlYXRlS2V5Y2hhaW5zV2l0aEV4dGVybmFsU2lnbmVyKHsgZW50ZXJwcmlzZSwgY2FsbGJhY2tzIH0pLFxuICAgICAgL1JvdW5kIDEgYW5kIHJvdW5kIDIgc2Vzc2lvbiBJRHMgZG8gbm90IG1hdGNoL1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVqZWN0IHdoZW4gQml0R28gRWREU0EgTVBDdjIgR1BHIHB1YmxpYyBrZXkgaXMgbWlzc2luZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAodXRpbHMgYXMgYW55KS5iaXRnb0VkZHNhTXBjdjJQdWJsaWNHcGdLZXkgPSB1bmRlZmluZWQ7XG5cbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+IHV0aWxzLmNyZWF0ZUtleWNoYWluc1dpdGhFeHRlcm5hbFNpZ25lcih7IGVudGVycHJpc2UsIGNhbGxiYWNrcyB9KSxcbiAgICAgIC9GYWlsZWQgdG8gZ2V0IEJpdEdvIEVkRFNBIE1QQ3YyIEdQRyBwdWJsaWMga2V5L1xuICAgICk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdFZGRzYU1QQ3YyVXRpbHMuZ2V0TXBjVjJSZXRyb2ZpdERhdGFGcm9tTXBjVjFLZXlzJywgKCkgPT4ge1xuICBsZXQgdXRpbHM6IEVkZHNhTVBDdjJVdGlscztcbiAgLy8gUmVhbCAzLXBhcnR5IE1QQ3YxIEVkRFNBIGtleSBzaGFyZXM6IDEgPSB1c2VyLCAyID0gYmFja3VwLCAzID0gYml0Z28uXG4gIGxldCB1c2VyU2lnbmluZ01hdGVyaWFsOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgbGV0IGJhY2t1cFNpZ25pbmdNYXRlcmlhbDogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGxldCBleHBlY3RlZFVzZXJQU2hhcmU6IHsgeTogc3RyaW5nOyB1OiBzdHJpbmc7IGNoYWluY29kZTogc3RyaW5nIH07XG4gIGxldCBleHBlY3RlZEJhY2t1cFBTaGFyZTogeyB5OiBzdHJpbmc7IHU6IHN0cmluZzsgY2hhaW5jb2RlOiBzdHJpbmcgfTtcblxuICBiZWZvcmUoYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IE1QQyA9IGF3YWl0IGdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICBjb25zdCB1c2VyID0gTVBDLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgIGNvbnN0IGJhY2t1cCA9IE1QQy5rZXlTaGFyZSgyLCAyLCAzKTtcbiAgICBjb25zdCBiaXRnbyA9IE1QQy5rZXlTaGFyZSgzLCAyLCAzKTtcblxuICAgIGV4cGVjdGVkVXNlclBTaGFyZSA9IE1QQy5rZXlDb21iaW5lKHVzZXIudVNoYXJlLCBbYmFja3VwLnlTaGFyZXNbMV0sIGJpdGdvLnlTaGFyZXNbMV1dKS5wU2hhcmU7XG4gICAgZXhwZWN0ZWRCYWNrdXBQU2hhcmUgPSBNUEMua2V5Q29tYmluZShiYWNrdXAudVNoYXJlLCBbdXNlci55U2hhcmVzWzJdLCBiaXRnby55U2hhcmVzWzJdXSkucFNoYXJlO1xuXG4gICAgdXNlclNpZ25pbmdNYXRlcmlhbCA9IHtcbiAgICAgIHVTaGFyZTogdXNlci51U2hhcmUsXG4gICAgICBiaXRnb1lTaGFyZTogYml0Z28ueVNoYXJlc1sxXSxcbiAgICAgIGJhY2t1cFlTaGFyZTogYmFja3VwLnlTaGFyZXNbMV0sXG4gICAgfTtcbiAgICBiYWNrdXBTaWduaW5nTWF0ZXJpYWwgPSB7XG4gICAgICB1U2hhcmU6IGJhY2t1cC51U2hhcmUsXG4gICAgICBiaXRnb1lTaGFyZTogYml0Z28ueVNoYXJlc1syXSxcbiAgICAgIHVzZXJZU2hhcmU6IHVzZXIueVNoYXJlc1syXSxcbiAgICB9O1xuICB9KTtcblxuICBiZWZvcmVFYWNoKCgpID0+IHtcbiAgICBjb25zdCBtb2NrQml0R28gPSB7fSBhcyB1bmtub3duIGFzIEJpdEdvQmFzZTtcbiAgICBjb25zdCBtb2NrQ29pbiA9IHt9IGFzIHVua25vd24gYXMgSUJhc2VDb2luO1xuICAgIHV0aWxzID0gbmV3IEVkZHNhTVBDdjJVdGlscyhtb2NrQml0R28sIG1vY2tDb2luKTtcbiAgfSk7XG5cbiAgaXQoJ2Rlcml2ZXMgbWF0Y2hpbmcgZXhwZWN0ZWRQayBhbmQgY2hhaW5Db2RlIGZvciB1c2VyIGFuZCBiYWNrdXAgZnJvbSByZWFsIE1QQ3YxIGtleSBjb21iaW5lJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgdXNlclJldHJvZml0RGF0YSwgYmFja3VwUmV0cm9maXREYXRhIH0gPSBhd2FpdCB1dGlscy5nZXRNcGNWMlJldHJvZml0RGF0YUZyb21NcGNWMUtleXMoe1xuICAgICAgbXBjdjFVc2VyS2V5U2hhcmU6IEpTT04uc3RyaW5naWZ5KHVzZXJTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgbXBjdjFCYWNrdXBLZXlTaGFyZTogSlNPTi5zdHJpbmdpZnkoYmFja3VwU2lnbmluZ01hdGVyaWFsKSxcbiAgICB9KTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1c2VyUmV0cm9maXREYXRhLmV4cGVjdGVkUGssIGV4cGVjdGVkVXNlclBTaGFyZS55KTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFja3VwUmV0cm9maXREYXRhLmV4cGVjdGVkUGssIGV4cGVjdGVkQmFja3VwUFNoYXJlLnkpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1c2VyUmV0cm9maXREYXRhLmV4cGVjdGVkUGssIGJhY2t1cFJldHJvZml0RGF0YS5leHBlY3RlZFBrKTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1c2VyUmV0cm9maXREYXRhLmNoYWluQ29kZSwgZXhwZWN0ZWRVc2VyUFNoYXJlLmNoYWluY29kZSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJhY2t1cFJldHJvZml0RGF0YS5jaGFpbkNvZGUsIGV4cGVjdGVkQmFja3VwUFNoYXJlLmNoYWluY29kZSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHVzZXJSZXRyb2ZpdERhdGEuY2hhaW5Db2RlLCBiYWNrdXBSZXRyb2ZpdERhdGEuY2hhaW5Db2RlKTtcbiAgfSk7XG5cbiAgaXQoJ2Rlcml2ZXMgc19pXzAgYXMgdGhlIGNvbWJpbmVkIHBTaGFyZS51IChjbGFtcGVkIHNjYWxhcikgZm9yIGVhY2ggcGFydHknLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgeyB1c2VyUmV0cm9maXREYXRhLCBiYWNrdXBSZXRyb2ZpdERhdGEgfSA9IGF3YWl0IHV0aWxzLmdldE1wY1YyUmV0cm9maXREYXRhRnJvbU1wY1YxS2V5cyh7XG4gICAgICBtcGN2MVVzZXJLZXlTaGFyZTogSlNPTi5zdHJpbmdpZnkodXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICBtcGN2MUJhY2t1cEtleVNoYXJlOiBKU09OLnN0cmluZ2lmeShiYWNrdXBTaWduaW5nTWF0ZXJpYWwpLFxuICAgIH0pO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHVzZXJSZXRyb2ZpdERhdGEuc19pXzAsIGV4cGVjdGVkVXNlclBTaGFyZS51KTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYmFja3VwUmV0cm9maXREYXRhLnNfaV8wLCBleHBlY3RlZEJhY2t1cFBTaGFyZS51KTtcbiAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwodXNlclJldHJvZml0RGF0YS5zX2lfMCwgYmFja3VwUmV0cm9maXREYXRhLnNfaV8wKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyBpZiB1c2VyIGtleSBpcyBtaXNzaW5nIHVTaGFyZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBrZXlOb1VTaGFyZSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIGJpdGdvWVNoYXJlOiB1c2VyU2lnbmluZ01hdGVyaWFsLmJpdGdvWVNoYXJlLFxuICAgICAgYmFja3VwWVNoYXJlOiB1c2VyU2lnbmluZ01hdGVyaWFsLmJhY2t1cFlTaGFyZSxcbiAgICB9KTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+XG4gICAgICAgIHV0aWxzLmdldE1wY1YyUmV0cm9maXREYXRhRnJvbU1wY1YxS2V5cyh7XG4gICAgICAgICAgbXBjdjFVc2VyS2V5U2hhcmU6IGtleU5vVVNoYXJlLFxuICAgICAgICAgIG1wY3YxQmFja3VwS2V5U2hhcmU6IEpTT04uc3RyaW5naWZ5KGJhY2t1cFNpZ25pbmdNYXRlcmlhbCksXG4gICAgICAgIH0pLFxuICAgICAgL01QQ3YxIGtleSBtYXRlcmlhbCBtaXNzaW5nIHVTaGFyZS9cbiAgICApO1xuICB9KTtcblxuICBpdCgndGhyb3dzIGlmIHVzZXIga2V5IGlzIG1pc3NpbmcgYml0Z29ZU2hhcmUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qga2V5Tm9CaXRnb1lTaGFyZSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIHVTaGFyZTogdXNlclNpZ25pbmdNYXRlcmlhbC51U2hhcmUsXG4gICAgICBiYWNrdXBZU2hhcmU6IHVzZXJTaWduaW5nTWF0ZXJpYWwuYmFja3VwWVNoYXJlLFxuICAgIH0pO1xuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgdXRpbHMuZ2V0TXBjVjJSZXRyb2ZpdERhdGFGcm9tTXBjVjFLZXlzKHtcbiAgICAgICAgICBtcGN2MVVzZXJLZXlTaGFyZToga2V5Tm9CaXRnb1lTaGFyZSxcbiAgICAgICAgICBtcGN2MUJhY2t1cEtleVNoYXJlOiBKU09OLnN0cmluZ2lmeShiYWNrdXBTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgICB9KSxcbiAgICAgIC9NUEN2MSBrZXkgbWF0ZXJpYWwgbWlzc2luZyBiaXRnb1lTaGFyZS9cbiAgICApO1xuICB9KTtcblxuICBpdCgndGhyb3dzIGlmIHVzZXIga2V5IGlzIG1pc3NpbmcgYmFja3VwWVNoYXJlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGtleU5vQmFja3VwWVNoYXJlID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgdVNoYXJlOiB1c2VyU2lnbmluZ01hdGVyaWFsLnVTaGFyZSxcbiAgICAgIGJpdGdvWVNoYXJlOiB1c2VyU2lnbmluZ01hdGVyaWFsLmJpdGdvWVNoYXJlLFxuICAgIH0pO1xuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgdXRpbHMuZ2V0TXBjVjJSZXRyb2ZpdERhdGFGcm9tTXBjVjFLZXlzKHtcbiAgICAgICAgICBtcGN2MVVzZXJLZXlTaGFyZToga2V5Tm9CYWNrdXBZU2hhcmUsXG4gICAgICAgICAgbXBjdjFCYWNrdXBLZXlTaGFyZTogSlNPTi5zdHJpbmdpZnkoYmFja3VwU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgICAgfSksXG4gICAgICAvVXNlciBNUEN2MSBrZXkgbWF0ZXJpYWwgbWlzc2luZyBiYWNrdXBZU2hhcmUvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyBpZiBiYWNrdXAga2V5IGlzIG1pc3NpbmcgdVNoYXJlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGtleU5vVVNoYXJlID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgYml0Z29ZU2hhcmU6IGJhY2t1cFNpZ25pbmdNYXRlcmlhbC5iaXRnb1lTaGFyZSxcbiAgICAgIHVzZXJZU2hhcmU6IGJhY2t1cFNpZ25pbmdNYXRlcmlhbC51c2VyWVNoYXJlLFxuICAgIH0pO1xuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT5cbiAgICAgICAgdXRpbHMuZ2V0TXBjVjJSZXRyb2ZpdERhdGFGcm9tTXBjVjFLZXlzKHtcbiAgICAgICAgICBtcGN2MVVzZXJLZXlTaGFyZTogSlNPTi5zdHJpbmdpZnkodXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICAgICAgbXBjdjFCYWNrdXBLZXlTaGFyZToga2V5Tm9VU2hhcmUsXG4gICAgICAgIH0pLFxuICAgICAgL01QQ3YxIGtleSBtYXRlcmlhbCBtaXNzaW5nIHVTaGFyZS9cbiAgICApO1xuICB9KTtcblxuICBpdCgndGhyb3dzIGlmIGJhY2t1cCBrZXkgaXMgbWlzc2luZyBiaXRnb1lTaGFyZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBrZXlOb0JpdGdvWVNoYXJlID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgdVNoYXJlOiBiYWNrdXBTaWduaW5nTWF0ZXJpYWwudVNoYXJlLFxuICAgICAgdXNlcllTaGFyZTogYmFja3VwU2lnbmluZ01hdGVyaWFsLnVzZXJZU2hhcmUsXG4gICAgfSk7XG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICB1dGlscy5nZXRNcGNWMlJldHJvZml0RGF0YUZyb21NcGNWMUtleXMoe1xuICAgICAgICAgIG1wY3YxVXNlcktleVNoYXJlOiBKU09OLnN0cmluZ2lmeSh1c2VyU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgICAgICBtcGN2MUJhY2t1cEtleVNoYXJlOiBrZXlOb0JpdGdvWVNoYXJlLFxuICAgICAgICB9KSxcbiAgICAgIC9NUEN2MSBrZXkgbWF0ZXJpYWwgbWlzc2luZyBiaXRnb1lTaGFyZS9cbiAgICApO1xuICB9KTtcblxuICBpdCgndGhyb3dzIGlmIGJhY2t1cCBrZXkgaXMgbWlzc2luZyB1c2VyWVNoYXJlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGtleU5vVXNlcllTaGFyZSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIHVTaGFyZTogYmFja3VwU2lnbmluZ01hdGVyaWFsLnVTaGFyZSxcbiAgICAgIGJpdGdvWVNoYXJlOiBiYWNrdXBTaWduaW5nTWF0ZXJpYWwuYml0Z29ZU2hhcmUsXG4gICAgfSk7XG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAoKSA9PlxuICAgICAgICB1dGlscy5nZXRNcGNWMlJldHJvZml0RGF0YUZyb21NcGNWMUtleXMoe1xuICAgICAgICAgIG1wY3YxVXNlcktleVNoYXJlOiBKU09OLnN0cmluZ2lmeSh1c2VyU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgICAgICBtcGN2MUJhY2t1cEtleVNoYXJlOiBrZXlOb1VzZXJZU2hhcmUsXG4gICAgICAgIH0pLFxuICAgICAgL0JhY2t1cCBNUEN2MSBrZXkgbWF0ZXJpYWwgbWlzc2luZyB1c2VyWVNoYXJlL1xuICAgICk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdFZGRzYU1QQ3YyVXRpbHMuZ2V0S2V5RGF0YUZvclJldHJvZml0JywgKCkgPT4ge1xuICBsZXQgdXNlclNpZ25pbmdNYXRlcmlhbDogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGxldCBiYWNrdXBTaWduaW5nTWF0ZXJpYWw6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBsZXQgZXhwZWN0ZWRVc2VyUFNoYXJlOiB7IHk6IHN0cmluZzsgdTogc3RyaW5nOyBjaGFpbmNvZGU6IHN0cmluZyB9O1xuICBsZXQgZXhwZWN0ZWRCYWNrdXBQU2hhcmU6IHsgeTogc3RyaW5nOyB1OiBzdHJpbmc7IGNoYWluY29kZTogc3RyaW5nIH07XG5cbiAgYmVmb3JlKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBNUEMgPSBhd2FpdCBnZXRJbml0aWFsaXplZE1wY0luc3RhbmNlKCk7XG4gICAgY29uc3QgdXNlciA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICBjb25zdCBiYWNrdXAgPSBNUEMua2V5U2hhcmUoMiwgMiwgMyk7XG4gICAgY29uc3QgYml0Z28gPSBNUEMua2V5U2hhcmUoMywgMiwgMyk7XG5cbiAgICBleHBlY3RlZFVzZXJQU2hhcmUgPSBNUEMua2V5Q29tYmluZSh1c2VyLnVTaGFyZSwgW2JhY2t1cC55U2hhcmVzWzFdLCBiaXRnby55U2hhcmVzWzFdXSkucFNoYXJlO1xuICAgIGV4cGVjdGVkQmFja3VwUFNoYXJlID0gTVBDLmtleUNvbWJpbmUoYmFja3VwLnVTaGFyZSwgW3VzZXIueVNoYXJlc1syXSwgYml0Z28ueVNoYXJlc1syXV0pLnBTaGFyZTtcblxuICAgIHVzZXJTaWduaW5nTWF0ZXJpYWwgPSB7XG4gICAgICB1U2hhcmU6IHVzZXIudVNoYXJlLFxuICAgICAgYml0Z29ZU2hhcmU6IGJpdGdvLnlTaGFyZXNbMV0sXG4gICAgICBiYWNrdXBZU2hhcmU6IGJhY2t1cC55U2hhcmVzWzFdLFxuICAgIH07XG4gICAgYmFja3VwU2lnbmluZ01hdGVyaWFsID0ge1xuICAgICAgdVNoYXJlOiBiYWNrdXAudVNoYXJlLFxuICAgICAgYml0Z29ZU2hhcmU6IGJpdGdvLnlTaGFyZXNbMl0sXG4gICAgICB1c2VyWVNoYXJlOiB1c2VyLnlTaGFyZXNbMl0sXG4gICAgfTtcbiAgfSk7XG5cbiAgaXQoJ2Rlcml2ZXMgVVNFUiByZXRyb2ZpdCBkYXRhIG1hdGNoaW5nIGtleUNvbWJpbmUgcFNoYXJlIGZpZWxkcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXRyb2ZpdERhdGEgPSBhd2FpdCBFZGRzYU1QQ3YyVXRpbHMuZ2V0S2V5RGF0YUZvclJldHJvZml0KFxuICAgICAgSlNPTi5zdHJpbmdpZnkodXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICBNUEN2MlBhcnRpZXNFbnVtLlVTRVJcbiAgICApO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJldHJvZml0RGF0YS5zX2lfMCwgZXhwZWN0ZWRVc2VyUFNoYXJlLnUpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXRyb2ZpdERhdGEuZXhwZWN0ZWRQaywgZXhwZWN0ZWRVc2VyUFNoYXJlLnkpO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXRyb2ZpdERhdGEuY2hhaW5Db2RlLCBleHBlY3RlZFVzZXJQU2hhcmUuY2hhaW5jb2RlKTtcbiAgfSk7XG5cbiAgaXQoJ2Rlcml2ZXMgQkFDS1VQIHJldHJvZml0IGRhdGEgbWF0Y2hpbmcga2V5Q29tYmluZSBwU2hhcmUgZmllbGRzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJldHJvZml0RGF0YSA9IGF3YWl0IEVkZHNhTVBDdjJVdGlscy5nZXRLZXlEYXRhRm9yUmV0cm9maXQoXG4gICAgICBKU09OLnN0cmluZ2lmeShiYWNrdXBTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVBcbiAgICApO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJldHJvZml0RGF0YS5zX2lfMCwgZXhwZWN0ZWRCYWNrdXBQU2hhcmUudSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJldHJvZml0RGF0YS5leHBlY3RlZFBrLCBleHBlY3RlZEJhY2t1cFBTaGFyZS55KTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmV0cm9maXREYXRhLmNoYWluQ29kZSwgZXhwZWN0ZWRCYWNrdXBQU2hhcmUuY2hhaW5jb2RlKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyBpZiBVU0VSIG1hdGVyaWFsIGlzIG1pc3NpbmcgYmFja3VwWVNoYXJlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGtleU5vQmFja3VwWVNoYXJlID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgdVNoYXJlOiB1c2VyU2lnbmluZ01hdGVyaWFsLnVTaGFyZSxcbiAgICAgIGJpdGdvWVNoYXJlOiB1c2VyU2lnbmluZ01hdGVyaWFsLmJpdGdvWVNoYXJlLFxuICAgIH0pO1xuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT4gRWRkc2FNUEN2MlV0aWxzLmdldEtleURhdGFGb3JSZXRyb2ZpdChrZXlOb0JhY2t1cFlTaGFyZSwgTVBDdjJQYXJ0aWVzRW51bS5VU0VSKSxcbiAgICAgIC9Vc2VyIE1QQ3YxIGtleSBtYXRlcmlhbCBtaXNzaW5nIGJhY2t1cFlTaGFyZS9cbiAgICApO1xuICB9KTtcblxuICBpdCgndGhyb3dzIGlmIEJBQ0tVUCBtYXRlcmlhbCBpcyBtaXNzaW5nIHVzZXJZU2hhcmUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qga2V5Tm9Vc2VyWVNoYXJlID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgdVNoYXJlOiBiYWNrdXBTaWduaW5nTWF0ZXJpYWwudVNoYXJlLFxuICAgICAgYml0Z29ZU2hhcmU6IGJhY2t1cFNpZ25pbmdNYXRlcmlhbC5iaXRnb1lTaGFyZSxcbiAgICB9KTtcbiAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICgpID0+IEVkZHNhTVBDdjJVdGlscy5nZXRLZXlEYXRhRm9yUmV0cm9maXQoa2V5Tm9Vc2VyWVNoYXJlLCBNUEN2MlBhcnRpZXNFbnVtLkJBQ0tVUCksXG4gICAgICAvQmFja3VwIE1QQ3YxIGtleSBtYXRlcmlhbCBtaXNzaW5nIHVzZXJZU2hhcmUvXG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ1VTRVIgYW5kIEJBQ0tVUCBleHBlY3RlZFBrIGFuZCBjaGFpbkNvZGUgbWF0Y2ggd2hlbiBidWlsdCBmcm9tIHRoZSBzYW1lIHRocmVlIGtleVNoYXJlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB1c2VyUmV0cm9maXREYXRhID0gYXdhaXQgRWRkc2FNUEN2MlV0aWxzLmdldEtleURhdGFGb3JSZXRyb2ZpdChcbiAgICAgIEpTT04uc3RyaW5naWZ5KHVzZXJTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgTVBDdjJQYXJ0aWVzRW51bS5VU0VSXG4gICAgKTtcbiAgICBjb25zdCBiYWNrdXBSZXRyb2ZpdERhdGEgPSBhd2FpdCBFZGRzYU1QQ3YyVXRpbHMuZ2V0S2V5RGF0YUZvclJldHJvZml0KFxuICAgICAgSlNPTi5zdHJpbmdpZnkoYmFja3VwU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgIE1QQ3YyUGFydGllc0VudW0uQkFDS1VQXG4gICAgKTtcblxuICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1c2VyUmV0cm9maXREYXRhLmV4cGVjdGVkUGssIGJhY2t1cFJldHJvZml0RGF0YS5leHBlY3RlZFBrKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwodXNlclJldHJvZml0RGF0YS5jaGFpbkNvZGUsIGJhY2t1cFJldHJvZml0RGF0YS5jaGFpbkNvZGUpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnRWRkc2FNUEN2MlV0aWxzLmdldFVzZXJBbmRCYWNrdXBTZXNzaW9uJywgKCkgPT4ge1xuICBsZXQgdXRpbHM6IEVkZHNhTVBDdjJVdGlscztcbiAgbGV0IHVzZXJTaWduaW5nTWF0ZXJpYWw6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBsZXQgYmFja3VwU2lnbmluZ01hdGVyaWFsOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICBiZWZvcmUoYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IE1QQyA9IGF3YWl0IGdldEluaXRpYWxpemVkTXBjSW5zdGFuY2UoKTtcbiAgICBjb25zdCB1c2VyID0gTVBDLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgIGNvbnN0IGJhY2t1cCA9IE1QQy5rZXlTaGFyZSgyLCAyLCAzKTtcbiAgICBjb25zdCBiaXRnbyA9IE1QQy5rZXlTaGFyZSgzLCAyLCAzKTtcbiAgICB1c2VyU2lnbmluZ01hdGVyaWFsID0ge1xuICAgICAgdVNoYXJlOiB1c2VyLnVTaGFyZSxcbiAgICAgIGJpdGdvWVNoYXJlOiBiaXRnby55U2hhcmVzWzFdLFxuICAgICAgYmFja3VwWVNoYXJlOiBiYWNrdXAueVNoYXJlc1sxXSxcbiAgICB9O1xuICAgIGJhY2t1cFNpZ25pbmdNYXRlcmlhbCA9IHtcbiAgICAgIHVTaGFyZTogYmFja3VwLnVTaGFyZSxcbiAgICAgIGJpdGdvWVNoYXJlOiBiaXRnby55U2hhcmVzWzJdLFxuICAgICAgdXNlcllTaGFyZTogdXNlci55U2hhcmVzWzJdLFxuICAgIH07XG4gIH0pO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGNvbnN0IG1vY2tCaXRHbyA9IHt9IGFzIHVua25vd24gYXMgQml0R29CYXNlO1xuICAgIGNvbnN0IG1vY2tDb2luID0ge30gYXMgdW5rbm93biBhcyBJQmFzZUNvaW47XG4gICAgdXRpbHMgPSBuZXcgRWRkc2FNUEN2MlV0aWxzKG1vY2tCaXRHbywgbW9ja0NvaW4pO1xuICB9KTtcblxuICBhZnRlckVhY2goKCkgPT4ge1xuICAgIHNpbm9uLnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgaXQoJ3JldHVybnMgcGxhaW4gREtHIHNlc3Npb25zIHdoZW4gcmV0cm9maXQgaXMgdW5kZWZpbmVkJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHsgdXNlckRrZywgYmFja3VwRGtnIH0gPSBhd2FpdCAodXRpbHMgYXMgYW55KS5nZXRVc2VyQW5kQmFja3VwU2Vzc2lvbih1bmRlZmluZWQpO1xuICAgIGFzc2VydC5vayh1c2VyRGtnLCAndXNlciBES0cgc2hvdWxkIGJlIGNyZWF0ZWQnKTtcbiAgICBhc3NlcnQub2soYmFja3VwRGtnLCAnYmFja3VwIERLRyBzaG91bGQgYmUgY3JlYXRlZCcpO1xuICB9KTtcblxuICBpdCgncmV0dXJucyByZXRyb2ZpdC1zZWVkZWQgREtHIHNlc3Npb25zIHdoZW4gcmV0cm9maXQgcGF5bG9hZCBpcyBzdXBwbGllZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXRyb2ZpdCA9IHtcbiAgICAgIGRlY3J5cHRlZFVzZXJLZXk6IEpTT04uc3RyaW5naWZ5KHVzZXJTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgZGVjcnlwdGVkQmFja3VwS2V5OiBKU09OLnN0cmluZ2lmeShiYWNrdXBTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgd2FsbGV0SWQ6ICd3YWxsZXQtMTIzJyxcbiAgICB9O1xuICAgIGNvbnN0IHsgdXNlckRrZywgYmFja3VwRGtnIH0gPSBhd2FpdCAodXRpbHMgYXMgYW55KS5nZXRVc2VyQW5kQmFja3VwU2Vzc2lvbihyZXRyb2ZpdCk7XG4gICAgYXNzZXJ0Lm9rKHVzZXJEa2csICd1c2VyIERLRyBzaG91bGQgYmUgY3JlYXRlZCB3aXRoIHJldHJvZml0IGRhdGEnKTtcbiAgICBhc3NlcnQub2soYmFja3VwRGtnLCAnYmFja3VwIERLRyBzaG91bGQgYmUgY3JlYXRlZCB3aXRoIHJldHJvZml0IGRhdGEnKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ0VkZHNhTVBDdjJVdGlscy5jcmVhdGVLZXljaGFpbnMgd2l0aCByZXRyb2ZpdCB3aXJpbmcnLCAoKSA9PiB7XG4gIGxldCB1dGlsczogRWRkc2FNUEN2MlV0aWxzO1xuICBsZXQgdXNlclNpZ25pbmdNYXRlcmlhbDogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGxldCBiYWNrdXBTaWduaW5nTWF0ZXJpYWw6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBsZXQgYml0Z29HcGdQdWJsaWNLZXlBcm1vcmVkOiBzdHJpbmc7XG4gIGNvbnN0IGVudGVycHJpc2UgPSAnZW50ZXJwcmlzZS1pZCc7XG4gIGNvbnN0IHNlc3Npb25JZCA9ICdzZXNzaW9uLTAwMSc7XG4gIGNvbnN0IHdhbGxldElkID0gJ3dhbGxldC1yZXRyb2ZpdC0xMjMnO1xuXG4gIGJlZm9yZShhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgTVBDID0gYXdhaXQgZ2V0SW5pdGlhbGl6ZWRNcGNJbnN0YW5jZSgpO1xuICAgIGNvbnN0IHVzZXIgPSBNUEMua2V5U2hhcmUoMSwgMiwgMyk7XG4gICAgY29uc3QgYmFja3VwID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuICAgIGNvbnN0IGJpdGdvID0gTVBDLmtleVNoYXJlKDMsIDIsIDMpO1xuICAgIHVzZXJTaWduaW5nTWF0ZXJpYWwgPSB7XG4gICAgICB1U2hhcmU6IHVzZXIudVNoYXJlLFxuICAgICAgYml0Z29ZU2hhcmU6IGJpdGdvLnlTaGFyZXNbMV0sXG4gICAgICBiYWNrdXBZU2hhcmU6IGJhY2t1cC55U2hhcmVzWzFdLFxuICAgIH07XG4gICAgYmFja3VwU2lnbmluZ01hdGVyaWFsID0ge1xuICAgICAgdVNoYXJlOiBiYWNrdXAudVNoYXJlLFxuICAgICAgYml0Z29ZU2hhcmU6IGJpdGdvLnlTaGFyZXNbMl0sXG4gICAgICB1c2VyWVNoYXJlOiB1c2VyLnlTaGFyZXNbMl0sXG4gICAgfTtcbiAgICAvLyBHZW5lcmF0ZSBhIHJlYWwgRWQyNTUxOSBHUEcga2V5IHRvIHN0YW5kIGluIGZvciB0aGUgQml0R28gR1BHIGtleVxuICAgIGNvbnN0IGJpdGdvR3BnS2V5UGFpciA9IGF3YWl0IGdlbmVyYXRlR1BHS2V5UGFpcignZWQyNTUxOScpO1xuICAgIGJpdGdvR3BnUHVibGljS2V5QXJtb3JlZCA9IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXk7XG4gIH0pO1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGNvbnN0IG1vY2tCaXRHbyA9IHtcbiAgICAgIGdldEVudjogc2lub24uc3R1YigpLnJldHVybnMoJ2RldicpLFxuICAgICAgZW5jcnlwdDogc2lub24uc3R1YigpLnJlc29sdmVzKCdlbmNyeXB0ZWQnKSxcbiAgICB9IGFzIGFueTtcbiAgICBjb25zdCBtb2NrS2V5Y2hhaW5zID0ge1xuICAgICAgYWRkOiBzaW5vblxuICAgICAgICAuc3R1YigpXG4gICAgICAgIC5jYWxsc0Zha2UoKHBhcmFtczogYW55KSA9PlxuICAgICAgICAgIFByb21pc2UucmVzb2x2ZSh7IGlkOiBgJHtwYXJhbXMuc291cmNlfS1rZXktaWRgLCBjb21tb25LZXljaGFpbjogJ2EnLnJlcGVhdCgxMjgpLCBpc01QQ3YyOiB0cnVlIH0pXG4gICAgICAgICksXG4gICAgfTtcbiAgICBjb25zdCBtb2NrQ29pbiA9IHtcbiAgICAgIGtleWNoYWluczogc2lub24uc3R1YigpLnJldHVybnMobW9ja0tleWNoYWlucyksXG4gICAgfSBhcyBhbnk7XG5cbiAgICB1dGlscyA9IG5ldyBFZGRzYU1QQ3YyVXRpbHMobW9ja0JpdEdvLCBtb2NrQ29pbik7XG4gICAgc2lub24uc3R1Yih1dGlscywgJ2dldEJpdGdvR3BnUHVia2V5QmFzZWRPbkZlYXR1cmVGbGFncycgYXMgYW55KS5yZXNvbHZlcyh7IGVkZHNhTXBjdjJQdWJsaWNLZXk6IG51bGwgfSk7XG4gICAgLy8gVXNlIGEgcmVhbCBhcm1vcmVkIEdQRyBwdWJsaWMga2V5IHNvIHBncC5yZWFkS2V5KCkgc3VjY2VlZHMgaW5zaWRlIGNyZWF0ZUtleWNoYWluc1xuICAgICh1dGlscyBhcyBhbnkpLmJpdGdvRWRkc2FNcGN2MlB1YmxpY0dwZ0tleSA9IHsgYXJtb3I6ICgpID0+IGJpdGdvR3BnUHVibGljS2V5QXJtb3JlZCB9O1xuICAgIHNpbm9uLnN0dWIodXRpbHMgYXMgYW55LCAnYWRkQml0Z29LZXljaGFpbicpLnJlc29sdmVzKHsgaWQ6ICdiaXRnby1rZXktaWQnLCBjb21tb25LZXljaGFpbjogJ2EnLnJlcGVhdCgxMjgpIH0pO1xuICB9KTtcblxuICBhZnRlckVhY2goKCkgPT4ge1xuICAgIHNpbm9uLnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgaXQoJ3NwcmVhZHMgd2FsbGV0SWQgaW50byByb3VuZC0xIHBheWxvYWQgd2hlbiByZXRyb2ZpdCBpcyBwcm92aWRlZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBjYXB0dXJlZFBheWxvYWRzOiBhbnlbXSA9IFtdO1xuICAgIHNpbm9uLnN0dWIodXRpbHMsICdzZW5kS2V5R2VuZXJhdGlvblJvdW5kMScpLmNhbGxzRmFrZShhc3luYyAoX2VudGVycHJpc2U6IHN0cmluZywgcGF5bG9hZDogYW55KSA9PiB7XG4gICAgICBjYXB0dXJlZFBheWxvYWRzLnB1c2gocGF5bG9hZCk7XG4gICAgICAvLyBSZXR1cm4gYSBiYWQgYml0Z29Nc2cxIHRvIHNob3J0LWNpcmN1aXQgdGhlIGNlcmVtb255IGFmdGVyIFIxIGNhcHR1cmVcbiAgICAgIHJldHVybiB7IHNlc3Npb25JZDogc2Vzc2lvbklkIGFzIGFueSwgYml0Z29Nc2cxOiB7IG1lc3NhZ2U6ICcnLCBzaWduYXR1cmU6ICcnIH0gYXMgYW55IH07XG4gICAgfSk7XG5cbiAgICBjb25zdCByZXRyb2ZpdCA9IHtcbiAgICAgIGRlY3J5cHRlZFVzZXJLZXk6IEpTT04uc3RyaW5naWZ5KHVzZXJTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgZGVjcnlwdGVkQmFja3VwS2V5OiBKU09OLnN0cmluZ2lmeShiYWNrdXBTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgd2FsbGV0SWQsXG4gICAgfTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT4gdXRpbHMuY3JlYXRlS2V5Y2hhaW5zKHsgcGFzc3BocmFzZTogJ3Rlc3QnLCBlbnRlcnByaXNlLCByZXRyb2ZpdCB9KSxcbiAgICAgICgpID0+IHRydWVcbiAgICApO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGNhcHR1cmVkUGF5bG9hZHMubGVuZ3RoLCAxLCAnc2VuZEtleUdlbmVyYXRpb25Sb3VuZDEgc2hvdWxkIGJlIGNhbGxlZCBvbmNlJyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGNhcHR1cmVkUGF5bG9hZHNbMF0ud2FsbGV0SWQsIHdhbGxldElkLCAnd2FsbGV0SWQgbXVzdCBiZSBwcmVzZW50IGluIHJvdW5kLTEgcGF5bG9hZCcpO1xuICB9KTtcblxuICBpdCgnb21pdHMgd2FsbGV0SWQgZnJvbSByb3VuZC0xIHBheWxvYWQgd2hlbiByZXRyb2ZpdCBpcyBhYnNlbnQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY2FwdHVyZWRQYXlsb2FkczogYW55W10gPSBbXTtcbiAgICBzaW5vbi5zdHViKHV0aWxzLCAnc2VuZEtleUdlbmVyYXRpb25Sb3VuZDEnKS5jYWxsc0Zha2UoYXN5bmMgKF9lbnRlcnByaXNlOiBzdHJpbmcsIHBheWxvYWQ6IGFueSkgPT4ge1xuICAgICAgY2FwdHVyZWRQYXlsb2Fkcy5wdXNoKHBheWxvYWQpO1xuICAgICAgcmV0dXJuIHsgc2Vzc2lvbklkOiBzZXNzaW9uSWQgYXMgYW55LCBiaXRnb01zZzE6IHsgbWVzc2FnZTogJycsIHNpZ25hdHVyZTogJycgfSBhcyBhbnkgfTtcbiAgICB9KTtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgKCkgPT4gdXRpbHMuY3JlYXRlS2V5Y2hhaW5zKHsgcGFzc3BocmFzZTogJ3Rlc3QnLCBlbnRlcnByaXNlIH0pLFxuICAgICAgKCkgPT4gdHJ1ZVxuICAgICk7XG5cbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoY2FwdHVyZWRQYXlsb2Fkcy5sZW5ndGgsIDEsICdzZW5kS2V5R2VuZXJhdGlvblJvdW5kMSBzaG91bGQgYmUgY2FsbGVkIG9uY2UnKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwoY2FwdHVyZWRQYXlsb2Fkc1swXS53YWxsZXRJZCwgdW5kZWZpbmVkLCAnd2FsbGV0SWQgbXVzdCBiZSBhYnNlbnQgd2hlbiBubyByZXRyb2ZpdCcpO1xuICB9KTtcbn0pO1xuIl19
|