• About
  • FAQ
  • Earn Bitcoin while Surfing the net
  • Buy & Sell Crypto on Paxful
Newsletter
Approx Foundation
  • Home
    • Home – Layout 1
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Business
  • Guide
  • Contact Us
No Result
View All Result
  • Home
    • Home – Layout 1
  • Bitcoin
  • Ethereum
  • Regulation
  • Market
  • Blockchain
  • Business
  • Guide
  • Contact Us
No Result
View All Result
Approx Foundation
No Result
View All Result
Home Bitcoin

javascript – bitcoinjs-lib: “bad-witness-nonstandard” when spending complex P2WSH with OP_IF/ELSE

Moussa by Moussa
August 20, 2025
in Bitcoin
0
peer discovery – how to obtain the IP addresses of nodes for mining pools?
189
SHARES
1.5k
VIEWS
Share on FacebookShare on Twitter


I’m trying to create and spend a P2WSH transaction on testnet with a “complex” script, but I’m running into a bad-witness-nonstandard error that I can’t figure out.

My Goal

I want to create a P2WSH output with a script that allows spending under two conditions:

A 3-of-4 multisig signature is provided.
OR
A timelock (e.g., 5 minutes) has passed AND a single recovery signature is provided.
The script logic uses OP_IF for the multisig path and OP_ELSE for the timelock path.

The Problem

I can generate a wallet, derive the P2WSH address, and fund it correctly. The funding transaction creates a standard P2WSH output (OP_0 <32-byte-hash>).

However, when I try to spend this UTXO via the 3-of-4 multisig path, my transaction is rejected by my Bitcoin Core node’s testmempoolaccept with the error: mandatory-script-verify-flag-failed (bad-witness-nonstandard)

What I’ve Already Verified

The P2W

  1. SH address derived from my scripts matches the address I funded.
  2. A debug script confirms that my redeemScript is generated deterministically and its SHA256 hash correctly matches the hash in the funded UTXO’s scriptPubKey.
  3. The funding transaction is correct and standard.

To Reproduce the Error

Here is all the code and data needed to reproduce the problem.

  1. package.json dependencies:
    {
      "dependencies": {
        "@types/node": "^20.12.12",
        "bitcoinjs-lib": "^6.1.5",
        "ecpair": "^2.1.0",
        "ts-node": "^10.9.2",
        "tiny-secp256k1": "^2.2.3",
        "typescript": "^5.4.5"
      }
    }
  1. Wallet Generation Script (index.ts): This script generates the keys and wallet.json.
import * as bitcoin from 'bitcoinjs-lib'; import ECPairFactory from 'ecpair'; 
import * as ecc from 'tiny-secp256k1'; import * as fs from 'fs';

// Initialisation const ECPair = ECPairFactory(ecc); bitcoin.initEccLib(ecc);

const network = bitcoin.networks.testnet;

// --- 1. Key Generation --- 
const multisigKeys = [
    ECPair.makeRandom({ network }),
    ECPair.makeRandom({ network }),
    ECPair.makeRandom({ network }),
    ECPair.makeRandom({ network }), ]; 

const multisigPubkeys = multisigKeys.map(key => Buffer.from(key.publicKey)).sort((a, b) => a.compare(b)); 
const recoveryKey = ECPair.makeRandom({ network }); const recoveryPubkey = Buffer.from(recoveryKey.publicKey);

// --- 2. Timelock Definition (5 minutes for testing) --- 
const date = new Date(); 
date.setMinutes(date.getMinutes() + 5); 
const lockTime = Math.floor(date.getTime() / 1000); 
const lockTimeBuffer = bitcoin.script.number.encode(lockTime);

// --- 3. Redeem Script Construction --- 
const redeemScript = bitcoin.script.compile([
    bitcoin.opcodes.OP_IF,
    bitcoin.opcodes.OP_3,
    ...multisigPubkeys,
    bitcoin.opcodes.OP_4,
    bitcoin.opcodes.OP_CHECKMULTISIG,
    bitcoin.opcodes.OP_ELSE,
    lockTimeBuffer,
    bitcoin.opcodes.OP_CHECKLOCKTIMEVERIFY,
    bitcoin.opcodes.OP_DROP,
    recoveryPubkey,
    bitcoin.opcodes.OP_CHECKSIG,
    bitcoin.opcodes.OP_ENDIF, ]);

