From 24e5cc061699cf66e63df7b371d4d1171646d529 Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Fri, 12 Nov 2021 12:39:56 +0900
Subject: [PATCH 1/8] Add Taproot example

---
 CHANGELOG.md                |  13 +++++
 README.md                   |   7 +--
 test/integration/taproot.md | 111 ++++++++++++++++++++++++++++++++++++
 3 files changed, 127 insertions(+), 4 deletions(-)
 create mode 100644 test/integration/taproot.md

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4e1eb7..f7d8f91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+# 6.0.0
+__removed__
+- bip32: Removed the re-export. Please add as dependency to your app instead.
+- ECPair: Please use bip32 moving forward. ecpair package was created for those who need it.
+- TransactionBuilder: Any internal files used only in TB (classify, templates, etc.) were also removed.
+
+__added__
+- taproot segwit v1 address support (bech32m) via address module (#1676)
+- hashForWitnessV1 method on Transaction class (#1745)
+
+__fixed__
+- Transaction version read/write differed. (#1717)
+
 # 5.2.0
 __changed__
 - Updated PSBT to allow for witnessUtxo and nonWitnessUtxo simultaneously (Re: segwit psbt bug) (#1563)
diff --git a/README.md b/README.md
index d974624..9389a73 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,5 @@
 # BitcoinJS (bitcoinjs-lib)
-[![Build Status](https://travis-ci.org/bitcoinjs/bitcoinjs-lib.png?branch=master)](https://travis-ci.org/bitcoinjs/bitcoinjs-lib)
-[![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)
+[![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)
 
 A javascript Bitcoin library for node.js and browsers. Written in TypeScript, but committing the JS files to verify.
 
@@ -94,6 +91,8 @@ The below examples are implemented as integration tests, they should be very eas
 Otherwise, pull requests are appreciated.
 Some examples interact (via HTTPS) with a 3rd Party Blockchain Provider (3PBP).
 
+- [Taproot Key Spend](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/taproot.md)
+
 - [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)
diff --git a/test/integration/taproot.md b/test/integration/taproot.md
new file mode 100644
index 0000000..2db6eef
--- /dev/null
+++ b/test/integration/taproot.md
@@ -0,0 +1,111 @@
+# Taproot
+
+A simple keyspend example that is possible with the current API is below.
+
+## Current state of taproot support
+
+- [x] segwit v1 address support via bech32m
+- [x] segwit v1 sighash calculation on Transaction class
+
+## TODO
+
+- [ ] p2tr payment API to make script spends easier
+- [ ] Support within the Psbt class
+
+## Example
+
+### Requirements
+- npm dependencies
+  - bitcoinjs-lib v6.x.x
+  - bip32 v3.x.x
+  - tiny-secp256k1 v2.x.x
+  - regtest-client vx.x.x
+- local regtest-server docker container running
+  - `docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server`
+- node >= v14
+
+```js
+const crypto = require('crypto');
+
+// bitcoinjs-lib v6
+const bitcoin = require('bitcoinjs-lib');
+// bip32 v3 wraps tiny-secp256k1
+const BIP32Wrapper = require('bip32').default;
+const RegtestUtils = require('regtest-client').RegtestUtils;
+// tiny-secp256k1 v2 is an ESM module, so we can't "require", and must import async
+import('tiny-secp256k1')
+  .then(async (ecc) => {
+    // End imports
+
+    // set up dependencies
+    const APIPASS = process.env.APIPASS || 'satoshi';
+    // docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server
+    const APIURL = process.env.APIURL || 'http://127.0.0.1:8080/1';
+    const regtestUtils = new RegtestUtils({ APIPASS, APIURL });
+
+    const bip32 = BIP32Wrapper(ecc);
+
+    const myKey = bip32.fromSeed(crypto.randomBytes(64), regtestUtils.network);
+    // scriptPubkey
+    const output = Buffer.concat([
+      // witness v1, PUSH_DATA 32 bytes
+      Buffer.from([0x51, 0x20]),
+      // x-only pubkey (remove 1 byte y parity)
+      myKey.publicKey.slice(1, 33),
+    ]);
+    const address = bitcoin.address.fromOutputScript(
+      output,
+      regtestUtils.network
+    );
+    // amount from faucet
+    const amount = 42e4;
+    // amount to send
+    const sendAmount = amount - 1e4;
+    // get faucet
+    const unspent = await regtestUtils.faucetComplex(output, amount);
+
+    const tx = createSigned(
+      myKey,
+      unspent.txId,
+      unspent.vout,
+      sendAmount,
+      [output],
+      [amount]
+    );
+
+    const hex = tx.toHex();
+    console.log('Valid tx sent from:');
+    console.log(address);
+    console.log('tx hex:');
+    console.log(hex);
+    await regtestUtils.broadcast(hex);
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address,
+      vout: 0,
+      value: sendAmount,
+    });
+  })
+  .catch(console.error);
+
+// Function for creating signed tx
+function createSigned(key, txid, vout, amountToSend, scriptPubkeys, values) {
+  const tx = new bitcoin.Transaction();
+  tx.version = 2;
+  // Add input
+  tx.addInput(Buffer.from(txid, 'hex').reverse(), vout);
+  // Add output
+  tx.addOutput(scriptPubkeys[0], amountToSend);
+  const sighash = tx.hashForWitnessV1(
+    0, // which input
+    scriptPubkeys, // All previous outputs of all inputs
+    values, // All previous values of all inputs
+    bitcoin.Transaction.SIGHASH_DEFAULT // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
+  );
+  const signature = Buffer.from(key.signSchnorr(sighash));
+  // witness stack for keypath spend is just the signature.
+  // If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
+  tx.ins[0].witness = [signature];
+  return tx;
+}
+```
\ No newline at end of file

From 31e512e63f0dac3af4f9cfe72e886baa1b768467 Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Fri, 12 Nov 2021 12:40:09 +0900
Subject: [PATCH 2/8] 6.0.0

---
 package-lock.json | 2 +-
 package.json      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index f07cf3c..c66d2ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "bitcoinjs-lib",
-  "version": "5.2.0",
+  "version": "6.0.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index 0eb793e..e420511 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "bitcoinjs-lib",
-  "version": "5.2.0",
+  "version": "6.0.0",
   "description": "Client-side Bitcoin JavaScript library",
   "main": "./src/index.js",
   "types": "./src/index.d.ts",

From 424abf2376772bb57b7668bc35b29ed18879fa0a Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Mon, 15 Nov 2021 08:25:22 +0900
Subject: [PATCH 3/8] Fix taproot example to follow the suggestion in BIP341

---
 test/integration/taproot.md | 147 +++++++++++++++++++++++-------------
 1 file changed, 96 insertions(+), 51 deletions(-)

diff --git a/test/integration/taproot.md b/test/integration/taproot.md
index 2db6eef..4010340 100644
--- a/test/integration/taproot.md
+++ b/test/integration/taproot.md
@@ -25,68 +25,108 @@ A simple keyspend example that is possible with the current API is below.
 - node >= v14
 
 ```js
-const crypto = require('crypto');
+// Run this whole file as async
+// Catch any errors at the bottom of the file
+// and exit the process with 1 error code
+(async () => {
 
+// Order of the curve (N) - 1
+const N_LESS_1 = Buffer.from(
+  'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
+  'hex'
+);
+// 1 represented as 32 bytes BE
+const ONE = Buffer.from(
+  '0000000000000000000000000000000000000000000000000000000000000001',
+  'hex'
+);
+
+const crypto = require('crypto');
 // bitcoinjs-lib v6
 const bitcoin = require('bitcoinjs-lib');
 // bip32 v3 wraps tiny-secp256k1
 const BIP32Wrapper = require('bip32').default;
 const RegtestUtils = require('regtest-client').RegtestUtils;
 // tiny-secp256k1 v2 is an ESM module, so we can't "require", and must import async
-import('tiny-secp256k1')
-  .then(async (ecc) => {
-    // End imports
+const ecc = await import('tiny-secp256k1');
+// wrap the bip32 library
+const bip32 = BIP32Wrapper(ecc);
+// set up dependencies
+const APIPASS = process.env.APIPASS || 'satoshi';
+// docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server
+const APIURL = process.env.APIURL || 'http://127.0.0.1:8080/1';
+const regtestUtils = new RegtestUtils({ APIPASS, APIURL });
+// End imports
 
-    // set up dependencies
-    const APIPASS = process.env.APIPASS || 'satoshi';
-    // docker run -d -p 8080:8080 junderw/bitcoinjs-regtest-server
-    const APIURL = process.env.APIURL || 'http://127.0.0.1:8080/1';
-    const regtestUtils = new RegtestUtils({ APIPASS, APIURL });
+const myKey = bip32.fromSeed(crypto.randomBytes(64), regtestUtils.network);
 
-    const bip32 = BIP32Wrapper(ecc);
+const output = createKeySpendOutput(myKey.publicKey);
+const address = bitcoin.address.fromOutputScript(
+  output,
+  regtestUtils.network
+);
+// amount from faucet
+const amount = 42e4;
+// amount to send
+const sendAmount = amount - 1e4;
+// get faucet
+const unspent = await regtestUtils.faucetComplex(output, amount);
 
-    const myKey = bip32.fromSeed(crypto.randomBytes(64), regtestUtils.network);
-    // scriptPubkey
-    const output = Buffer.concat([
-      // witness v1, PUSH_DATA 32 bytes
-      Buffer.from([0x51, 0x20]),
-      // x-only pubkey (remove 1 byte y parity)
-      myKey.publicKey.slice(1, 33),
-    ]);
-    const address = bitcoin.address.fromOutputScript(
-      output,
-      regtestUtils.network
-    );
-    // amount from faucet
-    const amount = 42e4;
-    // amount to send
-    const sendAmount = amount - 1e4;
-    // get faucet
-    const unspent = await regtestUtils.faucetComplex(output, amount);
+const tx = createSigned(
+  myKey,
+  unspent.txId,
+  unspent.vout,
+  sendAmount,
+  [output],
+  [amount]
+);
 
-    const tx = createSigned(
-      myKey,
-      unspent.txId,
-      unspent.vout,
-      sendAmount,
-      [output],
-      [amount]
-    );
+const hex = tx.toHex();
+console.log('Valid tx sent from:');
+console.log(address);
+console.log('tx hex:');
+console.log(hex);
+await regtestUtils.broadcast(hex);
+await regtestUtils.verify({
+  txId: tx.getId(),
+  address,
+  vout: 0,
+  value: sendAmount,
+});
 
-    const hex = tx.toHex();
-    console.log('Valid tx sent from:');
-    console.log(address);
-    console.log('tx hex:');
-    console.log(hex);
-    await regtestUtils.broadcast(hex);
-    await regtestUtils.verify({
-      txId: tx.getId(),
-      address,
-      vout: 0,
-      value: sendAmount,
-    });
-  })
-  .catch(console.error);
+// Function for creating a tweaked p2tr key-spend only address
+// (This is recommended by BIP341)
+function createKeySpendOutput(publicKey) {
+  // x-only pubkey (remove 1 byte y parity)
+  const myXOnlyPubkey = publicKey.slice(1, 33);
+  const commitHash = bitcoin.crypto.taggedHash('TapTweak', myXOnlyPubkey);
+  const tweakResult = ecc.xOnlyPointAddTweak(myXOnlyPubkey, commitHash);
+  if (tweakResult === null) throw new Error('Invalid Tweak');
+  const { xOnlyPubkey: tweaked } = tweakResult;
+  // scriptPubkey
+  return Buffer.concat([
+    // witness v1, PUSH_DATA 32 bytes
+    Buffer.from([0x51, 0x20]),
+    // x-only tweaked pubkey
+    tweaked,
+  ]);
+}
+
+// Function for signing for a tweaked p2tr key-spend only address
+// (Required for the above address)
+function signTweaked(messageHash, key) {
+  const privateKey =
+    key.publicKey[0] === 2
+      ? key.privateKey
+      : ecc.privateAdd(ecc.privateSub(N_LESS_1, key.privateKey), ONE);
+  const tweakHash = bitcoin.crypto.taggedHash(
+    'TapTweak',
+    key.publicKey.slice(1, 33)
+  );
+  const newPrivateKey = ecc.privateAdd(privateKey, tweakHash);
+  if (newPrivateKey === null) throw new Error('Invalid Tweak');
+  return ecc.signSchnorr(messageHash, newPrivateKey, Buffer.alloc(32));
+}
 
 // Function for creating signed tx
 function createSigned(key, txid, vout, amountToSend, scriptPubkeys, values) {
@@ -102,10 +142,15 @@ function createSigned(key, txid, vout, amountToSend, scriptPubkeys, values) {
     values, // All previous values of all inputs
     bitcoin.Transaction.SIGHASH_DEFAULT // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
   );
-  const signature = Buffer.from(key.signSchnorr(sighash));
+  const signature = Buffer.from(signTweaked(sighash, key));
   // witness stack for keypath spend is just the signature.
   // If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
   tx.ins[0].witness = [signature];
   return tx;
 }
+
+})().catch((err) => {
+  console.error(err);
+  process.exit(1);
+});
 ```
\ No newline at end of file

From 191b9e857341521507b35e21f748bf148ebb5301 Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Wed, 17 Nov 2021 16:01:08 +0900
Subject: [PATCH 4/8] Add taproot test with new CJS compatible tiny-secp256k1

---
 package-lock.json                     |  46 ++++++----
 package.json                          |   3 +-
 test/integration/bip32.spec.ts        |   5 +-
 test/integration/taproot.spec.ts      | 122 ++++++++++++++++++++++++++
 test/integration/transactions.spec.ts |   4 +-
 test/psbt.spec.ts                     |   5 +-
 6 files changed, 166 insertions(+), 19 deletions(-)
 create mode 100644 test/integration/taproot.spec.ts

diff --git a/package-lock.json b/package-lock.json
index c66d2ad..d6b9ce8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -556,16 +556,15 @@
       "integrity": "sha512-i3X26uKJOkDTAalYAp0Er+qGMDhrbbh2o93/xiPyAN2s25KrClSpe3VXo/7mNJoqA5qfko8rLS2l3RWZgYmjKQ=="
     },
     "bip32": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz",
-      "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==",
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/bip32/-/bip32-3.0.1.tgz",
+      "integrity": "sha512-Uhpp9aEx3iyiO7CpbNGFxv9WcMIVdGoHG04doQ5Ln0u60uwDah7jUSc3QMV/fSZGm/Oo01/OeAmYevXV+Gz5jQ==",
       "dev": true,
       "requires": {
         "@types/node": "10.12.18",
         "bs58check": "^2.1.1",
         "create-hash": "^1.2.0",
         "create-hmac": "^1.1.7",
-        "tiny-secp256k1": "^1.1.3",
         "typeforce": "^1.11.5",
         "wif": "^2.0.6"
       },
@@ -941,6 +940,21 @@
         "tiny-secp256k1": "^1.1.6",
         "typeforce": "^1.11.3",
         "wif": "^2.0.1"
+      },
+      "dependencies": {
+        "tiny-secp256k1": {
+          "version": "1.1.6",
+          "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz",
+          "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==",
+          "dev": true,
+          "requires": {
+            "bindings": "^1.3.0",
+            "bn.js": "^4.11.8",
+            "create-hmac": "^1.1.7",
+            "elliptic": "^6.4.0",
+            "nan": "^2.13.2"
+          }
+        }
       }
     },
     "elliptic": {
@@ -1707,9 +1721,9 @@
       "dev": true
     },
     "nan": {
-      "version": "2.14.2",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
-      "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
+      "version": "2.15.0",
+      "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
+      "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
       "dev": true
     },
     "node-environment-flags": {
@@ -2465,16 +2479,12 @@
       }
     },
     "tiny-secp256k1": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz",
-      "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.1.1.tgz",
+      "integrity": "sha512-pdENPcbI4l3Br6sPVuC5RWONHojcPjBiXljIBvQ5UIN/MD6wPzmJ8mpDnkps3O7FFfT+fLqGXo2MdFdRQaPWUg==",
       "dev": true,
       "requires": {
-        "bindings": "^1.3.0",
-        "bn.js": "^4.11.8",
-        "create-hmac": "^1.1.7",
-        "elliptic": "^6.4.0",
-        "nan": "^2.13.2"
+        "uint8array-tools": "0.0.6"
       }
     },
     "to-fast-properties": {
@@ -2583,6 +2593,12 @@
       "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
       "dev": true
     },
+    "uint8array-tools": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.6.tgz",
+      "integrity": "sha512-aIvEHNRX1AlOYAr6qSUjQBn4mCduxx6MtC967aRDTb2UUBPj0Ix2ZFQDcmXUUO/UxRPHcw1f5a5nVbCSKDSOqA==",
+      "dev": true
+    },
     "uuid": {
       "version": "3.4.0",
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
diff --git a/package.json b/package.json
index e420511..36d9003 100644
--- a/package.json
+++ b/package.json
@@ -66,7 +66,7 @@
     "@types/proxyquire": "^1.3.28",
     "@types/randombytes": "^2.0.0",
     "@types/wif": "^2.0.2",
-    "bip32": "^2.0.6",
+    "bip32": "^3.0.1",
     "bip39": "^3.0.2",
     "bip65": "^1.0.1",
     "bip68": "^1.0.3",
@@ -84,6 +84,7 @@
     "randombytes": "^2.1.0",
     "regtest-client": "0.2.0",
     "rimraf": "^2.6.3",
+    "tiny-secp256k1": "^2.1.1",
     "ts-node": "^8.3.0",
     "tslint": "^6.1.3",
     "typescript": "^4.4.4"
diff --git a/test/integration/bip32.spec.ts b/test/integration/bip32.spec.ts
index 7cd9e2f..938c281 100644
--- a/test/integration/bip32.spec.ts
+++ b/test/integration/bip32.spec.ts
@@ -1,9 +1,12 @@
 import * as assert from 'assert';
-import * as bip32 from 'bip32';
+import BIP32Factory from 'bip32';
+import * as ecc from 'tiny-secp256k1';
 import * as bip39 from 'bip39';
 import { describe, it } from 'mocha';
 import * as bitcoin from '../..';
 
+const bip32 = BIP32Factory(ecc);
+
 function getAddress(node: any, network?: any): string {
   return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address!;
 }
diff --git a/test/integration/taproot.spec.ts b/test/integration/taproot.spec.ts
new file mode 100644
index 0000000..f7b3733
--- /dev/null
+++ b/test/integration/taproot.spec.ts
@@ -0,0 +1,122 @@
+import BIP32Factory from 'bip32';
+import * as ecc from 'tiny-secp256k1';
+import { describe, it } from 'mocha';
+import * as bitcoin from '../..';
+import { regtestUtils } from './_regtest';
+const rng = require('randombytes');
+const regtest = regtestUtils.network;
+const bip32 = BIP32Factory(ecc);
+
+describe('bitcoinjs-lib (transaction with taproot)', () => {
+  it('can create (and broadcast via 3PBP) a taproot keyspend Transaction', async () => {
+    const myKey = bip32.fromSeed(rng(64), regtest);
+
+    const output = createKeySpendOutput(myKey.publicKey);
+    const address = bitcoin.address.fromOutputScript(output, regtest);
+    // amount from faucet
+    const amount = 42e4;
+    // amount to send
+    const sendAmount = amount - 1e4;
+    // get faucet
+    const unspent = await regtestUtils.faucetComplex(output, amount);
+
+    const tx = createSigned(
+      myKey,
+      unspent.txId,
+      unspent.vout,
+      sendAmount,
+      [output],
+      [amount],
+    );
+
+    const hex = tx.toHex();
+    // console.log('Valid tx sent from:');
+    // console.log(address);
+    // console.log('tx hex:');
+    // console.log(hex);
+    await regtestUtils.broadcast(hex);
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address,
+      vout: 0,
+      value: sendAmount,
+    });
+  });
+});
+
+// Order of the curve (N) - 1
+const N_LESS_1 = Buffer.from(
+  'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140',
+  'hex',
+);
+// 1 represented as 32 bytes BE
+const ONE = Buffer.from(
+  '0000000000000000000000000000000000000000000000000000000000000001',
+  'hex',
+);
+
+// Function for creating a tweaked p2tr key-spend only address
+// (This is recommended by BIP341)
+function createKeySpendOutput(publicKey: Buffer): Buffer {
+  // x-only pubkey (remove 1 byte y parity)
+  const myXOnlyPubkey = publicKey.slice(1, 33);
+  const commitHash = bitcoin.crypto.taggedHash('TapTweak', myXOnlyPubkey);
+  const tweakResult = ecc.xOnlyPointAddTweak(myXOnlyPubkey, commitHash);
+  if (tweakResult === null) throw new Error('Invalid Tweak');
+  const { xOnlyPubkey: tweaked } = tweakResult;
+  // scriptPubkey
+  return Buffer.concat([
+    // witness v1, PUSH_DATA 32 bytes
+    Buffer.from([0x51, 0x20]),
+    // x-only tweaked pubkey
+    tweaked,
+  ]);
+}
+
+// Function for signing for a tweaked p2tr key-spend only address
+// (Required for the above address)
+interface KeyPair {
+  publicKey: Buffer;
+  privateKey?: Buffer;
+}
+function signTweaked(messageHash: Buffer, key: KeyPair): Uint8Array {
+  const privateKey =
+    key.publicKey[0] === 2
+      ? key.privateKey
+      : ecc.privateAdd(ecc.privateSub(N_LESS_1, key.privateKey!)!, ONE)!;
+  const tweakHash = bitcoin.crypto.taggedHash(
+    'TapTweak',
+    key.publicKey.slice(1, 33),
+  );
+  const newPrivateKey = ecc.privateAdd(privateKey!, tweakHash);
+  if (newPrivateKey === null) throw new Error('Invalid Tweak');
+  return ecc.signSchnorr(messageHash, newPrivateKey, Buffer.alloc(32));
+}
+
+// Function for creating signed tx
+function createSigned(
+  key: KeyPair,
+  txid: string,
+  vout: number,
+  amountToSend: number,
+  scriptPubkeys: Buffer[],
+  values: number[],
+): bitcoin.Transaction {
+  const tx = new bitcoin.Transaction();
+  tx.version = 2;
+  // Add input
+  tx.addInput(Buffer.from(txid, 'hex').reverse(), vout);
+  // Add output
+  tx.addOutput(scriptPubkeys[0], amountToSend);
+  const sighash = tx.hashForWitnessV1(
+    0, // which input
+    scriptPubkeys, // All previous outputs of all inputs
+    values, // All previous values of all inputs
+    bitcoin.Transaction.SIGHASH_DEFAULT, // sighash flag, DEFAULT is schnorr-only (DEFAULT == ALL)
+  );
+  const signature = Buffer.from(signTweaked(sighash, key));
+  // witness stack for keypath spend is just the signature.
+  // If sighash is not SIGHASH_DEFAULT (ALL) then you must add 1 byte with sighash value
+  tx.ins[0].witness = [signature];
+  return tx;
+}
diff --git a/test/integration/transactions.spec.ts b/test/integration/transactions.spec.ts
index d4788dc..51e44a0 100644
--- a/test/integration/transactions.spec.ts
+++ b/test/integration/transactions.spec.ts
@@ -1,11 +1,13 @@
 import * as assert from 'assert';
-import * as bip32 from 'bip32';
+import BIP32Factory from 'bip32';
+import * as ecc from 'tiny-secp256k1';
 import { ECPair } from 'ecpair';
 import { describe, it } from 'mocha';
 import * as bitcoin from '../..';
 import { regtestUtils } from './_regtest';
 const rng = require('randombytes');
 const regtest = regtestUtils.network;
+const bip32 = BIP32Factory(ecc);
 
 const validator = (
   pubkey: Buffer,
diff --git a/test/psbt.spec.ts b/test/psbt.spec.ts
index 05d4468..32d81ba 100644
--- a/test/psbt.spec.ts
+++ b/test/psbt.spec.ts
@@ -1,9 +1,12 @@
 import * as assert from 'assert';
-import * as bip32 from 'bip32';
+import BIP32Factory from 'bip32';
+import * as ecc from 'tiny-secp256k1';
 import * as crypto from 'crypto';
 import { ECPair } from 'ecpair';
 import { describe, it } from 'mocha';
 
+const bip32 = BIP32Factory(ecc);
+
 import { networks as NETWORKS, payments, Psbt, Signer, SignerAsync } from '..';
 
 import * as preFixtures from './fixtures/psbt.json';

From 4674433bb9333cc50858f44aa92b64fb643ed386 Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Wed, 17 Nov 2021 16:06:45 +0900
Subject: [PATCH 5/8] Update container

---
 .github/workflows/main_ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/main_ci.yml b/.github/workflows/main_ci.yml
index a9fdc58..7bc62cb 100644
--- a/.github/workflows/main_ci.yml
+++ b/.github/workflows/main_ci.yml
@@ -41,7 +41,7 @@ jobs:
     runs-on: ubuntu-latest
     services:
       regtest:
-        image: junderw/bitcoinjs-regtest-server@sha256:a46ec1a651ca5b1a5408f2b2526ea5f435421dd2bc2f28fae3bc33e1fd614552
+        image: junderw/bitcoinjs-regtest-server@sha256:5b69cf95d9edf6d5b3a00504665d6b3c382a6aa3728fe8ce897974c519061463
         ports:
           - 8080:8080
     steps:

From 93af5afe67dbc491e36bdfc8d48a00179093f7d1 Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Sat, 27 Nov 2021 08:35:19 +0900
Subject: [PATCH 6/8] Add warning to future segwit version address
 generation/parsing

---
 src/address.js    | 10 +++++++++-
 ts_src/address.ts | 12 +++++++++++-
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/src/address.js b/src/address.js
index 12938fc..164bf7e 100644
--- a/src/address.js
+++ b/src/address.js
@@ -13,6 +13,11 @@ const FUTURE_SEGWIT_MIN_SIZE = 2;
 const FUTURE_SEGWIT_MAX_VERSION = 16;
 const FUTURE_SEGWIT_MIN_VERSION = 1;
 const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
+const FUTURE_SEGWIT_VERSION_WARNING =
+  'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
+  'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
+  'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
+  'then decide when it is safe to use which version of segwit.';
 function _toFutureSegwitAddress(output, network) {
   const data = output.slice(2);
   if (
@@ -28,6 +33,7 @@ function _toFutureSegwitAddress(output, network) {
     throw new TypeError('Invalid version for segwit address');
   if (output[1] !== data.length)
     throw new TypeError('Invalid script for segwit address');
+  console.warn(FUTURE_SEGWIT_VERSION_WARNING);
   return toBech32(data, version, network.bech32);
 }
 function fromBase58Check(address) {
@@ -128,11 +134,13 @@ function toOutputScript(address, network) {
         decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
         decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
         decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
-      )
+      ) {
+        console.warn(FUTURE_SEGWIT_VERSION_WARNING);
         return bscript.compile([
           decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
           decodeBech32.data,
         ]);
+      }
     }
   }
   throw new Error(address + ' has no matching Script');
diff --git a/ts_src/address.ts b/ts_src/address.ts
index d8111a7..753589d 100644
--- a/ts_src/address.ts
+++ b/ts_src/address.ts
@@ -23,6 +23,11 @@ const FUTURE_SEGWIT_MIN_SIZE: number = 2;
 const FUTURE_SEGWIT_MAX_VERSION: number = 16;
 const FUTURE_SEGWIT_MIN_VERSION: number = 1;
 const FUTURE_SEGWIT_VERSION_DIFF: number = 0x50;
+const FUTURE_SEGWIT_VERSION_WARNING: string =
+  'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
+  'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
+  'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
+  'then decide when it is safe to use which version of segwit.';
 
 function _toFutureSegwitAddress(output: Buffer, network: Network): string {
   const data = output.slice(2);
@@ -44,6 +49,8 @@ function _toFutureSegwitAddress(output: Buffer, network: Network): string {
   if (output[1] !== data.length)
     throw new TypeError('Invalid script for segwit address');
 
+  console.warn(FUTURE_SEGWIT_VERSION_WARNING);
+
   return toBech32(data, version, network.bech32);
 }
 
@@ -163,11 +170,14 @@ export function toOutputScript(address: string, network?: Network): Buffer {
         decodeBech32.version <= FUTURE_SEGWIT_MAX_VERSION &&
         decodeBech32.data.length >= FUTURE_SEGWIT_MIN_SIZE &&
         decodeBech32.data.length <= FUTURE_SEGWIT_MAX_SIZE
-      )
+      ) {
+        console.warn(FUTURE_SEGWIT_VERSION_WARNING);
+
         return bscript.compile([
           decodeBech32.version + FUTURE_SEGWIT_VERSION_DIFF,
           decodeBech32.data,
         ]);
+      }
     }
   }
 

