diff --git a/package-lock.json b/package-lock.json
index d528ba3..bb292ce 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "bitcoinjs-lib",
-  "version": "5.1.3",
+  "version": "5.1.4",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -200,9 +200,9 @@
       }
     },
     "bip174": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/bip174/-/bip174-1.0.0.tgz",
-      "integrity": "sha512-AaoWrkYtv6A2y8H+qzs6NvRWypzNbADT8PQGpM9rnP+jLzeol+uzhe3Myeuq/dwrHYtmsW8V71HmX2oXhQGagw=="
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/bip174/-/bip174-1.0.1.tgz",
+      "integrity": "sha512-Mq2aFs1TdMfxBpYPg7uzjhsiXbAtoVq44TNjEWtvuZBiBgc3m7+n55orYMtTAxdg7jWbL4DtH0MKocJER4xERQ=="
     },
     "bip32": {
       "version": "2.0.4",
diff --git a/package.json b/package.json
index be2321f..07bb419 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "bitcoinjs-lib",
-  "version": "5.1.3",
+  "version": "5.1.4",
   "description": "Client-side Bitcoin JavaScript library",
   "main": "./src/index.js",
   "types": "./types/index.d.ts",
@@ -47,7 +47,7 @@
   "dependencies": {
     "@types/node": "10.12.18",
     "bech32": "^1.1.2",
-    "bip174": "^1.0.0",
+    "bip174": "^1.0.1",
     "bip32": "^2.0.4",
     "bip66": "^1.1.0",
     "bitcoin-ops": "^1.4.0",
diff --git a/src/psbt.js b/src/psbt.js
index 051de6e..e134774 100644
--- a/src/psbt.js
+++ b/src/psbt.js
@@ -815,13 +815,29 @@ function getHashForSig(inputIndex, input, cache, sighashTypes) {
     } else {
       script = prevout.script;
     }
-    if (isP2WPKH(script) || isP2WSHScript(script)) {
-      throw new Error(
-        `Input #${inputIndex} has nonWitnessUtxo but segwit script: ` +
-          `${script.toString('hex')}`,
+    if (isP2WSHScript(script)) {
+      if (!input.witnessScript)
+        throw new Error('Segwit input needs witnessScript if not P2WPKH');
+      checkWitnessScript(inputIndex, script, input.witnessScript);
+      hash = unsignedTx.hashForWitnessV0(
+        inputIndex,
+        input.witnessScript,
+        prevout.value,
+        sighashType,
       );
+      script = input.witnessScript;
+    } else if (isP2WPKH(script)) {
+      // P2WPKH uses the P2PKH template for prevoutScript when signing
+      const signingScript = payments.p2pkh({ hash: script.slice(2) }).output;
+      hash = unsignedTx.hashForWitnessV0(
+        inputIndex,
+        signingScript,
+        prevout.value,
+        sighashType,
+      );
+    } else {
+      hash = unsignedTx.hashForSignature(inputIndex, script, sighashType);
     }
-    hash = unsignedTx.hashForSignature(inputIndex, script, sighashType);
   } else if (input.witnessUtxo) {
     let _script; // so we don't shadow the `let script` above
     if (input.redeemScript) {
@@ -927,11 +943,14 @@ function getScriptFromInput(inputIndex, input, cache) {
     isP2SH: false,
     isP2WSH: false,
   };
-  if (input.nonWitnessUtxo) {
-    if (input.redeemScript) {
-      res.isP2SH = true;
-      res.script = input.redeemScript;
-    } else {
+  res.isP2SH = !!input.redeemScript;
+  res.isP2WSH = !!input.witnessScript;
+  if (input.witnessScript) {
+    res.script = input.witnessScript;
+  } else if (input.redeemScript) {
+    res.script = input.redeemScript;
+  } else {
+    if (input.nonWitnessUtxo) {
       const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(
         cache,
         input,
@@ -939,22 +958,12 @@ function getScriptFromInput(inputIndex, input, cache) {
       );
       const prevoutIndex = unsignedTx.ins[inputIndex].index;
       res.script = nonWitnessUtxoTx.outs[prevoutIndex].script;
+    } else if (input.witnessUtxo) {
+      res.script = input.witnessUtxo.script;
     }
-  } else if (input.witnessUtxo) {
+  }
+  if (input.witnessScript || isP2WPKH(res.script)) {
     res.isSegwit = true;
-    res.isP2SH = !!input.redeemScript;
-    res.isP2WSH = !!input.witnessScript;
-    if (input.witnessScript) {
-      res.script = input.witnessScript;
-    } else if (input.redeemScript) {
-      res.script = payments.p2wpkh({
-        hash: input.redeemScript.slice(2),
-      }).output;
-    } else {
-      res.script = payments.p2wpkh({
-        hash: input.witnessUtxo.script.slice(2),
-      }).output;
-    }
   }
   return res;
 }
diff --git a/test/fixtures/psbt.json b/test/fixtures/psbt.json
index 22655da..95c980e 100644
--- a/test/fixtures/psbt.json
+++ b/test/fixtures/psbt.json
@@ -513,7 +513,7 @@
     {
       "type": "P2SH-P2WPKH",
       "psbt": "cHNidP8BAFUCAAAAATIK6DMTn8bbrG7ZdiiVU3/YAgzyk3dwa56En58YfXbDAAAAAAD/////AYA4AQAAAAAAGXapFNU4SHWUW9ZNz+BcxCiuU/7UtJoMiKwAAAAAAAEAvgIAAAABly2BCiYZ3slqurlLwE7b8UXINYKfrJ9sQlBovzBAwFsBAAAAa0gwRQIhAJJ+Hyniw+KneWomeQYrP1duH7cfQ3j8GN6/RshZCfuvAiBux7Uu/5QqmSmL+LjoWZY2b9TWdluY6zLTkQWIornmYwEhAvUo9Sy7Pu44z84ZZPrQMQxBPpDJyy9WlLQMGdGIuUy7/////wGQXwEAAAAAABepFPwojcWCH2oE9dUjMmLC3bdK/xeWhwAAAAAiAgKj88rhJwk3Zxm0p0Rp+xC/6cxmj+I741DHPWPWN7iA+0cwRAIgTRhd9WUpoHYl9tUVmoJ336fJAJInIjdYsoatvRiW8hgCIGOYMlpKRHiHA428Sfa2CdAIIGGQCGhuIgIzj2FN6USnAQEEFgAU4sZupXPxqhcsOB1ghJxBvH4XcesAAA==",
-      "result": "cHNidP8BAFUCAAAAATIK6DMTn8bbrG7ZdiiVU3/YAgzyk3dwa56En58YfXbDAAAAAAD/////AYA4AQAAAAAAGXapFNU4SHWUW9ZNz+BcxCiuU/7UtJoMiKwAAAAAAAEAvgIAAAABly2BCiYZ3slqurlLwE7b8UXINYKfrJ9sQlBovzBAwFsBAAAAa0gwRQIhAJJ+Hyniw+KneWomeQYrP1duH7cfQ3j8GN6/RshZCfuvAiBux7Uu/5QqmSmL+LjoWZY2b9TWdluY6zLTkQWIornmYwEhAvUo9Sy7Pu44z84ZZPrQMQxBPpDJyy9WlLQMGdGIuUy7/////wGQXwEAAAAAABepFPwojcWCH2oE9dUjMmLC3bdK/xeWhwAAAAABBxcWABTixm6lc/GqFyw4HWCEnEG8fhdx6wAA"
+      "result": "cHNidP8BAFUCAAAAATIK6DMTn8bbrG7ZdiiVU3/YAgzyk3dwa56En58YfXbDAAAAAAD/////AYA4AQAAAAAAGXapFNU4SHWUW9ZNz+BcxCiuU/7UtJoMiKwAAAAAAAEAvgIAAAABly2BCiYZ3slqurlLwE7b8UXINYKfrJ9sQlBovzBAwFsBAAAAa0gwRQIhAJJ+Hyniw+KneWomeQYrP1duH7cfQ3j8GN6/RshZCfuvAiBux7Uu/5QqmSmL+LjoWZY2b9TWdluY6zLTkQWIornmYwEhAvUo9Sy7Pu44z84ZZPrQMQxBPpDJyy9WlLQMGdGIuUy7/////wGQXwEAAAAAABepFPwojcWCH2oE9dUjMmLC3bdK/xeWhwAAAAABBxcWABTixm6lc/GqFyw4HWCEnEG8fhdx6wEIawJHMEQCIE0YXfVlKaB2JfbVFZqCd9+nyQCSJyI3WLKGrb0YlvIYAiBjmDJaSkR4hwONvEn2tgnQCCBhkAhobiICM49hTelEpwEhAqPzyuEnCTdnGbSnRGn7EL/pzGaP4jvjUMc9Y9Y3uID7AAA="
     },
     {
       "type": "P2WPKH",
diff --git a/test/integration/transactions-psbt.js b/test/integration/transactions-psbt.js
index 7b9d9c5..9040fc2 100644
--- a/test/integration/transactions-psbt.js
+++ b/test/integration/transactions-psbt.js
@@ -282,6 +282,36 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
     });
   });
 
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input with nonWitnessUtxo', async () => {
+    // For learning purposes, ignore this test.
+    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+    const p2sh = createPayment('p2sh-p2wpkh');
+    const inputData = await getInputData(5e4, p2sh.payment, false, 'p2sh');
+    const inputData2 = await getInputData(5e4, p2sh.payment, false, 'p2sh');
+    const keyPair = p2sh.keys[0];
+    const outputData = {
+      script: p2sh.payment.output,
+      value: 2e4,
+    };
+    const outputData2 = {
+      script: p2sh.payment.output,
+      value: 7e4,
+    };
+    const tx = new bitcoin.Psbt()
+      .addInputs([inputData, inputData2])
+      .addOutputs([outputData, outputData2])
+      .signAllInputs(keyPair)
+      .finalizeAllInputs()
+      .extractTransaction();
+    await regtestUtils.broadcast(tx.toHex());
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address: p2sh.payment.address,
+      vout: 0,
+      value: 2e4,
+    });
+  });
+
   it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => {
     // the only thing that changes is you don't give a redeemscript for input data
 
@@ -316,6 +346,29 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
     });
   });
 
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input with nonWitnessUtxo', async () => {
+    // For learning purposes, ignore this test.
+    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+    const p2wpkh = createPayment('p2wpkh');
+    const inputData = await getInputData(5e4, p2wpkh.payment, false, 'noredeem');
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInput(0, p2wpkh.keys[0]);
+    psbt.finalizeAllInputs();
+    const tx = psbt.extractTransaction();
+    await regtestUtils.broadcast(tx.toHex());
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address: regtestUtils.RANDOM_ADDRESS,
+      vout: 0,
+      value: 2e4,
+    });
+  });
+
   it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', async () => {
     const p2wsh = createPayment('p2wsh-p2pk');
     const inputData = await getInputData(5e4, p2wsh.payment, true, 'p2wsh');
@@ -356,6 +409,29 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
     });
   });
 
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input with nonWitnessUtxo', async () => {
+    // For learning purposes, ignore this test.
+    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+    const p2wsh = createPayment('p2wsh-p2pk');
+    const inputData = await getInputData(5e4, p2wsh.payment, false, 'p2wsh');
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInput(0, p2wsh.keys[0]);
+    psbt.finalizeAllInputs();
+    const tx = psbt.extractTransaction();
+    await regtestUtils.broadcast(tx.toHex());
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address: regtestUtils.RANDOM_ADDRESS,
+      vout: 0,
+      value: 2e4,
+    });
+  });
+
   it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input', async () => {
     const p2sh = createPayment('p2sh-p2wsh-p2ms(3 of 4)');
     const inputData = await getInputData(5e4, p2sh.payment, true, 'p2sh-p2wsh');
@@ -406,6 +482,31 @@ describe('bitcoinjs-lib (transactions with psbt)', () => {
     });
   });
 
+  it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input with nonWitnessUtxo', async () => {
+    // For learning purposes, ignore this test.
+    // REPEATING ABOVE BUT WITH nonWitnessUtxo by passing false to getInputData
+    const p2sh = createPayment('p2sh-p2wsh-p2ms(3 of 4)');
+    const inputData = await getInputData(5e4, p2sh.payment, false, 'p2sh-p2wsh');
+    const psbt = new bitcoin.Psbt({ network: regtest })
+      .addInput(inputData)
+      .addOutput({
+        address: regtestUtils.RANDOM_ADDRESS,
+        value: 2e4,
+      })
+      .signInput(0, p2sh.keys[0])
+      .signInput(0, p2sh.keys[2])
+      .signInput(0, p2sh.keys[3]);
+    psbt.finalizeAllInputs();
+    const tx = psbt.extractTransaction();
+    await regtestUtils.broadcast(tx.toHex());
+    await regtestUtils.verify({
+      txId: tx.getId(),
+      address: regtestUtils.RANDOM_ADDRESS,
+      vout: 0,
+      value: 2e4,
+    });
+  });
+
   it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input using HD', async () => {
     const hdRoot = bip32.fromSeed(rng(64));
     const masterFingerprint = hdRoot.fingerprint;
diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts
index a83ced3..0431056 100644
--- a/ts_src/psbt.ts
+++ b/ts_src/psbt.ts
@@ -1025,7 +1025,7 @@ function getHashForSig(
     }
 
     const prevoutIndex = unsignedTx.ins[inputIndex].index;
-    const prevout = nonWitnessUtxoTx.outs[prevoutIndex];
+    const prevout = nonWitnessUtxoTx.outs[prevoutIndex] as Output;
 
     if (input.redeemScript) {
       // If a redeemScript is provided, the scriptPubKey must be for that redeemScript
@@ -1035,14 +1035,29 @@ function getHashForSig(
       script = prevout.script;
     }
 
-    if (isP2WPKH(script) || isP2WSHScript(script)) {
-      throw new Error(
-        `Input #${inputIndex} has nonWitnessUtxo but segwit script: ` +
-          `${script.toString('hex')}`,
+    if (isP2WSHScript(script)) {
+      if (!input.witnessScript)
+        throw new Error('Segwit input needs witnessScript if not P2WPKH');
+      checkWitnessScript(inputIndex, script, input.witnessScript);
+      hash = unsignedTx.hashForWitnessV0(
+        inputIndex,
+        input.witnessScript,
+        prevout.value,
+        sighashType,
       );
+      script = input.witnessScript;
+    } else if (isP2WPKH(script)) {
+      // P2WPKH uses the P2PKH template for prevoutScript when signing
+      const signingScript = payments.p2pkh({ hash: script.slice(2) }).output!;
+      hash = unsignedTx.hashForWitnessV0(
+        inputIndex,
+        signingScript,
+        prevout.value,
+        sighashType,
+      );
+    } else {
+      hash = unsignedTx.hashForSignature(inputIndex, script, sighashType);
     }
-
-    hash = unsignedTx.hashForSignature(inputIndex, script, sighashType);
   } else if (input.witnessUtxo) {
     let _script: Buffer; // so we don't shadow the `let script` above
     if (input.redeemScript) {
@@ -1165,11 +1180,14 @@ function getScriptFromInput(
     isP2SH: false,
     isP2WSH: false,
   };
-  if (input.nonWitnessUtxo) {
-    if (input.redeemScript) {
-      res.isP2SH = true;
-      res.script = input.redeemScript;
-    } else {
+  res.isP2SH = !!input.redeemScript;
+  res.isP2WSH = !!input.witnessScript;
+  if (input.witnessScript) {
+    res.script = input.witnessScript;
+  } else if (input.redeemScript) {
+    res.script = input.redeemScript;
+  } else {
+    if (input.nonWitnessUtxo) {
       const nonWitnessUtxoTx = nonWitnessUtxoTxFromCache(
         cache,
         input,
@@ -1177,22 +1195,12 @@ function getScriptFromInput(
       );
       const prevoutIndex = unsignedTx.ins[inputIndex].index;
       res.script = nonWitnessUtxoTx.outs[prevoutIndex].script;
+    } else if (input.witnessUtxo) {
+      res.script = input.witnessUtxo.script;
     }
-  } else if (input.witnessUtxo) {
+  }
+  if (input.witnessScript || isP2WPKH(res.script!)) {
     res.isSegwit = true;
-    res.isP2SH = !!input.redeemScript;
-    res.isP2WSH = !!input.witnessScript;
-    if (input.witnessScript) {
-      res.script = input.witnessScript;
-    } else if (input.redeemScript) {
-      res.script = payments.p2wpkh({
-        hash: input.redeemScript.slice(2),
-      }).output!;
-    } else {
-      res.script = payments.p2wpkh({
-        hash: input.witnessUtxo.script.slice(2),
-      }).output!;
-    }
   }
   return res;
 }