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

Ordinal Provenance #28

Closed skyrover7 closed 7 months ago

skyrover7 commented 8 months ago

@cmdruid appreciate all the work and examples in this library!

I had a question regarding ordinal provenance as documented here.

I have an inscription flow in place which generally follows the example you provided for inscriptions. While I believe i have followed the ordinal provenance documentation correctly as far as the script construction and input values, I am having issues signing the transaction.

Code snippets below, any thoughts/suggestions on how to get this working is appreciated! I am currently getting RPC error: {"code":-26,"message":"non-mandatory-script-verify-flag (Invalid Schnorr signature)"}. The ordinal I am trying to use as the parent is here: https://mempool.space/testnet/tx/e13f106578fe0955b375cfb66e4a212fd794b7168a7da5873fada2b78c47e035

image image image

cmdruid commented 8 months ago

The problem is that for sig2, you are using the tapkey to sign, however the tapkey is a tweaked public key from Tap.getPubKey, and you need the tweaked private key in order to sign.

There should also be a Tap.getSecKey which you can use to get the tweaked private key, and you should be able to use that to produce a proper sig2.

Let me know if that change fixes the issue.

The API isn't very clear in this regard, so I apologize. I'm hoping to make V2 of the library even simpler to use.

skyrover7 commented 8 months ago

@cmdruid thanks for the quick response! I just tried that but still facing the same issue. does the whole process make sense in context of the ordinal provenance docs? I think the relevant instructions are in the screenshot below. i believe i have correctly added the script tag 3, but think I am having issues with the spending the parent in input of the child.

image

So far I have

cmdruid commented 8 months ago

I'm not clear how the child tx is supposed to be formatted in order to spend the parent.

Do you have a link to a pair of example transactions that perform a successful child inscription? That would help clarify how this should be formatted.

skyrover7 commented 8 months ago

here is a child

parent

cmdruid commented 8 months ago

Looking at the transactions that you linked, the example inscriptions do not seem to be following the documentation.

In any case, the second input doesn't seem to be anything important to the spec, it looks like just an input being used for fees and change. So that input should just be a simple P2TR key-spend of the selected utxo being used for fees.

skyrover7 commented 8 months ago

thanks @cmdruid

image

cmdruid commented 8 months ago
  • Is the second input not the Spend the parent P in one of the inputs of T. part of the spec? Can you elaborate on So that input should just be a simple P2TR key-spend of the selected utxo being used for fees

From my understanding, only one input is handing the inscriptions stuff, so it is both spending the parent and minting the child. All the inscription related stuff should be in that tx input.

Any additional inputs are merely adding funds to the tx, and are not relevant to the inscription protocol. You can use any utxo for that, it doesn't even need to be P2TR actually.

rohitkeshav27 commented 8 months ago

@skyrover7 Did you find a way inscribing the child inscription using Parent?

Even I was trying do the same thing , seeing your code I think I have a suggestion

the var=endian you are using happens to be a wrong value (i guess)

//Pass the inscription id to the below function
function convertHexString(hexString) {
  // Reverse the hexadecimal string
  const reversedHexString = hexString
    .match(/.{2}/g) // Split string into pairs
    .reverse() // Reverse the order
    .join("");

  // Convert reversed hex string to a byte array
  const byteArray = [];
  for (let i = 0; i < reversedHexString.length; i += 2) {
    byteArray.push(parseInt(reversedHexString.substr(i, 2), 16));
  }

  // Convert byte array to hexadecimal string with '0x' prefix
  const formattedHex = "0x" + Buffer.from(byteArray).toString("hex");

  return formattedHex;
}

Try using the above helper function to convert and let me know , if it worked

Coz I need your help after this !!

skyrover7 commented 8 months ago

@rohitkeshav27 nope, still no luck

i believe the endian value is correct. I am using the below function and am able to make an inscription with the delegate ID. the delegate ID and parent ID need to be serialized the same way. I have confirmed that the below code is creating the correct endian value and is recognised as a valid delegate ID. Here is an inscription with valid delegate ID using the below code for ID conversion https://ordinals.com/inscription/20bd89f9f9b29314f7995286c18a80386d245efc1f03aa76e07feb81bf1748a8i0

my trouble is still on signing the transaction, hoping @cmdruid can shine some light 🙏🏾

export function convertInscriptionId(inscriptionId) {
    // Extract the TXID from the inscription ID
    const txid = inscriptionId.slice(0, 64);

    // Extract the INDEX value following the 'i' after the TXID
    const indexPart = inscriptionId.slice(65); // Assuming the index always follows 'i' after the TXID
    const index = parseInt(indexPart, 10);

    // Reverse the bytes of the TXID
    const reversedTxid = txid.match(/.{2}/g).reverse().join('');

    // Convert the INDEX to a 4-byte little-endian format
    const littleEndianIndexBuffer = Buffer.alloc(4);
    littleEndianIndexBuffer.writeUInt32LE(index);

    // Concatenate and return the result
    let result = reversedTxid + littleEndianIndexBuffer.toString('hex');

    // Omit trailing zeros
    result = result.replace(/0+$/, '');

    return result;
}
cmdruid commented 8 months ago

Do you have updated code for signing the transaction?

Your previous example was using the tapkey to sign the second input, which was incorrect. It should be the secret key that signs for that second utxo.

rohitkeshav27 commented 8 months ago

@skyrover7
I had a doubt in your code you are spending the parent inscription in input But you are not creating an appropriate output , does this mean your parent inscription is spent ( lost)

and 2nd input is a taproot address , so the witness passed also shd be like the first input There is something missing !!

rohitkeshav the above is my discord username - we could connect and work this together ( coz even I have an urgent need to complete this )

skyrover7 commented 8 months ago

@rohitkeshav27 sent you a fr on discord

cmdruid commented 7 months ago

I am closing this for now. Feel free to reopen this issue if you still need help.