cmdruid / tapscript

A humble library for working with Tapscript and Bitcoin Transactions.
https://www.npmjs.com/package/@cmdcode/tapscript
Creative Commons Zero v1.0 Universal
188 stars 49 forks source link

{"code":-26,"message":"non-mandatory-script-verify-flag (Witness program hash mismatch)"} #24

Closed HFFP closed 9 months ago

HFFP commented 9 months ago

when i push tx i got this error...

here is my code

async function deploy(
    secret: string,
    brc20: string,
    totalSupply: number,
    mintLimit: number,
    input: {txId: string; index: number; amount: number},
    network: Networks,
) {
    const text = `{"p":"brc-20","op":"deploy","tick":"${brc20}","max":"${totalSupply}","lim":"${mintLimit}"}`
    const inscription = createTextInscription(text)

    const seckey = keys.get_seckey(secret)
    const pubkey = keys.get_pubkey(secret, true)
    const tweakKey = Tap.tweak.getPubKey(pubkey)

    const script = [
        tweakKey,
        "OP_CHECKSIG",
        "OP_0",
        "OP_IF",
        Buffer.from(encoder.encode("ord")),
        "01",
        inscription.contentType,
        "OP_0",
        inscription.content,
        "OP_ENDIF",
    ]
    const tapleaf = Tap.encodeScript(script)
    const [tpubkey, cblock] = Tap.getPubKey(tweakKey, {target: tapleaf})
    const address = Address.p2tr.fromPubKey(tweakKey, network)
    // const address = Address.p2tr.fromPubKey(tpubkey, network)
    console.log(address, "address")
    const txdata = Tx.create({
        vin: [
            {
                // Use the txid of the funding transaction used to send the sats.
                txid: input.txId,
                // Specify the index value of the output that you are going to spend from.
                vout: input.index,
                // Also include the value and script of that ouput.
                prevout: {
                    // Feel free to change this if you sent a different amount.
                    value: input.amount,
                    // This is what our address looks like in script form.
                    scriptPubKey: ["OP_1", tpubkey],
                },
            },
        ],
        vout: [
            {
                // We are leaving behind 1000 sats as a fee to the miners.
                value: 1000,
                // This is the new script that we are locking our funds to.
                scriptPubKey: Address.toScriptPubKey("tb1q7gnys2cwhkm7r73px6nus0g9dcr8mjh6fe2ums"),
            },
            {
                value: input.amount - 5000,
                scriptPubKey: Address.toScriptPubKey(address),
            },
        ],
    })
    const sig = Signer.taproot.sign(seckey, txdata, 0, {extension: tapleaf})
    txdata.vin[0].witness = [sig, script, cblock]
    const isValid = Signer.taproot.verify(txdata, 0, {pubkey, throws: true})
    console.log("Your txhex:", Tx.encode(txdata).hex, isValid)
    // console.dir(txdata, {depth: null})
    await boardCast(Tx.encode(txdata).hex)
}

Did I get something wrong? Thanks!

cmdruid commented 9 months ago

I think you have the wrong idea with what you are doing with const tweakKey = Tap.tweak.getPubKey(pubkey) .

For Tap.getPubKey you should be using the internal pubkey, and for the address you should be using the tpubkey. For the pubkey in the script itself, it can be any keypair that you want, but it can be convenient to reuse the internal pubkey for that as well.

The internal pubkey is what gets tweaked by the taproot, creating the tpubkey, which you then encode into an address. I hope that helps.

HuangCaiJin commented 9 months ago

![Uploading 1.png…]()

HuangCaiJin commented 9 months ago

Maybe it's because taproot hash deletion

HFFP commented 9 months ago

i fix it. see

chirag9899 commented 9 months ago

hey am also facing same witness mismatch problem ` // Here is my code

const inscriptions = async () => { const marker = Buff.encode('ord') const mimetype = Buff.encode('image/png') const imgdata = Buff.from('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/Pv8hOAAAAABJRU5ErkJggg==', 'base64')

// const pubKey = "02f8a93684235245259faf189eb6b5787b03dbe8711a1262409cfcfd0ee015a483";
const pvt = "06e257ee24ce8ee772d78568da1e0c281b5b816c90fa77d.........";
const pvtKey = keys.get_seckey(pvt)
const pubkey = keys.get_pubkey(pvt,true);

// Basic format of an 'inscription' script.
const script = [pubkey.hex, 'OP_CHECKSIG', 'OP_0', 'OP_IF', marker, '01', mimetype, 'OP_0', imgdata, 'OP_ENDIF']
// const tapleaf = Tap.encodeScript(script)
const tapleaf = Tap.tree.getLeaf(Script.encode(script));
const [tpubkey, cblock] = Tap.getPubKey(pubkey, { target: tapleaf });
const address = Address.p2tr.fromPubKey(tpubkey, 'regtest')

console.log('Inscription address: ', address);
console.log('Tapkey:', tpubkey);

try {
  const txdata = Tx.create({
    vin: [{
      // Use the txid of the funding transaction used to send the sats.
      txid: "c404bc4ba89e9423ff772cb45268ba6fba8b713f809484c1216f1a657aafa088",
      // Specify the index value of the output that you are going to spend from.
      vout: 1,
      // Also include the value and script of that ouput.
      prevout: {
        // Feel free to change this if you sent a different amount.
        value: 1973787,
        // This is what our address looks like in script form.
        scriptPubKey: ['OP_1', tpubkey]
      },
    }],
    vout: [{
      // We are leaving behind 1000 sats as a fee to the miners.
      value: 500,
      // This is the new script that we are locking our funds to. sent
      scriptPubKey: Address.toScriptPubKey('tb1q7gnys2cwhkm7r73px6nus0g9dcr8mjh6fe2ums')
      // scriptPubKey: [ 'OP_1', tpubkey ]
    }]
  })

  // let sig = await window.unisat.signMessage(pvtKey, txdata, 0, { extension: tapleaf });
  const sig = Signer.taproot.sign(pvtKey, txdata, 0, { extension: tapleaf })
  console.log("sig",sig)

  txdata.vin[0].witness = [sig, script, cblock]
  console.log(txdata.vin[0].witness)
  console.log(script,cblock)

  // const isValid = await Signer.taproot.verify(txdata, 0, { pubkey, throws: true })
  console.log("txdata", txdata)

  // encode
  console.log('Your txhex:', Tx.encode(txdata).hex)
  const isValid = Signer.taproot.verify(txdata, 0, { pubkey, throws: true })

  console.log("valid",isValid)

  // console.dir(txdata, { depth: null })
} catch (error) {
  console.log("error", error)
}

}

`

cmdruid commented 8 months ago

A witness hash mismatch problem is usually because there is something wrong with the encoding of the script when you first encode it as a tapleaf.

Using Tap.encodeScript(script) should make sure that the script is encoded properly, so that when the script is verified in the witness, the encoding during verification is the same as the encoding when you first create the tapleaf.

Let me know if that helps.