From 11202eb74cc9d9a7338ef4aa04c78061f0544289 Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Sat, 27 Nov 2021 08:42:12 +0900
Subject: [PATCH 7/8] 6.0.1

---
 package-lock.json | 2 +-
 package.json      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index d6b9ce8..2ea42ae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "bitcoinjs-lib",
-  "version": "6.0.0",
+  "version": "6.0.1",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index 36d9003..dc93c53 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "bitcoinjs-lib",
-  "version": "6.0.0",
+  "version": "6.0.1",
   "description": "Client-side Bitcoin JavaScript library",
   "main": "./src/index.js",
   "types": "./src/index.d.ts",

From 2edfb992fa09761e09490b5efa27ba13a77de374 Mon Sep 17 00:00:00 2001
From: Vlad Stan <stan.v.vlad@gmail.com>
Date: Fri, 17 Dec 2021 13:27:35 +0200
Subject: [PATCH 8/8] test: upgrade ecpair lib to version 2.0.1

---
 package-lock.json                     | 123 ++------------------------
 package.json                          |   4 +-
 test/integration/addresses.spec.ts    |   5 +-
 test/integration/cltv.spec.ts         |   5 +-
 test/integration/csv.spec.ts          |   5 +-
 test/integration/payments.spec.ts     |   5 +-
 test/integration/transactions.spec.ts |   4 +-
 test/psbt.spec.ts                     |   3 +-
 8 files changed, 32 insertions(+), 122 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 2ea42ae..3e5bd51 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -541,15 +541,6 @@
       "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
       "dev": true
     },