// --- 4. Address Creation --- 
const p2wsh = bitcoin.payments.p2wsh({
    redeem: { output: redeemScript, network },
    network, });

// --- 5. Save Data --- 
const wallet = {
    network: 'testnet',
    lockTime: lockTime,
    lockTimeDate: date.toISOString(),
    p2wshAddress: p2wsh.address,
    redeemScriptHex: redeemScript.toString('hex'),
    multisigKeysWIF: multisigKeys.map(k => k.toWIF()),
    recoveryKeyWIF: recoveryKey.toWIF(), };

fs.writeFileSync('wallet.json', JSON.stringify(wallet, null, 2));

console.log('Wallet generated and saved to wallet.json'); 
console.log('P2WSH Deposit Address:', wallet.p2wshAddress);
  1. Multisig Spending Script (1_spend_multisig.ts): This is the script that fails with bad-witness-nonstandard.
import * as bitcoin from 'bitcoinjs-lib'; 
import ECPairFactory from 'ecpair'; 
import * as ecc from 'tiny-secp256k1'; 
import * as fs from 'fs';

// --- UTXO Configuration --- 
const UTXO_TXID = 'PASTE_YOUR_FUNDING_TXID_HERE'; 
const UTXO_INDEX = 0; // Or 1, depending on the output 
const UTXO_VALUE_SATS = 10000; // Amount in satoshis 
const DESTINATION_ADDRESS = 'PASTE_A_TESTNET_ADDRESS_HERE'; 
const FEE_SATS = 2000;

// --- Initialization --- 
const ECPair = ECPairFactory(ecc); bitcoin.initEccLib(ecc); 
const network = bitcoin.networks.testnet;

// --- 1. Load Wallet --- 
const wallet = JSON.parse(fs.readFileSync('wallet.json', 'utf-8')); 
const redeemScript = Buffer.from(wallet.redeemScriptHex, 'hex'); 
const p2wsh = bitcoin.payments.p2wsh({ redeem: { output: redeemScript, network }, network }); 
const multisigKeys = wallet.multisigKeysWIF.map((wif: string) => ECPair.fromWIF(wif, network));

// --- 2. Build PSBT --- 
const psbt = new bitcoin.Psbt({ network }); psbt.addInput({
    hash: UTXO_TXID,
    index: UTXO_INDEX,
    witnessUtxo: { script: p2wsh.output!, value: UTXO_VALUE_SATS },
    witnessScript: redeemScript, }); 
psbt.addOutput({ address: DESTINATION_ADDRESS, value: UTXO_VALUE_SATS - FEE_SATS });

// --- 3. Sign Transaction --- 
const createSigner = (key: any) => ({   publicKey: Buffer.from(key.publicKey),   
    sign: (hash: Buffer): Buffer => Buffer.from(key.sign(hash)), }); // Sign with 3 of the 4 keys 
psbt.signInput(0, createSigner(multisigKeys[0])); 
psbt.signInput(0, createSigner(multisigKeys[1])); 
psbt.signInput(0, createSigner(multisigKeys[2]));

// --- 4. Finalize Transaction --- 
const finalizer = (inputIndex: number, input: any) => {
    const emptySignature = Buffer.from([]); // Placeholder for OP_CHECKMULTISIG bug
    const partialSignatures = input.partialSig.map((ps: any) => ps.signature);
    const witnessStack = [
        emptySignature,
        ...partialSignatures,
        bitcoin.script.number.encode(1), // Standard way to push OP_1
        redeemScript,
    ];
    const witness = witnessStack.reduce((acc, item) => {
        const push = bitcoin.script.compile([item]);
        return Buffer.concat([acc, push]);
    }, Buffer.from([witnessStack.length]));
    return { finalScriptWitness: witness }; }; psbt.finalizeInput(0, finalizer);

// --- 5. Extract and create validation command --- 
const tx = psbt.extractTransaction(); 
const txHex = tx.toHex(); 
console.log('\n--- testmempoolaccept command ---'); 
console.log(`bitcoin-cli -testnet testmempoolaccept '["${txHex}"]'`);
  1. Data to reproduce:

wallet.json (TESTNET KEYS, NO VALUE):

