Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
- [Create (and broadcast via 3PBP) a taproot script-path spend Transaction - OP_CHECKSIG](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/taproot.spec.ts)
- [Create (and broadcast via 3PBP) a taproot script-path spend Transaction - OP_CHECKSEQUENCEVERIFY](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/taproot.spec.ts)
- [Create (and broadcast via 3PBP) a taproot script-path spend Transaction - OP_CHECKSIGADD (3-of-3)](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/taproot.spec.ts)
- [P2MR (BIP360) address generation and script-path spend](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/p2mr.spec.ts)
- [P2MR multi-leaf script tree with PSBT signing](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/p2mr.spec.ts)
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
Expand Down
8 changes: 8 additions & 0 deletions src/cjs/address.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ function fromOutputScript(output, network) {
try {
return payments.p2tr({ output, network }).address;
} catch (e) {}
try {
return payments.p2mr({ output, network }).address;
} catch (e) {}
try {
return _toFutureSegwitAddress(output, network);
} catch (e) {}
Expand Down Expand Up @@ -239,6 +242,11 @@ function toOutputScript(address, network) {
} else if (decodeBech32.version === 1) {
if (decodeBech32.data.length === 32)
return payments.p2tr({ pubkey: decodeBech32.data }).output;
} else if (
decodeBech32.version === 2 &&
decodeBech32.data.length === 32
) {
return payments.p2mr({ hash: decodeBech32.data }).output;
} else if (
decodeBech32.version >= FUTURE_SEGWIT_MIN_VERSION &&
decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
Expand Down
6 changes: 3 additions & 3 deletions src/cjs/address.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ export interface Base58CheckResult {
}
/** bech32 decode result */
export interface Bech32Result {
/** address version: 0x00 for P2WPKHP2WSH, 0x01 for P2TR*/
/** address version: 0x00 for P2WPKH/P2WSH, 0x01 for P2TR, 0x02 for P2MR */
version: number;
/** address prefix: bc for P2WPKHP2WSHP2TR */
/** address prefix: bc for P2WPKH/P2WSH/P2TR/P2MR */
prefix: string;
/** address data:20 bytes for P2WPKH, 32 bytes for P2WSHP2TR */
/** address data:20 bytes for P2WPKH, 32 bytes for P2WSH/P2TR/P2MR */
data: Uint8Array;
}
/**
Expand Down
32 changes: 32 additions & 0 deletions src/cjs/payments/bip341.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ var __importStar =
Object.defineProperty(exports, '__esModule', { value: true });
exports.MAX_TAPTREE_DEPTH = exports.LEAF_VERSION_TAPSCRIPT = void 0;
exports.rootHashFromPath = rootHashFromPath;
exports.rootHashFromP2MRPath = rootHashFromP2MRPath;
exports.toHashTree = toHashTree;
exports.findScriptPath = findScriptPath;
exports.tapleafHash = tapleafHash;
exports.tapTweakHash = tapTweakHash;
exports.tweakKey = tweakKey;
exports.tapBranchHash = tapBranchHash;
const ecc_lib_js_1 = require('../ecc_lib.cjs');
const bcrypto = __importStar(require('../crypto.cjs'));
const bufferutils_js_1 = require('../bufferutils.cjs');
Expand Down Expand Up @@ -83,6 +85,36 @@ function rootHashFromPath(controlBlock, leafHash) {
}
return kj;
}
/**
* Calculates the root hash from a P2MR control block and leaf hash.
* Unlike P2TR, P2MR control blocks do not include an internal public key,
* so the Merkle path starts at byte offset 1 (after the control byte).
* @param controlBlock - The P2MR control block buffer (1 + 32*m bytes).
* @param leafHash - The leaf hash buffer.
* @returns The root hash buffer.
* @throws {TypeError} If the control block length is invalid.
*/
function rootHashFromP2MRPath(controlBlock, leafHash) {
if (controlBlock.length < 1)
throw new TypeError(
`The control-block length is too small. Got ${controlBlock.length}, expected min 1.`,
);
if ((controlBlock.length - 1) % 32 !== 0)
throw new TypeError(
`The control-block length of ${controlBlock.length} is incorrect for P2MR!`,
);
const m = (controlBlock.length - 1) / 32;
let kj = leafHash;
for (let j = 0; j < m; j++) {
const ej = controlBlock.slice(1 + 32 * j, 33 + 32 * j);
if (tools.compare(kj, ej) < 0) {
kj = tapBranchHash(kj, ej);
} else {
kj = tapBranchHash(ej, kj);
}
}
return kj;
}
/**
* Build a hash tree of merkle nodes from the scripts binary tree.
* @param scriptTree - the tree of scripts to pairwise hash.
Expand Down
18 changes: 18 additions & 0 deletions src/cjs/payments/bip341.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ export type HashTree = HashLeaf | HashBranch;
* @throws {TypeError} If the control block length is less than 33.
*/
export declare function rootHashFromPath(controlBlock: Uint8Array, leafHash: Uint8Array): Uint8Array;
/**
* Calculates the root hash from a P2MR control block and leaf hash.
* Unlike P2TR, P2MR control blocks do not include an internal public key,
* so the Merkle path starts at byte offset 1 (after the control byte).
* @param controlBlock - The P2MR control block buffer (1 + 32*m bytes).
* @param leafHash - The leaf hash buffer.
* @returns The root hash buffer.
* @throws {TypeError} If the control block length is invalid.
*/
export declare function rootHashFromP2MRPath(controlBlock: Uint8Array, leafHash: Uint8Array): Uint8Array;
/**
* Build a hash tree of merkle nodes from the scripts binary tree.
* @param scriptTree - the tree of scripts to pairwise hash.
Expand Down Expand Up @@ -65,4 +75,12 @@ export declare function tapTweakHash(pubKey: Uint8Array, h: Uint8Array | undefin
* @returns The tweaked public key or null if the input is invalid.
*/
export declare function tweakKey(pubKey: Uint8Array, h: Uint8Array | undefined): TweakedPublicKey | null;
/**
* Computes the TapBranch hash by concatenating two buffers and applying the 'TapBranch' tagged hash algorithm.
*
* @param a - The first buffer.
* @param b - The second buffer.
* @returns The TapBranch hash of the concatenated buffers.
*/
export declare function tapBranchHash(a: Uint8Array, b: Uint8Array): Uint8Array;
export {};
10 changes: 9 additions & 1 deletion src/cjs/payments/index.cjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.p2tr =
exports.p2mr =
exports.p2tr =
exports.p2wsh =
exports.p2wpkh =
exports.p2sh =
Expand Down Expand Up @@ -65,5 +66,12 @@ Object.defineProperty(exports, 'p2tr', {
return p2tr_js_1.p2tr;
},
});
const p2mr_js_1 = require('./p2mr.cjs');
Object.defineProperty(exports, 'p2mr', {
enumerable: true,
get: function () {
return p2mr_js_1.p2mr;
},
});
// TODO
// witness commitment
4 changes: 3 additions & 1 deletion src/cjs/payments/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* - P2WPKH (Pay-to-Witness-PubKey-Hash)
* - P2WSH (Pay-to-Witness-Script-Hash)
* - P2TR (Taproot)
* - P2MR (Pay-to-Merkle-Root, BIP 360)
*
* The `Payment` interface defines the structure of a payment object used for constructing various
* payment types, with fields for signatures, public keys, redeem scripts, and more.
Expand All @@ -23,6 +24,7 @@ import { p2sh } from './p2sh.js';
import { p2wpkh } from './p2wpkh.js';
import { p2wsh } from './p2wsh.js';
import { p2tr } from './p2tr.js';
import { p2mr } from './p2mr.js';
export interface Payment {
name?: string;
network?: Network;
Expand Down Expand Up @@ -52,4 +54,4 @@ export interface PaymentOpts {
export type StackElement = Uint8Array | number;
export type Stack = StackElement[];
export type StackFunction = () => Stack;
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh, p2tr };
export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh, p2tr, p2mr };
Loading
Loading