-    "bindings": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
-      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
-      "dev": true,
-      "requires": {
-        "file-uri-to-path": "1.0.0"
-      }
-    },
     "bip174": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.0.1.tgz",
@@ -640,12 +631,6 @@
         "fill-range": "^7.0.1"
       }
     },
-    "brorand": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
-      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
-      "dev": true
-    },
     "browser-stdout": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
@@ -931,59 +916,14 @@
       "dev": true
     },
     "ecpair": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-1.0.0.tgz",
-      "integrity": "sha512-1L+P/ivLC3eKHgqcX1M9tFYQWXDoqwJ3zQnN7zDaTtLpiCQKpFTaAZvnsPC5PkWB4q3EPFAHffCLvjfCqRjuwQ==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.0.1.tgz",
+      "integrity": "sha512-iT3wztQMeE/nDTlfnAg8dAFUfBS7Tq2BXzq3ae6L+pWgFU0fQ3l0woTzdTBrJV3OxBjxbzjq8EQhAbEmJNWFSw==",
       "dev": true,
       "requires": {
-        "randombytes": "^2.0.1",
-        "tiny-secp256k1": "^1.1.6",
-        "typeforce": "^1.11.3",
-        "wif": "^2.0.1"
-      },
-      "dependencies": {
-        "tiny-secp256k1": {
-          "version": "1.1.6",
-          "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz",
-          "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==",
-          "dev": true,
-          "requires": {
-            "bindings": "^1.3.0",
-            "bn.js": "^4.11.8",
-            "create-hmac": "^1.1.7",
-            "elliptic": "^6.4.0",
-            "nan": "^2.13.2"
-          }
-        }
-      }
-    },
-    "elliptic": {
-      "version": "6.5.4",
-      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
-      "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
-      "dev": true,
-      "requires": {
-        "bn.js": "^4.11.9",
-        "brorand": "^1.1.0",
-        "hash.js": "^1.0.0",
-        "hmac-drbg": "^1.0.1",
-        "inherits": "^2.0.4",
-        "minimalistic-assert": "^1.0.1",
-        "minimalistic-crypto-utils": "^1.0.1"
-      },
-      "dependencies": {
-        "bn.js": {
-          "version": "4.12.0",
-          "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
-          "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
-          "dev": true
-        },
-        "inherits": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-          "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-          "dev": true
-        }
+        "randombytes": "^2.1.0",
+        "typeforce": "^1.18.0",
+        "wif": "^2.0.6"
       }
     },
     "emoji-regex": {
@@ -1040,12 +980,6 @@
       "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
       "dev": true
     },
