UNPKG

@vbyte/btc-dev

Version:

Batteries-included toolset for plebian bitcoin development

57 lines (56 loc) 2.06 kB
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); }