@bitgo/utxo-lib
Version:
Client-side Bitcoin JavaScript library
60 lines • 8.13 kB
JavaScript
;
/**
* V1 Safe Wallets are the oldest type of wallets that BitGo supports. They were
* created back in 2013-14 and don't use HD chains. Instead, they have only one
* P2SH address per wallet whose redeem script uses uncompressed public keys.
* */
Object.defineProperty(exports, "__esModule", { value: true });
exports.toUncompressedPub = toUncompressedPub;
exports.toCompressedPub = toCompressedPub;
exports.createLegacySafeOutputScript2of3 = createLegacySafeOutputScript2of3;
const assert = require("assert");
const secp256k1_1 = require("@bitgo/secp256k1");
const networks_1 = require("../../networks");
const types_1 = require("../types");
const bitcoinjs = require("bitcoinjs-lib");
function getPublicKeyBuffer(publicKey, { compressed = true } = {}) {
const res = secp256k1_1.ecc.pointCompress(publicKey, compressed);
if (res === null) {
throw new Error('invalid public key');
}
const buffer = Buffer.from(res);
assert.strictEqual(buffer.length, compressed ? 33 : 65);
return buffer;
}
function toUncompressedPub(pubkey) {
return getPublicKeyBuffer(pubkey, { compressed: false });
}
function toCompressedPub(pubkey) {
return getPublicKeyBuffer(pubkey, { compressed: true });
}
/** create p2sh scripts with uncompressed pubkeys */
function createLegacySafeOutputScript2of3(pubkeys, network) {
if (network) {
if (!(0, networks_1.isBitcoin)(network)) {
throw new Error(`unsupported network for legacy safe output script: ${network.coin}`);
}
}
if (!(0, types_1.isTriple)(pubkeys)) {
throw new Error(`must provide pubkey triple`);
}
pubkeys.forEach((key) => {
if (key.length !== pubkeys[0].length) {
throw new Error(`all pubkeys must have the same length`);
}
if (key.length !== 65 && key.length !== 33) {
// V1 Safe BTC wallets could contain either uncompressed or compressed pubkeys
throw new Error(`Unexpected key length ${key.length}, neither compressed nor uncompressed.`);
}
});
const script2of3 = bitcoinjs.payments.p2ms({ m: 2, pubkeys });
assert.ok(script2of3.output);
const scriptPubKey = bitcoinjs.payments.p2sh({ redeem: script2of3 });
assert.ok(scriptPubKey);
assert.ok(scriptPubKey.output);
return {
scriptPubKey: scriptPubKey.output,
redeemScript: script2of3.output,
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYml0Z28vbGVnYWN5c2FmZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7S0FJSzs7QUFtQkwsOENBRUM7QUFFRCwwQ0FFQztBQUdELDRFQXNDQztBQWhFRCxpQ0FBaUM7QUFDakMsZ0RBQWlEO0FBQ2pELDZDQUFvRDtBQUNwRCxvQ0FBb0M7QUFDcEMsMkNBQTJDO0FBRTNDLFNBQVMsa0JBQWtCLENBQUMsU0FBaUIsRUFBRSxFQUFFLFVBQVUsR0FBRyxJQUFJLEVBQUUsR0FBRyxFQUFFO0lBQ3ZFLE1BQU0sR0FBRyxHQUFHLGVBQU0sQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3hELElBQUksR0FBRyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUVoQyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3hELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFnQixpQkFBaUIsQ0FBQyxNQUFjO0lBQzlDLE9BQU8sa0JBQWtCLENBQUMsTUFBTSxFQUFFLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQUVELFNBQWdCLGVBQWUsQ0FBQyxNQUFjO0lBQzVDLE9BQU8sa0JBQWtCLENBQUMsTUFBTSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDMUQsQ0FBQztBQUVELG9EQUFvRDtBQUNwRCxTQUFnQixnQ0FBZ0MsQ0FDOUMsT0FBaUIsRUFDakIsT0FBaUI7SUFLakIsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNaLElBQUksQ0FBQyxJQUFBLG9CQUFTLEVBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLHNEQUFzRCxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN4RixDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksQ0FBQyxJQUFBLGdCQUFRLEVBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVELE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUN0QixJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3JDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztRQUMzRCxDQUFDO1FBQ0QsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEVBQUUsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEVBQUUsRUFBRSxDQUFDO1lBQzNDLDhFQUE4RTtZQUM5RSxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixHQUFHLENBQUMsTUFBTSx3Q0FBd0MsQ0FBQyxDQUFDO1FBQy9GLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztJQUVILE1BQU0sVUFBVSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQzlELE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRTdCLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDckUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN4QixNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUUvQixPQUFPO1FBQ0wsWUFBWSxFQUFFLFlBQVksQ0FBQyxNQUFNO1FBQ2pDLFlBQVksRUFBRSxVQUFVLENBQUMsTUFBTTtLQUNoQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVjEgU2FmZSBXYWxsZXRzIGFyZSB0aGUgb2xkZXN0IHR5cGUgb2Ygd2FsbGV0cyB0aGF0IEJpdEdvIHN1cHBvcnRzLiBUaGV5IHdlcmVcbiAqIGNyZWF0ZWQgYmFjayBpbiAyMDEzLTE0IGFuZCBkb24ndCB1c2UgSEQgY2hhaW5zLiBJbnN0ZWFkLCB0aGV5IGhhdmUgb25seSBvbmVcbiAqIFAyU0ggYWRkcmVzcyBwZXIgd2FsbGV0IHdob3NlIHJlZGVlbSBzY3JpcHQgdXNlcyB1bmNvbXByZXNzZWQgcHVibGljIGtleXMuXG4gKiAqL1xuXG5pbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGVjYyBhcyBlY2NMaWIgfSBmcm9tICdAYml0Z28vc2VjcDI1NmsxJztcbmltcG9ydCB7IGlzQml0Y29pbiwgTmV0d29yayB9IGZyb20gJy4uLy4uL25ldHdvcmtzJztcbmltcG9ydCB7IGlzVHJpcGxlIH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0ICogYXMgYml0Y29pbmpzIGZyb20gJ2JpdGNvaW5qcy1saWInO1xuXG5mdW5jdGlvbiBnZXRQdWJsaWNLZXlCdWZmZXIocHVibGljS2V5OiBCdWZmZXIsIHsgY29tcHJlc3NlZCA9IHRydWUgfSA9IHt9KTogQnVmZmVyIHtcbiAgY29uc3QgcmVzID0gZWNjTGliLnBvaW50Q29tcHJlc3MocHVibGljS2V5LCBjb21wcmVzc2VkKTtcbiAgaWYgKHJlcyA9PT0gbnVsbCkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBwdWJsaWMga2V5Jyk7XG4gIH1cbiAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmZyb20ocmVzKTtcblxuICBhc3NlcnQuc3RyaWN0RXF1YWwoYnVmZmVyLmxlbmd0aCwgY29tcHJlc3NlZCA/IDMzIDogNjUpO1xuICByZXR1cm4gYnVmZmVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9VbmNvbXByZXNzZWRQdWIocHVia2V5OiBCdWZmZXIpOiBCdWZmZXIge1xuICByZXR1cm4gZ2V0UHVibGljS2V5QnVmZmVyKHB1YmtleSwgeyBjb21wcmVzc2VkOiBmYWxzZSB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvQ29tcHJlc3NlZFB1YihwdWJrZXk6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gIHJldHVybiBnZXRQdWJsaWNLZXlCdWZmZXIocHVia2V5LCB7IGNvbXByZXNzZWQ6IHRydWUgfSk7XG59XG5cbi8qKiBjcmVhdGUgcDJzaCBzY3JpcHRzIHdpdGggdW5jb21wcmVzc2VkIHB1YmtleXMgKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVMZWdhY3lTYWZlT3V0cHV0U2NyaXB0Mm9mMyhcbiAgcHVia2V5czogQnVmZmVyW10sXG4gIG5ldHdvcms/OiBOZXR3b3JrXG4pOiB7XG4gIHNjcmlwdFB1YktleTogQnVmZmVyO1xuICByZWRlZW1TY3JpcHQ6IEJ1ZmZlcjtcbn0ge1xuICBpZiAobmV0d29yaykge1xuICAgIGlmICghaXNCaXRjb2luKG5ldHdvcmspKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIG5ldHdvcmsgZm9yIGxlZ2FjeSBzYWZlIG91dHB1dCBzY3JpcHQ6ICR7bmV0d29yay5jb2lufWApO1xuICAgIH1cbiAgfVxuXG4gIGlmICghaXNUcmlwbGUocHVia2V5cykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG11c3QgcHJvdmlkZSBwdWJrZXkgdHJpcGxlYCk7XG4gIH1cblxuICBwdWJrZXlzLmZvckVhY2goKGtleSkgPT4ge1xuICAgIGlmIChrZXkubGVuZ3RoICE9PSBwdWJrZXlzWzBdLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBhbGwgcHVia2V5cyBtdXN0IGhhdmUgdGhlIHNhbWUgbGVuZ3RoYCk7XG4gICAgfVxuICAgIGlmIChrZXkubGVuZ3RoICE9PSA2NSAmJiBrZXkubGVuZ3RoICE9PSAzMykge1xuICAgICAgLy8gVjEgU2FmZSBCVEMgd2FsbGV0cyBjb3VsZCBjb250YWluIGVpdGhlciB1bmNvbXByZXNzZWQgb3IgY29tcHJlc3NlZCBwdWJrZXlzXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQga2V5IGxlbmd0aCAke2tleS5sZW5ndGh9LCBuZWl0aGVyIGNvbXByZXNzZWQgbm9yIHVuY29tcHJlc3NlZC5gKTtcbiAgICB9XG4gIH0pO1xuXG4gIGNvbnN0IHNjcmlwdDJvZjMgPSBiaXRjb2luanMucGF5bWVudHMucDJtcyh7IG06IDIsIHB1YmtleXMgfSk7XG4gIGFzc2VydC5vayhzY3JpcHQyb2YzLm91dHB1dCk7XG5cbiAgY29uc3Qgc2NyaXB0UHViS2V5ID0gYml0Y29pbmpzLnBheW1lbnRzLnAyc2goeyByZWRlZW06IHNjcmlwdDJvZjMgfSk7XG4gIGFzc2VydC5vayhzY3JpcHRQdWJLZXkpO1xuICBhc3NlcnQub2soc2NyaXB0UHViS2V5Lm91dHB1dCk7XG5cbiAgcmV0dXJuIHtcbiAgICBzY3JpcHRQdWJLZXk6IHNjcmlwdFB1YktleS5vdXRwdXQsXG4gICAgcmVkZWVtU2NyaXB0OiBzY3JpcHQyb2YzLm91dHB1dCxcbiAgfTtcbn1cbiJdfQ==