-    "file-uri-to-path": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
-      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
-      "dev": true
-    },
     "fill-keys": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
@@ -1218,16 +1152,6 @@
         "safe-buffer": "^5.0.1"
       }
     },
-    "hash.js": {
-      "version": "1.1.7",
-      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
-      "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
-      "dev": true,
-      "requires": {
-        "inherits": "^2.0.3",
-        "minimalistic-assert": "^1.0.1"
-      }
-    },
     "hasha": {
       "version": "5.2.2",
       "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
@@ -1244,17 +1168,6 @@
       "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
       "dev": true
     },
-    "hmac-drbg": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
-      "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
-      "dev": true,
-      "requires": {
-        "hash.js": "^1.0.3",
-        "minimalistic-assert": "^1.0.0",
-        "minimalistic-crypto-utils": "^1.0.1"
-      }
-    },
     "hoodwink": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/hoodwink/-/hoodwink-2.0.0.tgz",
@@ -1640,18 +1553,6 @@
         "pushdata-bitcoin": "^1.0.1"
       }
     },
-    "minimalistic-assert": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
-      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
-      "dev": true
-    },
-    "minimalistic-crypto-utils": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
-      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
-      "dev": true
-    },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -1720,12 +1621,6 @@
       "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
       "dev": true
     },
