Skip to content

Commit 24e5cc0

Browse files
committed
Add Taproot example
1 parent 45187a3 commit 24e5cc0

File tree

3 files changed

+127
-4
lines changed

3 files changed

+127
-4
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
# 6.0.0
2+
__removed__
3+
- bip32: Removed the re-export. Please add as dependency to your app instead.
4+
- ECPair: Please use bip32 moving forward. ecpair package was created for those who need it.
5+
- TransactionBuilder: Any internal files used only in TB (classify, templates, etc.) were also removed.
6+
7+
__added__
8+
- taproot segwit v1 address support (bech32m) via address module (#1676)
9+
- hashForWitnessV1 method on Transaction class (#1745)
10+
11+
__fixed__
12+
- Transaction version read/write differed. (#1717)
13+
114
# 5.2.0
215
__changed__
316
- Updated PSBT to allow for witnessUtxo and nonWitnessUtxo simultaneously (Re: segwit psbt bug) (#1563)

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
# BitcoinJS (bitcoinjs-lib)
2-
[![Build Status](https://travis-ci.org/bitcoinjs/bitcoinjs-lib.png?branch=master)](https://travis-ci.org/bitcoinjs/bitcoinjs-lib)
3-
[![NPM](https://img.shields.io/npm/v/bitcoinjs-lib.svg)](https://www.npmjs.org/package/bitcoinjs-lib)
4-
5-
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
2+
[![Github CI](https://github.com/bitcoinjs/bitcoinjs-lib/actions/workflows/main_ci.yml/badge.svg)](https://github.com/bitcoinjs/bitcoinjs-lib/actions/workflows/main_ci.yml) [![NPM](https://img.shields.io/npm/v/bitcoinjs-lib.svg)](https://www.npmjs.org/package/bitcoinjs-lib) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
63

74
A javascript Bitcoin library for node.js and browsers. Written in TypeScript, but committing the JS files to verify.
85

@@ -94,6 +91,8 @@ The below examples are implemented as integration tests, they should be very eas
9491
Otherwise, pull requests are appreciated.
9592
Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
9693

94+
- [Taproot Key Spend](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/taproot.md)
95+
9796
- [Generate a random address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
9897
- [Import an address via WIF](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)
9998
- [Generate a 2-of-3 P2SH multisig address](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts)

test/integration/taproot.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Taproot
2+
3+
A simple keyspend example that is possible with the current API is below.
4+
5+
## Current state of taproot support
6+
7+
- [x] segwit v1 address support via bech32m
8+
- [x] segwit v1 sighash calculation on Transaction class
9+
10+
## TODO
11+
12+
- [ ] p2tr payment API to make script spends easier
13+
- [ ] Support within the Psbt class
14+
15+
## Example
16+
17+
### Requirements
18+
- npm dependencies
19+
- bitcoinjs-lib v6.x.x
20+
- bip32 v3.x.x
21+
- tiny-secp256k1 v2.x.x
22+
- regtest-client vx.x.x
23+
- local regtest-server docker container running
24+
- `docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server`
25+
- node >= v14
26+
27+
```js
28+
const crypto = require('crypto');
29+
30+
// bitcoinjs-lib v6
31+
const bitcoin = require('bitcoinjs-lib');
32+
// bip32 v3 wraps tiny-secp256k1
33+
const BIP32Wrapper = require('bip32').default;
34+
const RegtestUtils = require('regtest-client').RegtestUtils;
35+
// tiny-secp256k1 v2 is an ESM module, so we can't "require", and must import async
36+
import('tiny-secp256k1')
37+
.then(async (ecc) => {
38+
// End imports
39+
40+
// set up dependencies
41+
const APIPASS = process.env.APIPASS || 'satoshi';
42+
// docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server
43+
const APIURL = process.env.APIURL || 'http://127.0.0.1:8080/1';
44+
const regtestUtils = new RegtestUtils({ APIPASS, APIURL });
45+
46+
const bip32 = BIP32Wrapper(ecc);
47+
48+
const myKey = bip32.fromSeed(crypto.randomBytes(64), regtestUtils.network);
49+
// scriptPubkey
50+
const output = Buffer.concat([
51+
// witness v1, PUSH_DATA 32 bytes
52+
Buffer.from([0x51, 0x20]),
53+
// x-only pubkey (remove 1 byte y parity)
54+
myKey.publicKey.slice(1, 33),
55+
]);
56+
const address = bitcoin.address.fromOutputScript(
57+
output,
58+
regtestUtils.network
59+
);
60+
// amount from faucet
61+
const amount = 42e4;
62+
// amount to send
63+
const sendAmount = amount - 1e4;
64+
// get faucet
65+
const unspent = await regtestUtils.faucetComplex(output, amount);
66+
67+
const tx = createSigned(
68+
myKey,
69+
unspent.txId,
70+
unspent.vout,
71+
sendAmount,
72+
[output],
73+
[amount]
74+
);
75+
76+
const hex = tx.toHex();
77+
console.log('Valid tx sent from:');
78+
console.log(address);
79+
console.log('tx hex:');
80+
console.log(hex);
81+
await regtestUtils.broadcast(hex);
82+
await regtestUtils.verify({
83+
txId: tx.getId(),
84+
address,
85+
vout: 0,
86+
value: sendAmount,
87+
});
88+
})
89+
.catch(console.error);
90+
91+
// Function for creating signed tx
92+
function createSigned(key, txid, vout, amountToSend, scriptPubkeys, values) {
93+
const tx = new bitcoin.Transaction();
94+
tx.version = 2;
95+
// Add input
96+
tx.addInput(Buffer.from(txid, 'hex').reverse(), vout);
97+
// Add output
98+
tx.addOutput(scriptPubkeys[0], amountToSend);
99+
const sighash = tx.hashForWitnessV1(
100+
0, // which input
101+
scriptPubkeys, // All previous outputs of all inputs
102+
values, // All previous values of all inputs
103+
bitcoin.Transaction.SIGHASH_DEFAULT // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
104+
);
105+
const signature = Buffer.from(key.signSchnorr(sighash));
106+
// witness stack for keypath spend is just the signature.
107+
// If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
108+
tx.ins[0].witness = [signature];
109+
return tx;
110+
}
111+
```

0 commit comments

Comments
 (0)