Closed UIZorrot closed 6 months ago
hashForSignature
is for pre-segwit sighashes. Please use segwit v1 (not v0)
thank you,but may i ask how can I using v1, from which function?
Zorrot Chen | |
---|---|
@. | ---- Replied Message ---- | From | Jonathan @.> | | Date | 04/03/2024 01:24 | | To | bitcoinjs/bitcoinjs-lib @.> | | Cc | Zorrot @.>, Author @.***> | | Subject | Re: [bitcoinjs/bitcoinjs-lib] A problem in trying scriptless transcation (Issue #2066) |
hashForSignature is for pre-segwit sighashes. Please use segwit v1 (not v0)
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
Use the hashForWitnessV1
method instead. As taproot commits to all the outputs of the previous transaction, you will need to get an array of all scripts from all outputs of the previous transaction as well as an array of all the values of all the outputs too.
Thanks!
Zorrot Chen | |
---|---|
@. | ---- Replied Message ---- | From | Jonathan @.> | | Date | 04/03/2024 08:42 | | To | bitcoinjs/bitcoinjs-lib @.> | | Cc | Zorrot @.>, Author @.***> | | Subject | Re: [bitcoinjs/bitcoinjs-lib] A problem in trying scriptless transcation (Issue #2066) |
Use the hashForWitnessV1 method instead. As taproot commits to all the outputs of the previous transaction, you will need to get an array of all scripts from all outputs of the previous transaction as well as an array of all the values of all the outputs too.
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
I'm so sorry, that I may need to ask here again (sincerely, I just don't know anywhere else to ask), the code is still output same error Invaild schnorr sigature
. And I have changed the segwit to V1. Here is the alternative code:
let wallets = get_agg_keypair(5)
let options = get_option(wallets)
let pub = get_agg_pub(wallets, options)
console.log('Testing schnorr tx.')
// Generate an address from the tweaked public key
const p2pktr = payments.p2tr({
internalPubkey: Buffer.from(pub),
network
});
const p2pktr_addr = p2pktr.address ?? "";
console.log(`Waiting till UTXO is detected at this Address: ${p2pktr_addr}`)
// push trans but not confirm
let temp_trans = await pushTrans(p2pktr_addr)
console.log("the new txid is:", temp_trans)
// get UTXO
const utxos = await getUTXOfromTx(temp_trans, p2pktr_addr)
console.log(`Using UTXO ${utxos.txid}:${utxos.vout}`);
const psbt = new Psbt({ network });
psbt.addInput({
hash: utxos.txid,
index: utxos.vout,
witnessUtxo: { value: utxos.value, script: p2pktr.output! },
tapInternalKey: Buffer.from(pub),
});
// utxos.value
psbt.addOutput({
address: "bcrt1q5hk8re6mar775fxnwwfwse4ql9vtpn6x558g0w", // main wallet address
value: utxos.value - 150
});
let transaction = new Transaction;
transaction.addInput(Buffer.from(utxos.txid, 'hex').reverse(), utxos.vout)
transaction.addOutput(p2pktr.output!, utxos.value - 150)
let signatureHash = transaction.hashForWitnessV1(0, [p2pktr.output!], [utxos.value - 150], Transaction.SIGHASH_ALL);
let msg = signatureHash
let sign = get_agg_sign(wallets, options, Buff.from(msg));
let tapKeySig = Buffer.from(sign)
psbt.updateInput(0, { tapKeySig })
console.log(psbt.data.inputs)
psbt.finalizeAllInputs();
console.log(psbt.data.inputs)
// Here is perfectly passed, when using a third-party schnorr verification
// const isValid2 = schnorr.verify(Buffer.from(sign), Buffer.from(msg), Buffer.from(pub))
// if (isValid2) { console.log('The signature should validate using another library.') }
const tx = psbt.extractTransaction();
console.log(`Broadcasting Transaction Hex: ${tx.toHex()}`);
console.log("Txid is:", tx.getId());
// Borad cast will failed
const txHex = await broadcast(tx.toHex());
console.log(`Success! TxHex is ${txHex}`);
// generate new block to lookup
await pushBlock(p2pktr_addr)
So according to your code, the full transaction with the txid of utxos.txid
contains only 1 output.
That output's script is equal to p2pktr.output!
and the value of that same output is equal to utxos.value - 150
.
This doesn't make sense, because your input (which points to the transaction at utxos.txid
) says { value: utxos.value, script: p2pktr.output! }
which contradicts what your hashForWitnessV1
call is saying.
You need:
of the transaction with the id utxos.txid
I'll trying, thank you again!
Hi, sorry to bored you again, It will be the last time I come here to ask, in case its heavily disturbing you I think I have done everything right, but it still not work. By the way, It passed two different schnorr verification, so I just can't figure out where is the problem
async function start_musig_txbuilder() {
let wallets = get_agg_keypair(5);
let options = get_option(wallets);
let pub = get_agg_pub(wallets, options);
console.log('Testing schnorr tx.');
// Generate an address from the tweaked public key
const p2pktr = payments.p2tr({
pubkey: Buffer.from(pub),
network
});
const p2pktr_addr = p2pktr.address ?? "";
console.log(`Waiting till UTXO is detected at this Address: ${p2pktr_addr}`);
// Push transaction but not confirm
let temp_trans = await pushTrans(p2pktr_addr);
console.log("the new txid is:", temp_trans);
// Get UTXO
const utxos = await getUTXOfromTx(temp_trans, p2pktr_addr);
console.log(`Using UTXO ${utxos.txid}:${utxos.vout}`);
// Building a new transaction
let transaction = new Transaction(); // Assuming you have defined network
transaction.addInput(Buffer.from(utxos.txid, 'hex').reverse(), utxos.vout);
const scriptPubKey = bitcoin.address.toOutputScript("bcrt1q5hk8re6mar775fxnwwfwse4ql9vtpn6x558g0w", network);
transaction.addOutput(scriptPubKey, utxos.value - 200);
const pubKey = Buffer.from(pub);
const prevOutScript = bitcoin.script.compile([
bitcoin.opcodes.OP_1,
pubKey,
]);
let signatureHash = transaction.hashForWitnessV1(0, [prevOutScript], [utxos.value], Transaction.SIGHASH_ALL);
let sign: Buff = get_agg_sign(wallets, options, signatureHash);
let tapKeySig = Buffer.from(sign); // Ensure the signature is in the correct format
transaction.ins[0].witness = [tapKeySig];
// Check if the signature is valid.
const isValid2 = schnorr.verify(sign, signatureHash, pub)
if (isValid2) { console.log('The signature should validate using another library.') }
// Both of this two passed.
const isValid1 = tinysecp.verifySchnorr(signatureHash, pub, sign);
if (isValid1) { console.log('The test demo should produce a valid signature.') }
transaction.version = 1
console.log(transaction)
// Broadcasting the transaction
const txHex = transaction.toHex();
console.log(`Broadcasting Transaction Hex: ${txHex}`);
const broadcastResult = await broadcastraw(txHex);
console.log(`Success! Broadcast result: ${broadcastResult}`);
// Generate new block to confirm
await pushBlock(p2pktr_addr);
}
It gets:
error: {
code: -26,
message: 'mandatory-script-verify-flag-failed (Invalid Schnorr signature)'
},
As for how I make musig and aggr key, I was using https://github.com/cmdruid/musig2
utxos.txid
ONLY has one output. It has NO OTHER OUTPUTS? Like no change outputs AT ALL?signatureHash
so you must remove transaction.version = 1
(although the default is 1, so this should not matter)SIGHASH_DEFAULT
instead of SIGHASH_ALL
and make sure that your schnorr signature is 64 bytes.Please read the related BIP (341) to learn about what SIGHASH_DEFAULT is and how it affects the shape of the signature Buffer.
Are you absolutely sure that the transaction at utxos.txid ONLY has one output. It has NO OTHER OUTPUTS? Like no change outputs AT ALL?
There is two uxto from the pervious tx
however, If I include all two uxto in the prevOutScript
and Value
like:
let prevOutScript: any[] = []
let prevValue: any[] = []
for (var i = 0; i < all_utxos.length; i++) {
prevOutScript.push(bitcoin.address.toOutputScript(all_utxos[i].address, network));
prevValue.push(all_utxos[i].value)
}
// const prevOutScript = ;
// const prevOutScript2 = bitcoin.address.toOutputScript(p2pktr_addr, network);
let signatureHash = transaction.hashForWitnessV1(0, prevOutScript, prevValue, Transaction.SIGHASH_DEFAULT);
It will return an error, named Error: Must supply prevout script and value for all inputs
I think it should only need one of the UTXO, cause the other change address is back to the faucet itself, like
faucet ---> tapaddress -- my new tx is here --> faucet ············· ---> change it back
and I check it, the sign is 64 bytes
You should use SIGHASH_DEFAULT instead of SIGHASH_ALL and make sure that your schnorr signature is 64 bytes.
I tried both, none of them are working
You can not change the transaction version AFTER getting the signatureHash so you must remove transaction.version = 1 (although the default is 1, so this should not matter)
Yeah, I deleted, it doesn't work
Hi, I success, and I found this problem is really tricky, it maybe a good lesson for other guys.
It was because
// Wrong
// Generate an address from the tweaked public key
const p2pktr = payments.p2tr({
pubkey: Buffer.from(pub),
network
});
// Right
// Generate an address from the tweaked public key
const p2pktr = payments.p2tr({
pubkey: Buffer.from(pub, 'hex'),
network
});
Yeah, there's no way I could have known that because you had so many black box functions...
Glad you figured it out.
It will return an error, named Error: Must supply prevout script and value for all inputs
I was mistaken. It isn't an array of all outputs of utxos.txid, but it is the outputs of the utxos that every input of THIS transaction points to. So if THIS transaction only has 1 input you only have 1 item, if this tx has 5 inputs, then every call of hashForWitnessV1
(regardless of the index) must have the same two arrays with 5 items each.
Hi, I'm trying to using a single aggr pubkey as the pubkey of the p2tr, therefore I expected to using only one signature to unlock the
psbt
, and in this case, I want to signinput[0]
.The function
get_agg_*
is from musig2 and passed test case, so it should working fine. Theget_agg_sign
should sign amsg
in schnorr manner.However, this function does not work, it reported
mandatory-script-verify-flag-failed (Invalid Schnorr signature)
at the last of the function, So I think I may make some mistakes.I think the problem is coming from the
msg
that I should sign, the code snippet is here:My question is, Have I making mistake in
let msg = signatureHash
? Or I making mistakes somewhere else? Or It's impossible at the first place?Below is all of the code: