Closed earthflower closed 1 year ago
Ordinals are created using commit and reveal transaction
how to get const controlBlock = ??
const createInscription = () => {
let content_type = "text/plain;charset=utf-8";
let body = Buffer.from("999");
const inscription = {
body: body,
content_type,
};
const network = bitcoin.networks.bitcoin;
const internalKey = bip32.fromSeed(rng(64), bitcoin.networks.bitcoin);
const tweakInternalPubKey = toXOnly(internalKey.publicKey);
const randKey = bip32.fromSeed(rng(64), bitcoin.networks.bitcoin);
const pubKeyChunks = bitcoin.script.compile([
tweakInternalPubKey,
bitcoin.opcodes.OP_CHECKSIG,
]);
const revealScript = appendRevealScript(inscription);
const revealScriptWithCheckSig = bitcoin.script.compile([
pubKeyChunks,
revealScript,
]);
const scriptTree = {
output: revealScriptWithCheckSig,
};
bitcoin.initEccLib(ecc);
//taproot_spend_info
const { output, witness } = bitcoin.payments.p2tr({
internalPubkey: toXOnly(internalKey.publicKey),
scriptTree,
network: network,
});
let commitTxAddress = Bitcoin.address.fromOutputScript(output, network);
const controlBlock = ??
}
//Adding ord content
export const appendRevealScript = (inscription: Inscription) => {
let instructions = [
bitcoin.opcodes.OP_FALSE,
bitcoin.opcodes.OP_IF,
PROTOCOL_ID,
];
if (inscription.content_type) {
instructions.push(CONTENT_TYPE_TAG);
instructions.push(Buffer.from(inscription.content_type));
}
if (inscription.body) {
instructions.push(BODY_TAG);
const chunks = makeChunks(Buffer.from(inscription.body), 520);
for (let chunk of chunks) {
instructions.push(Buffer.from(chunk));
}
}
instructions.push(bitcoin.opcodes.OP_ENDIF);
return bitcoin.script.compile(instructions);
};
in inscribe rs line 192, ord is using TaprootBuilder
let taproot_spend_info = TaprootBuilder::new()
.add_leaf(0, reveal_script.clone())
.expect("adding leaf should work")
.finalize(&secp256k1, public_key)
.expect("finalizing taproot builder should work");
let control_block = taproot_spend_info
.control_block(&(reveal_script.clone(), LeafVersion::TapScript))
.expect("should compute control block");
Can somebody give some pointers about getting control block?
Much appreciated!!
did you manage to handle this?
Just found the answer regarding the control block here, would love to know your learning regarding the Ordinals minting using bitcoinjs
https://bitcoin.stackexchange.com/questions/107154/what-is-the-control-block-in-taproot
Maybe you can look this url https://github.com/bitcoinjs/bitcoinjs-lib/blob/v6.1.0/ts_src/payments/p2tr.ts#LL271C23-L271C23
Hi team, facing the same issue. Is there any updated script? Thanks!
Hi @earthflower , have you managed to inscribe ordinals using bitcoinjs? I'm not having luck
Somebody who deleted the comment recommended https://github.com/supertestnet/inscriptions-online. It's not bitcoinjs but it has given me really good pointers. I'll try migrating it to use bitcoinjs. thanks!
I've finally solved creating bitcoin inscriptions using the latest bitcoinjs-lib. I've crated a repo if anybody has issues
https://github.com/fboucquez/ordinal-inscription-example-using-bitcoinjs-lib
It concerns me that the inscriptions protocol doesn't even mention minimal pushes at all... At the very least I would have hoped they strongly suggested minimal pushes, but for what it's designed for, a strict "MUST" for minimal push would have been appropriate in my opinion.
Now I guess it really just depends on the various explorers and how they implement it.
Also, if you want to add this as an integration test in our repo, it'll probably be more visible and also benefit the ability to be tested against each version of Core we use in our CI. (You should probably mention the non-minimal push issue in the integration test as well)
Hi @junderw , thank you for your comments. I'll create a PR porting the ordinal test cases here.
I've tried using minimal pushes (aka, Buffer.of([1])
= 15
hex rather 1,1
= 0101
hex)
So far, it has not been detected in any Ordinal explorer I know even when confirmed
https://www.blockchain.com/explorer/transactions/btc/2c75a32425246d0812ccbb3985795fe5c133311769ef38580f57a7d9d6a20e32 https://magiceden.io/ordinals/item-details/2c75a32425246d0812ccbb3985795fe5c133311769ef38580f57a7d9d6a20e32i0 https://ordinals.hiro.so/inscription/2c75a32425246d0812ccbb3985795fe5c133311769ef38580f57a7d9d6a20e32i0
I've also inscribed another ordinal using 0101 separator. I'm still waiting for confirmation, I'll check it out tomorrow morning. https://www.blockchain.com/explorer/transactions/btc/450088d408495c90cf63d796c9878f9e2fa2ab6d4dad96bfd51952e950960c55 https://ordinals.hiro.so/inscription/450088d408495c90cf63d796c9878f9e2fa2ab6d4dad96bfd51952e950960c55i0 https://magiceden.io/ordinals/item-details/450088d408495c90cf63d796c9878f9e2fa2ab6d4dad96bfd51952e950960c55i0
btw OP_PUSHNUM_1 is 0x51
, not 0x15
.
That's unfortunate that no one seems to support minimal push for the tags.
I wonder if they accept oversized push? In total there's 5 ways to push 0x01 on the stack and we only tested 2 ways. heh
If you're curious I'd be curious to see it too.
// Just remove the white space to figure out the bytes.
0x4c 01 01 // OP_PUSHDATA1_1 0x01
0x4d 0100 01 // OP_PUSHDATA2_1 0x01
0x4e 01000000 01 // OP_PUSHDATA4_1 0x01
Thanks. For some reason, my last mainnet execution detected the inscription but with an empty body. Checking the witness, it was corrupted.. Strange because I have created many inscriptions. I've just added another here via my e2e integration scripts
Just to confirm before running more tests, What's the script you want to try? I'm curious to try...
export function createInscriptionScript({ xOnlyPublicKey, inscription }) {
assert(xOnlyPublicKey instanceof Buffer, `xOnlyPublicKey must be a Buffer`)
assert(inscription, `inscription is required`)
assert(inscription.content instanceof Buffer, `inscription.content must be a Buffer`)
assert(inscription.contentType instanceof Buffer, `inscription.content must be a Buffer`)
const protocolId = Buffer.from(encoder.encode('ord'))
return [
xOnlyPublicKey,
bitcoinjsLib.opcodes.OP_CHECKSIG,
bitcoinjsLib.opcodes.OP_0,
bitcoinjsLib.opcodes.OP_IF,
protocolId,
1, 1, /// What goes here??
inscription.contentType,
bitcoinjsLib.opcodes.OP_0,
inscription.content,
bitcoinjsLib.opcodes.OP_ENDIF,
]
}
All 17 of these byte sequences will be read a the number 1 by Bitcoin's Script.
const possibleValuesForOne = [
[0x51],
[1, 1],
[0x4c, 1, 1],
[0x4d, 1, 0, 1],
[0x4e, 1, 0, 0, 0, 1],
[2, 1, 0],
[0x4c, 2, 1, 0],
[0x4d, 2, 0, 1, 0],
[0x4e, 2, 0, 0, 0, 1, 0],
[3, 1, 0, 0],
[0x4c, 3, 1, 0, 0],
[0x4d, 3, 0, 1, 0, 0],
[0x4e, 3, 0, 0, 0, 1, 0, 0],
[4, 1, 0, 0, 0],
[0x4c, 4, 1, 0, 0, 0],
[0x4d, 4, 0, 1, 0, 0, 0],
[0x4e, 4, 0, 0, 0, 1, 0, 0, 0],
];
ie.
export function createInscriptionScript({ xOnlyPublicKey, inscription }) {
assert(xOnlyPublicKey instanceof Buffer, `xOnlyPublicKey must be a Buffer`)
assert(inscription, `inscription is required`)
assert(inscription.content instanceof Buffer, `inscription.content must be a Buffer`)
assert(inscription.contentType instanceof Buffer, `inscription.content must be a Buffer`)
const protocolId = Buffer.from(encoder.encode('ord'))
return [
xOnlyPublicKey,
bitcoinjsLib.opcodes.OP_CHECKSIG,
bitcoinjsLib.opcodes.OP_0,
bitcoinjsLib.opcodes.OP_IF,
protocolId,
0x4e, 4, 0, 0, 0, 1, 0, 0, 0, /// What goes here??
inscription.contentType,
bitcoinjsLib.opcodes.OP_0,
inscription.content,
bitcoinjsLib.opcodes.OP_ENDIF,
]
}
(Man, looking at this brings back memories of the days when transaction malleability was a thing that we all worried about... lol)
The use of p2tr transactions has increased, because more people are using ordinals that require p2tr type of transaction.
While there are examples of creating p2tr transactions using Partially Signed Bitcoin Transactions (PSBTs), it would be helpful to have more information on how to use new bitcoin.Transaction(); for this purpose.
Can some bitcoinjs-lib patron please information on how to create p2tr transaction using new bitcoin.Transaction();