{   
    "network": "testnet",   
    "lockTime": 1723986942,   
    "lockTimeDate": "2025-08-18T13:15:42.339Z",   
    "p2wshAddress": "tb1qztq5rg30lv8y7kup7tftuelppcy2f9u9ygm8daq7gv4lgf0dw3ss3hj9qw",   
    "redeemScriptHex": "6353210200847c4a13f98cb1e3138bda175ba6f4c7ffd9e03a4c8617878ab03cf4a4a97921024b3e2544b4e311985477d88ac77ea00aa68f85490d0c663fba38fcdf582d043f2102c822f5026d382a93476d20de66c87c5e4e4997654817bfacc69b29f2dc8b6a10210328c2213b0813b4dac9c063f674b2c61dc50344c6e093df045c8ee2fe09f67bd854ae6704c413a368b1752103c5512e31f8a2555a116146262382be4be774fca326a2ee01d71e0fe33ffe4925ac68", 
    "multisigKeysWIF": [
        "cT5h8LgJ2a4V3c4yF5g6H7j8K9L0M1n2p3q4R5s6T7u8V9w0XyZ",
        "cT5h8LgJ2a4V3c4yF5g6H7j8K9L0M1n2p3q4R5s6T7u8V9w0XyZ",
        "cT5h8LgJ2a4V3c4yF5g6H7j8K9L0M1n2p3q4R5s6T7u8V9w0XyZ",
        "cT5h8LgJ2a4V3c4yF5g6H7j8K9L0M1n2p3q4R5s6T7u8V9w0XyZ"   ],   
"recoveryKeyWIF": "cT5h8LgJ2a4V3c4yF5g6H7j8K9L0M1n2p3q4R5s6T7u8V9w0XyZ" }

(Note: this will be generated using index.ts).

Funding Transaction:
 
Funded Address: tb1qztq5rg30lv8y7kup7tftuelppcy2f9u9ygm8daq7gv4lgf0dw3ss3hj9qw   
Funding TXID: e9e764b3c63740d0eef68506970e80f819d360bdfc173d0b983f1e3d5411096d  
Funding VOUT: 1   
Funding ScriptPubKey: OP_0 12c141a22ffb0e4f5b81f2d2be67e10e08a49785223676f41e432bf425ed7461  

Any idea why my manually constructed witness would be considered non-standard?
Thank you.



Source link

Related articles

Congressman Keith Self Moves To Block US CBDC Via Defense Bill Amendment

Aave Crypto V4 Upgrade: Ethereum’s DeFi Giant Levels Up

March 25, 2026
Stablecoin Yield Off The Table In CLARITY Act’s Latest Text

Stablecoin Yield Off The Table In CLARITY Act’s Latest Text

March 25, 2026
Share76Tweet47

Related Posts

Congressman Keith Self Moves To Block US CBDC Via Defense Bill Amendment

Aave Crypto V4 Upgrade: Ethereum’s DeFi Giant Levels Up

by Moussa
March 25, 2026
0

The Aave community has officially voted to approve the deployment of Aave V4 on the Ethereum mainnet, setting in motion...

Stablecoin Yield Off The Table In CLARITY Act’s Latest Text

Stablecoin Yield Off The Table In CLARITY Act’s Latest Text

by Moussa
March 25, 2026
0

Trusted Editorial content, reviewed by leading industry experts and seasoned editors. Ad Disclosure In a closed-door meeting on Capitol Hill,...

This Level Holds Cost Basis Of 28 Billion DOGE

This Level Holds Cost Basis Of 28 Billion DOGE

by Moussa
March 25, 2026
0

Keshav is currently a senior writer at NewsBTC and has been attached to the website since June 14, 2021. Keshav...

U.S. Senator Cynthia Lummis Confirmed As A Bitcoin 2026 Speaker

U.S. Senator Cynthia Lummis Confirmed As A Bitcoin 2026 Speaker

by Moussa
March 25, 2026
0

U.S. Senator Cynthia Lummis has been officially confirmed as a speaker at Bitcoin 2026. A Republican senator from Wyoming, Lummis...

Sen. Warren Questions MrBeast on Step Acquisition Amid Teen Crypto Concerns – Crypto News Bitcoin News

Sen. Warren Questions MrBeast on Step Acquisition Amid Teen Crypto Concerns – Crypto News Bitcoin News

by Moussa
March 25, 2026
0

Step Deal Draws Senate Scrutiny Over Teen Crypto Access Sen. Elizabeth Warren is turning up the pressure on Beast Industries...

Load More

youssufi.com

sephina.com

