@unisat/wallet-sdk
Version:
UniSat Wallet SDK
160 lines (159 loc) • 7.68 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyMessageOfBIP322Simple = exports.signMessageOfBIP322Simple = exports.getSignatureFromPsbtOfBIP322Simple = exports.genPsbtOfBIP322Simple = void 0;
const varuint_bitcoin_1 = require("varuint-bitcoin");
const address_1 = require("../address");
const bitcoin_core_1 = require("../bitcoin-core");
const network_1 = require("../network");
const types_1 = require("../types");
const utils_1 = require("../utils");
function bip0322_hash(message) {
const { sha256 } = bitcoin_core_1.bitcoin.crypto;
const tag = 'BIP0322-signed-message';
const tagHash = sha256(Buffer.from(tag));
const result = sha256(Buffer.concat([tagHash, tagHash, Buffer.from(message)]));
return result.toString('hex');
}
function genPsbtOfBIP322Simple({ message, address, networkType }) {
const outputScript = (0, address_1.addressToScriptPk)(address, networkType);
const addressType = (0, address_1.getAddressType)(address, networkType);
const supportedTypes = [types_1.AddressType.P2WPKH, types_1.AddressType.P2TR, types_1.AddressType.M44_P2WPKH, types_1.AddressType.M44_P2TR];
if (supportedTypes.includes(addressType) == false) {
throw new Error('Not support address type to sign');
}
const prevoutHash = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex');
const prevoutIndex = 0xffffffff;
const sequence = 0;
const scriptSig = Buffer.concat([Buffer.from('0020', 'hex'), Buffer.from(bip0322_hash(message), 'hex')]);
const txToSpend = new bitcoin_core_1.bitcoin.Transaction();
txToSpend.version = 0;
txToSpend.addInput(prevoutHash, prevoutIndex, sequence, scriptSig);
txToSpend.addOutput(outputScript, 0);
const psbtToSign = new bitcoin_core_1.bitcoin.Psbt();
psbtToSign.setVersion(0);
psbtToSign.addInput({
hash: txToSpend.getHash(),
index: 0,
sequence: 0,
witnessUtxo: {
script: outputScript,
value: 0
}
});
psbtToSign.addOutput({ script: Buffer.from('6a', 'hex'), value: 0 });
return psbtToSign;
}
exports.genPsbtOfBIP322Simple = genPsbtOfBIP322Simple;
function getSignatureFromPsbtOfBIP322Simple(psbt) {
const txToSign = psbt.extractTransaction();
function encodeVarString(b) {
return Buffer.concat([(0, varuint_bitcoin_1.encode)(b.byteLength), b]);
}
const len = (0, varuint_bitcoin_1.encode)(txToSign.ins[0].witness.length);
const result = Buffer.concat([len, ...txToSign.ins[0].witness.map((w) => encodeVarString(w))]);
const signature = result.toString('base64');
return signature;
}
exports.getSignatureFromPsbtOfBIP322Simple = getSignatureFromPsbtOfBIP322Simple;
/**
* reference: https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki
*/
function signMessageOfBIP322Simple({ message, address, networkType, wallet }) {
return __awaiter(this, void 0, void 0, function* () {
const psbtToSign = genPsbtOfBIP322Simple({
message,
address,
networkType
});
yield wallet.signPsbt(psbtToSign);
return getSignatureFromPsbtOfBIP322Simple(psbtToSign);
});
}
exports.signMessageOfBIP322Simple = signMessageOfBIP322Simple;
function verifyMessageOfBIP322Simple(address, msg, signature, networkType = network_1.NetworkType.MAINNET) {
const addressType = (0, address_1.getAddressType)(address, networkType);
if (addressType === types_1.AddressType.P2WPKH || addressType === types_1.AddressType.M44_P2WPKH) {
return verifySignatureOfBIP322Simple_P2PWPKH(address, msg, signature, networkType);
}
else if (addressType === types_1.AddressType.P2TR || addressType === types_1.AddressType.M44_P2TR) {
return verifySignatureOfBIP322Simple_P2TR(address, msg, signature, networkType);
}
return false;
}
exports.verifyMessageOfBIP322Simple = verifyMessageOfBIP322Simple;
function verifySignatureOfBIP322Simple_P2TR(address, msg, sign, networkType = network_1.NetworkType.MAINNET) {
const network = (0, network_1.toPsbtNetwork)(networkType);
const outputScript = bitcoin_core_1.bitcoin.address.toOutputScript(address, network);
const prevoutHash = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex');
const prevoutIndex = 0xffffffff;
const sequence = 0;
const scriptSig = Buffer.concat([Buffer.from('0020', 'hex'), Buffer.from(bip0322_hash(msg), 'hex')]);
const txToSpend = new bitcoin_core_1.bitcoin.Transaction();
txToSpend.version = 0;
txToSpend.addInput(prevoutHash, prevoutIndex, sequence, scriptSig);
txToSpend.addOutput(outputScript, 0);
const data = Buffer.from(sign, 'base64');
const _res = bitcoin_core_1.bitcoin.script.decompile(data.slice(1));
const signature = _res[0];
const pubkey = Buffer.from('02' + outputScript.subarray(2).toString('hex'), 'hex');
const psbtToSign = new bitcoin_core_1.bitcoin.Psbt();
psbtToSign.setVersion(0);
psbtToSign.addInput({
hash: txToSpend.getHash(),
index: 0,
sequence: 0,
witnessUtxo: {
script: outputScript,
value: 0
}
});
psbtToSign.addOutput({ script: Buffer.from('6a', 'hex'), value: 0 });
const tapKeyHash = psbtToSign.__CACHE.__TX.hashForWitnessV1(0, [outputScript], [0], 0);
const valid = (0, utils_1.schnorrValidator)(pubkey, tapKeyHash, signature);
return valid;
}
function verifySignatureOfBIP322Simple_P2PWPKH(address, msg, sign, networkType = network_1.NetworkType.MAINNET) {
const network = (0, network_1.toPsbtNetwork)(networkType);
const outputScript = bitcoin_core_1.bitcoin.address.toOutputScript(address, network);
const prevoutHash = Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex');
const prevoutIndex = 0xffffffff;
const sequence = 0;
const scriptSig = Buffer.concat([Buffer.from('0020', 'hex'), Buffer.from(bip0322_hash(msg), 'hex')]);
const txToSpend = new bitcoin_core_1.bitcoin.Transaction();
txToSpend.version = 0;
txToSpend.addInput(prevoutHash, prevoutIndex, sequence, scriptSig);
txToSpend.addOutput(outputScript, 0);
const data = Buffer.from(sign, 'base64');
const _res = bitcoin_core_1.bitcoin.script.decompile(data.slice(1));
const psbtToSign = new bitcoin_core_1.bitcoin.Psbt();
psbtToSign.setVersion(0);
psbtToSign.addInput({
hash: txToSpend.getHash(),
index: 0,
sequence: 0,
witnessUtxo: {
script: outputScript,
value: 0
}
});
psbtToSign.addOutput({ script: Buffer.from('6a', 'hex'), value: 0 });
psbtToSign.updateInput(0, {
partialSig: [
{
pubkey: _res[1],
signature: _res[0]
}
]
});
const valid = psbtToSign.validateSignaturesOfAllInputs(utils_1.validator);
return valid;
}