-    "nan": {
-      "version": "2.15.0",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
-      "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
-      "dev": true
-    },
     "node-environment-flags": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
@@ -2479,9 +2374,9 @@
       }
     },
     "tiny-secp256k1": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.1.1.tgz",
-      "integrity": "sha512-pdENPcbI4l3Br6sPVuC5RWONHojcPjBiXljIBvQ5UIN/MD6wPzmJ8mpDnkps3O7FFfT+fLqGXo2MdFdRQaPWUg==",
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.1.2.tgz",
+      "integrity": "sha512-8qPw7zDK6Hco2tVGYGQeOmOPp/hZnREwy2iIkcq0ygAuqc9WHo29vKN94lNymh1QbB3nthtAMF6KTIrdbsIotA==",
       "dev": true,
       "requires": {
         "uint8array-tools": "0.0.6"
diff --git a/package.json b/package.json
index dc93c53..c5553d5 100644
--- a/package.json
+++ b/package.json
@@ -73,7 +73,7 @@
     "bn.js": "^4.11.8",
     "bs58": "^4.0.0",
     "dhttp": "^3.0.0",
-    "ecpair": "^1.0.0",
+    "ecpair": "^2.0.1",
     "hoodwink": "^2.0.0",
     "minimaldata": "^1.0.2",
     "mocha": "^7.1.1",
@@ -84,7 +84,7 @@
     "randombytes": "^2.1.0",
     "regtest-client": "0.2.0",
     "rimraf": "^2.6.3",
-    "tiny-secp256k1": "^2.1.1",
+    "tiny-secp256k1": "^2.1.2",
     "ts-node": "^8.3.0",
     "tslint": "^6.1.3",
     "typescript": "^4.4.4"
diff --git a/test/integration/addresses.spec.ts b/test/integration/addresses.spec.ts
index 2b24ef5..d6e758b 100644
--- a/test/integration/addresses.spec.ts
+++ b/test/integration/addresses.spec.ts
@@ -1,8 +1,11 @@
 import * as assert from 'assert';
-import { ECPair } from 'ecpair';
+import ECPairFactory from 'ecpair';
+import * as ecc from 'tiny-secp256k1';
 import { describe, it } from 'mocha';
 import * as bitcoin from '../..';
 import { regtestUtils } from './_regtest';
+
+const ECPair = ECPairFactory(ecc);
 const dhttp = regtestUtils.dhttp;
 const TESTNET = bitcoin.networks.testnet;
 
diff --git a/test/integration/cltv.spec.ts b/test/integration/cltv.spec.ts
index c1a52de..04944eb 100644
--- a/test/integration/cltv.spec.ts
+++ b/test/integration/cltv.spec.ts
@@ -1,8 +1,11 @@
 import * as assert from 'assert';
-import { ECPair } from 'ecpair';
+import ECPairFactory from 'ecpair';
+import * as ecc from 'tiny-secp256k1';
 import { before, describe, it } from 'mocha';
 import * as bitcoin from '../..';
 import { regtestUtils } from './_regtest';
+
+const ECPair = ECPairFactory(ecc);
 const regtest = regtestUtils.network;
 const bip65 = require('bip65');
 
diff --git a/test/integration/csv.spec.ts b/test/integration/csv.spec.ts
index 9993d5c..742d68f 100644
--- a/test/integration/csv.spec.ts
+++ b/test/integration/csv.spec.ts
@@ -1,9 +1,12 @@
 import * as assert from 'assert';
 import { PsbtInput } from 'bip174/src/lib/interfaces';
-import { ECPair } from 'ecpair';
+import ECPairFactory from 'ecpair';
+import * as ecc from 'tiny-secp256k1';
 import { before, describe, it } from 'mocha';
 import * as bitcoin from '../..';
 import { regtestUtils } from './_regtest';
+
+const ECPair = ECPairFactory(ecc);
 const regtest = regtestUtils.network;
 const bip68 = require('bip68');
 const varuint = require('varuint-bitcoin');
diff --git a/test/integration/payments.spec.ts b/test/integration/payments.spec.ts
index ea7294e..d9d7fde 100644
--- a/test/integration/payments.spec.ts
+++ b/test/integration/payments.spec.ts
@@ -1,7 +1,10 @@
-import { ECPair } from 'ecpair';
+import ECPairFactory from 'ecpair';
+import * as ecc from 'tiny-secp256k1';
 import { describe, it } from 'mocha';
 import * as bitcoin from '../..';
 import { regtestUtils } from './_regtest';
+
+const ECPair = ECPairFactory(ecc);
 const NETWORK = regtestUtils.network;
 const keyPairs = [
   ECPair.makeRandom({ network: NETWORK }),
diff --git a/test/integration/transactions.spec.ts b/test/integration/transactions.spec.ts
index 51e44a0..ba7f2fe 100644
--- a/test/integration/transactions.spec.ts
+++ b/test/integration/transactions.spec.ts
@@ -1,10 +1,12 @@
 import * as assert from 'assert';
 import BIP32Factory from 'bip32';
 import * as ecc from 'tiny-secp256k1';
-import { ECPair } from 'ecpair';
+import ECPairFactory from 'ecpair';
 import { describe, it } from 'mocha';
 import * as bitcoin from '../..';
 import { regtestUtils } from './_regtest';
+
+const ECPair = ECPairFactory(ecc);
 const rng = require('randombytes');
 const regtest = regtestUtils.network;
 const bip32 = BIP32Factory(ecc);
diff --git a/test/psbt.spec.ts b/test/psbt.spec.ts
index 32d81ba..f583e80 100644
--- a/test/psbt.spec.ts
+++ b/test/psbt.spec.ts
@@ -2,10 +2,11 @@ import * as assert from 'assert';
 import BIP32Factory from 'bip32';
 import * as ecc from 'tiny-secp256k1';
 import * as crypto from 'crypto';
-import { ECPair } from 'ecpair';
+import ECPairFactory from 'ecpair';
 import { describe, it } from 'mocha';
 
 const bip32 = BIP32Factory(ecc);
+const ECPair = ECPairFactory(ecc);
 
 import { networks as NETWORKS, payments, Psbt, Signer, SignerAsync } from '..';