[vc_row full_width="stretch_row" parallax="content-moving" vc_row_background="" background_repeat="no-repeat" background_position="center center" footer_scheme="dark" css=".vc_custom_1517813231908{padding-top: 60px !important;padding-bottom: 30px !important;background-color: #191818 !important;background-position: center;background-repeat: no-repeat !important;background-size: cover !important;}" footer_widget_title_color="#fcbf46" footer_button_bg="#fcb11e"][vc_column width="1/4"]

We bring you the latest in Crypto News

[/vc_column][vc_column width="1/4"][vc_wp_categories]
[/vc_column][vc_column width="1/4"][vc_wp_tagcloud taxonomy="post_tag"][/vc_column][vc_column width="1/4"]

Newsletter

[vc_raw_html]JTNDcCUzRSUzQ2RpdiUyMGNsYXNzJTNEJTIydG5wJTIwdG5wLXN1YnNjcmlwdGlvbiUyMiUzRSUwQSUzQ2Zvcm0lMjBtZXRob2QlM0QlMjJwb3N0JTIyJTIwYWN0aW9uJTNEJTIyaHR0cHMlM0ElMkYlMkZhcHByb3gub3JnJTJGJTNGbmElM0RzJTIyJTNFJTBBJTBBJTNDaW5wdXQlMjB0eXBlJTNEJTIyaGlkZGVuJTIyJTIwbmFtZSUzRCUyMm5sYW5nJTIyJTIwdmFsdWUlM0QlMjIlMjIlM0UlM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1maXJzdG5hbWUlMjIlM0UlM0NsYWJlbCUyMGZvciUzRCUyMnRucC0xJTIyJTNFRmlyc3QlMjBuYW1lJTIwb3IlMjBmdWxsJTIwbmFtZSUzQyUyRmxhYmVsJTNFJTBBJTNDaW5wdXQlMjBjbGFzcyUzRCUyMnRucC1uYW1lJTIyJTIwdHlwZSUzRCUyMnRleHQlMjIlMjBuYW1lJTNEJTIybm4lMjIlMjBpZCUzRCUyMnRucC0xJTIyJTIwdmFsdWUlM0QlMjIlMjIlM0UlM0MlMkZkaXYlM0UlMEElM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1lbWFpbCUyMiUzRSUzQ2xhYmVsJTIwZm9yJTNEJTIydG5wLTIlMjIlM0VFbWFpbCUzQyUyRmxhYmVsJTNFJTBBJTNDaW5wdXQlMjBjbGFzcyUzRCUyMnRucC1lbWFpbCUyMiUyMHR5cGUlM0QlMjJlbWFpbCUyMiUyMG5hbWUlM0QlMjJuZSUyMiUyMGlkJTNEJTIydG5wLTIlMjIlMjB2YWx1ZSUzRCUyMiUyMiUyMHJlcXVpcmVkJTNFJTNDJTJGZGl2JTNFJTBBJTNDZGl2JTIwY2xhc3MlM0QlMjJ0bnAtZmllbGQlMjB0bnAtcHJpdmFjeS1maWVsZCUyMiUzRSUzQ2xhYmVsJTNFJTNDaW5wdXQlMjB0eXBlJTNEJTIyY2hlY2tib3glMjIlMjBuYW1lJTNEJTIybnklMjIlMjByZXF1aXJlZCUyMGNsYXNzJTNEJTIydG5wLXByaXZhY3klMjIlM0UlQzIlQTBCeSUyMGNvbnRpbnVpbmclMkMlMjB5b3UlMjBhY2NlcHQlMjB0aGUlMjBwcml2YWN5JTIwcG9saWN5JTNDJTJGbGFiZWwlM0UlM0MlMkZkaXYlM0UlM0NkaXYlMjBjbGFzcyUzRCUyMnRucC1maWVsZCUyMHRucC1maWVsZC1idXR0b24lMjIlM0UlM0NpbnB1dCUyMGNsYXNzJTNEJTIydG5wLXN1Ym1pdCUyMiUyMHR5cGUlM0QlMjJzdWJtaXQlMjIlMjB2YWx1ZSUzRCUyMlN1YnNjcmliZSUyMiUyMCUzRSUwQSUzQyUyRmRpdiUzRSUwQSUzQyUyRmZvcm0lM0UlMEElM0MlMkZkaXYlM0UlM0NiciUyRiUzRSUzQyUyRnAlM0U=[/vc_raw_html][/vc_column][/vc_row]
No Result
View All Result
  • Contact Us
  • Homepages
  • Business
  • Guide

© 2024 APPROX FOUNDATION - The Crypto Currency News