@vbyte/btc-dev
Version:
Batteries-included toolset for plebian bitcoin development
57 lines (56 loc) • 2.06 kB
JavaScript
import { Buff } from '@vbyte/buff';
import { Assert, ECC } from '@vbyte/micro-lib';
import { merkleize } from './tree.js';
import { TAPLEAF_DEFAULT_VERSION } from '../../const.js';
import * as Schema from '../../schema/index.js';
import { encode_tapbranch, encode_taptweak } from './encode.js';
import { parse_pubkey_parity, parse_cblock } from './parse.js';
const DEFAULT_VERSION = TAPLEAF_DEFAULT_VERSION;
export function create_taproot(config) {
Schema.taproot.config.parse(config);
const { pubkey, version = DEFAULT_VERSION } = config;
const leaves = config.leaves ?? [];
const target = (config.target !== undefined)
? Buff.bytes(config.target).hex
: undefined;
let path = [], taproot;
if (leaves.length > 0) {
const [root, _, proofs] = merkleize(leaves, target);
path = proofs;
taproot = root;
}
else {
taproot = target;
}
const taptweak = encode_taptweak(pubkey, taproot);
const twk_key = ECC.tweak_pubkey(pubkey, taptweak, 'ecdsa');
const parity = parse_pubkey_parity(twk_key);
const tapkey = ECC.serialize_pubkey(twk_key, 'bip340');
const cbit = Buff.num(version + parity);
const block = [cbit, Buff.bytes(pubkey)];
if (path.length > 0) {
path.forEach(e => block.push(e));
}
const cblock = Buff.join(block);
return {
int_key: Buff.bytes(pubkey).hex,
path,
parity,
taproot: taproot ?? null,
cblock: cblock.hex,
tapkey: tapkey.hex,
taptweak: taptweak.hex
};
}
export function verify_taproot(tapkey, target, cblock) {
Assert.size(tapkey, 32);
const { parity, path, int_key } = parse_cblock(cblock);
const ext_key = Buff.join([parity, tapkey]);
let branch = Buff.bytes(target).hex;
for (const leaf of path) {
branch = encode_tapbranch(branch, leaf).hex;
}
const tap_tweak = encode_taptweak(int_key, branch);
const tweaked_key = ECC.tweak_pubkey(int_key, tap_tweak, 'ecdsa');
return (ext_key.hex === tweaked_key.hex);
}