bitcoinjs / bitcoinjs-lib

A javascript Bitcoin library for node.js and browsers.
MIT License
5.6k stars 2.08k forks source link

MANDATORY-SCRIPT-VERIFY-FLAG-FAILED #1632

Closed sinanouri closed 3 years ago

sinanouri commented 3 years ago

I am trying to spend segwit utxo from an address but i get MANDATORY-SCRIPT-VERIFY-FLAG-FAILED error while trying to broadcast. here is my code:

const bitcoin = require ( 'bitcoinjs-lib' )
let network = bitcoin.networks.testnet
let key = bitcoin.ECPair.fromWIF ( 'cSZXwWwhJPM9kQjH2qMe29TtQWw98NTaH5L9objd6QFCADna8WVP' , network )
let { address } = bitcoin.payments.p2pkh ( { pubkey : key.publicKey , network : network } ) //mhx8a8NAn7jXjTvwGyYEAZ5GDiRGeskF38
let to_address = 'mgnJs1tjM6iG4UGobuGm2T4mpAvNwN1NP1'
const p2sh = bitcoin.payments.p2sh ( {
redeem : bitcoin.payments.p2wpkh ( {
pubkey : key.publicKey ,
network
} ) , network
 } )
let scriptPubKey = p2sh.output
let redeemscript = p2sh.redeem.output
let utxo = {
    block_id : 1861426 ,
    transaction_hash : '403c77c76f66963bb4ce09179a4cd63d4892ecff5e2ba48bc7ce48b2ed347fd2' ,
    index : 0 ,
    value : 2000 ,
    address : 'mhx8a8NAn7jXjTvwGyYEAZ5GDiRGeskF38' ,
    raw_tx : '020000000001011fb516b60a44eb884e5146520d17845fa8ac9c53c62a3bd2194147c7a1ce065a0000000000feffffff02d0070000000000001976a9141ab33ac298aab1a41a080cd809ddcaa463a99c6c88ac3c52cd0000000000160014d1e8ecae9f6bc19922251b88a32d11399319e09902473044022035c535ae1c35eebf790ffeb8b21c95b14034c1036ee199b45102c553e0bbd229022036b57398af44461344b866b1f9357479e90bcea3273559d7420a2e6ed99e09d30121026e35fe3ac4f330d2505cc9cff7553afc5011b0ad5790cb57b45456fd3530ba6331671c00'
}
let isSegwit = utxo.raw_tx.substring ( 8 , 12 ) === '0001'
let psbt = new bitcoin.Psbt ( { network : network } )
if ( isSegwit ) {
    psbt.addInput ( {
    hash : utxo.transaction_hash ,
    index : utxo.index ,
    witnessUtxo : { 
        script : scriptPubKey ,
        value : utxo.value // value in satoshi
    } ,
    redeemScript : redeemscript ,
    } )
}
else {
    psbt.addInput ( {
hash : utxo.transaction_hash ,
index : utxo.index ,
nonWitnessUtxo : Buffer.from ( utxo.raw_tx , 'hex' ) ,
redeemScript : redeemscript
} )
}
psbt.addOutput ( {
address : to_address ,
value : 1800
 } )
psbt.signInput ( 0 , key )
if ( psbt.validateSignaturesOfAllInputs () ) {
    psbt.finalizeAllInputs ()
    let transaction = psbt.extractTransaction ()
    let signedTransaction = transaction.toHex ()
    console.log ( signedTransaction )
}
else {
    console.log ( 'is not valid' )
}

when i am checking with psbt.validateSignaturesOfAllInputs () it returns true and the final signed transaction is:

02000000000101d27f34edb248cec78ba42b5effec92483dd64c9a1709ceb43b96666fc7773c4000000000171600141ab33ac298aab1a41a080cd809ddcaa463a99c6cffffffff0108070000000000001976a9140ddf88e6f1c54d83596ba4ffa362a0ec2473077988ac0248304502210086168d871aaa548843c75cdc9220dca1857520fc2d99d8db48d170f5558983bb0220505cb32ac4a1ff3ccb757ffa1271f9dbe10d3ce2097e2fa77454f5b2e65e14450121031327d6d2948bcbfd952bf06f095379d2328832575284fb957b5ab288a7f2965a00000000

when i decode it using https://testnet.smartbit.com.au/txs/decodetx i get:

{
    "Version": "2",
    "LockTime": "0",
    "Vin": [
        {
            "TxId": "403c77c76f66963bb4ce09179a4cd63d4892ecff5e2ba48bc7ce48b2ed347fd2",
            "Vout": "0",
            "ScriptSig": {
                "Asm": "00141ab33ac298aab1a41a080cd809ddcaa463a99c6c",
                "Hex": "1600141ab33ac298aab1a41a080cd809ddcaa463a99c6c"
            },
            "CoinBase": null,
            "TxInWitness": [
                "304502210086168d871aaa548843c75cdc9220dca1857520fc2d99d8db48d170f5558983bb0220505cb32ac4a1ff3ccb757ffa1271f9dbe10d3ce2097e2fa77454f5b2e65e144501",
                "031327d6d2948bcbfd952bf06f095379d2328832575284fb957b5ab288a7f2965a"
            ],
            "Sequence": "4294967295"
        }
    ],
    "Vout": [
        {
            "Value": 0.000018,
            "N": 0,
            "ScriptPubKey": {
                "Asm": "OP_DUP OP_HASH160 0ddf88e6f1c54d83596ba4ffa362a0ec24730779 OP_EQUALVERIFY OP_CHECKSIG",
                "Hex": "76a9140ddf88e6f1c54d83596ba4ffa362a0ec2473077988ac",
                "ReqSigs": 1,
                "Type": "pubkeyhash",
                "Addresses": [
                    "mgnJs1tjM6iG4UGobuGm2T4mpAvNwN1NP1"
                ]
            }
        }
    ],
    "TxId": "7c37f8d5a4a31f936a5975574eb8dbd9ab47eafbda0ef1fbae8a75070cbc4378"
}

but at the last step when trying to broadcast i get this error:

PUSH TRANSACTION ERROR: 16: MANDATORY-SCRIPT-VERIFY-FLAG-FAILED (SCRIPT FAILED AN OP_EQUALVERIFY OPERATION)

i could not find out which part i am doing wrong, would you please help me figure out the problem?

junderw commented 3 years ago

isSegwit logic is flawed. It contains "is the parent transaction a segwit transaction? (aka. does it have witnesses in the inputs)" but this has nothing to do "Is the OUTPUT I am using in this input a SEGWIT SCRIPT?"

mhx8a8NAn7jXjTvwGyYEAZ5GDiRGeskF38 is not an address for segwit, nor is it p2sh or p2wsh...

So therefore, to spend it you must use P2PKH and not P2SH-P2WPKH.

validateSignaturesOfAllInputs passed with true because you essentially gave the Psbt false information; you said witnessUtxo.script was the p2sh output. This is not true. Looking at the blockchain, the script is a p2pkh output. Since our library is not a full node, we have no way to tell if the data you input is true.