UNPKG

bitcore-wallet-client

Version:
202 lines 8.44 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Verifier = void 0; const crypto_wallet_core_1 = require("crypto-wallet-core"); const lodash_1 = __importDefault(require("lodash")); const preconditions_1 = require("preconditions"); const common_1 = require("./common"); const log_1 = __importDefault(require("./log")); const $ = (0, preconditions_1.singleton)(); const BCHAddress = crypto_wallet_core_1.BitcoreLibCash.Address; class Verifier { static useRegtest() { this._useRegtest = true; } static useTestnet() { this._useRegtest = false; } static checkAddress(credentials, address, escrowInputs) { $.checkState(credentials.isComplete(), 'Failed state: credentials at <checkAddress>'); let network = credentials.network; if (network === 'testnet' && this._useRegtest) { network = 'regtest'; } var local = common_1.Utils.deriveAddress(address.type || credentials.addressType, credentials.publicKeyRing, address.path, credentials.m, network, credentials.chain, escrowInputs, credentials.hardwareSourcePublicKey, credentials.clientDerivedPublicKey); return (local.address == address.address && lodash_1.default.difference(local.publicKeys, address.publicKeys).length === 0); } static checkCopayers(credentials, copayers) { $.checkState(credentials.walletPrivKey, 'Failed state: credentials at <checkCopayers>'); var walletPubKey = crypto_wallet_core_1.BitcoreLib.PrivateKey.fromString(credentials.walletPrivKey) .toPublicKey() .toString(); if (copayers.length != credentials.n) { log_1.default.error('Missing public keys in server response'); return false; } var uniq = []; var error; for (const copayer of copayers || []) { if (error) return; if (uniq[copayers.xPubKey]++) { log_1.default.error('Repeated public keys in server response'); error = true; } if (!(copayer.encryptedName || copayer.name) || !copayer.xPubKey || !copayer.requestPubKey || !copayer.signature) { log_1.default.error('Missing copayer fields in server response'); error = true; } else { var hash = common_1.Utils.getCopayerHash(copayer.encryptedName || copayer.name, copayer.xPubKey, copayer.requestPubKey); if (!common_1.Utils.verifyMessage(hash, copayer.signature, walletPubKey)) { log_1.default.error('Invalid signatures in server response'); error = true; } } } if (error) return false; if (!copayers.map(c => c.xPubKey).includes(credentials.xPubKey)) { log_1.default.error('Server response does not contains our public keys'); return false; } return true; } static checkProposalCreation(args, txp, encryptingKey) { var strEqual = (str1, str2) => { return (!str1 && !str2) || str1 === str2; }; if (txp.outputs.length != args.outputs.length) return false; for (var i = 0; i < txp.outputs.length; i++) { var o1 = txp.outputs[i]; var o2 = args.outputs[i]; if (!strEqual(o1.toAddress, o2.toAddress)) return false; if (!strEqual(o1.script, o2.script)) return false; if (o1.amount != o2.amount) return false; var decryptedMessage = null; try { decryptedMessage = common_1.Utils.decryptMessage(o2.message, encryptingKey); } catch (e) { return false; } if (!strEqual(o1.message, decryptedMessage)) return false; } var changeAddress; if (txp.changeAddress) { changeAddress = txp.changeAddress.address; } if (args.changeAddress && !strEqual(changeAddress, args.changeAddress)) return false; if (typeof args.feePerKb === 'number' && txp.feePerKb != args.feePerKb) return false; if (!strEqual(txp.payProUrl, args.payProUrl)) return false; var decryptedMessage = null; try { decryptedMessage = common_1.Utils.decryptMessage(args.message, encryptingKey); } catch (e) { return false; } if (!strEqual(txp.message, decryptedMessage)) return false; if ((args.customData || txp.customData) && !lodash_1.default.isEqual(txp.customData, args.customData)) return false; return true; } static checkTxProposalSignature(credentials, txp) { var _a; $.checkArgument(txp.creatorId); $.checkState(credentials.isComplete(), 'Failed state: credentials at checkTxProposalSignature'); var chain = ((_a = txp.chain) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || common_1.Utils.getChain(txp.coin); var creatorKeys = (credentials.publicKeyRing || []).find(item => { if (common_1.Utils.xPubToCopayerId(chain, item.xPubKey) === txp.creatorId) return true; }); if (!creatorKeys) return false; var creatorSigningPubKey; if (txp.proposalSignaturePubKey) { if (!common_1.Utils.verifyRequestPubKey(txp.proposalSignaturePubKey, txp.proposalSignaturePubKeySig, creatorKeys.xPubKey)) return false; creatorSigningPubKey = txp.proposalSignaturePubKey; } else { creatorSigningPubKey = creatorKeys.requestPubKey; } if (!creatorSigningPubKey) return false; var hash; if (parseInt(txp.version) >= 3) { var t = common_1.Utils.buildTx(txp); hash = t.uncheckedSerialize(); } else { throw new Error('Transaction proposal not supported'); } log_1.default.debug('Regenerating & verifying tx proposal hash -> Hash: ', hash, ' Signature: ', txp.proposalSignature); const verified = common_1.Utils.verifyMessage(hash, txp.proposalSignature, creatorSigningPubKey); if (!verified && !txp.prePublishRaw) return false; if (!verified && txp.prePublishRaw && !common_1.Utils.verifyMessage(txp.prePublishRaw, txp.proposalSignature, creatorSigningPubKey)) return false; if (common_1.Constants.UTXO_CHAINS.includes(chain)) { if (!this.checkAddress(credentials, txp.changeAddress)) { return false; } if (txp.escrowAddress && !this.checkAddress(credentials, txp.escrowAddress, txp.inputs)) { return false; } } return true; } static checkPaypro(txp, payproOpts) { var toAddress, amount, feeRate; if (parseInt(txp.version) >= 3) { toAddress = txp.outputs[0].toAddress; amount = txp.amount; if (txp.feePerKb) { feeRate = txp.feePerKb / 1024; } } else { toAddress = txp.toAddress; amount = txp.amount; } if (amount != (payproOpts.instructions || []).reduce((sum, i) => sum += i.amount, 0)) return false; if (txp.coin == 'btc' && toAddress != payproOpts.instructions[0].toAddress) return false; if (txp.coin == 'bch' && new BCHAddress(toAddress).toString() != new BCHAddress(payproOpts.instructions[0].toAddress).toString()) return false; return true; } static checkTxProposal(credentials, txp, opts) { opts = opts || {}; if (!this.checkTxProposalSignature(credentials, txp)) return false; if (opts.paypro && !this.checkPaypro(txp, opts.paypro)) return false; return true; } } exports.Verifier = Verifier; Verifier._useRegtest = false; //# sourceMappingURL=verifier.js.map