bitcoinjs-lib
bitcoinjs-lib copied to clipboard
Does bitcoinjs lib has instruments for creating MuSig key-path spend wallets with n-n scheme?
Could someone help me please. I want to create a taproot MuSig wallet with an n-n scheme and make a payment from this wallet. And I have a few questions:
- I didn't find a function to combine pubkeys. Does it exist or not in lib?
- I want to extract an unsigned transaction hash for signing because my public keys will be stored in different places and I need to send a hash to all of them and then combine signatures into one and set it in the transaction's input witness. Do you know how I can do this?
Thanks a lot for a response
I would also like to know about this.
Found it finnaly
To extract your signatures :
console.log(txb.data.inputs[0].partialSig[0].pubkey.toString('hex')) console.log(txb.data.inputs[0].partialSig[0].signature.toString('hex'))
To import signatures:
txb.data.inputs[0].partialSig.push({ pubkey: Buffer.from('0305cc4dceb1d8f8ef19f084cfbbc01fc60a91410c4d95617466183b098b781993', 'hex'), signature: Buffer.from('304402207dad5ee98ff738d627d17dd0b4021d45f370caca141a7cd71aacff429891c17d022009c276d1db69e920f6c4857f04cc203bb53f5488f1e121b6baa32b3f8498ead001', 'hex'), });
To extract the Transaction:
txb.toHex()
To import the Transaction:
const txb = bitcoin.Psbt.fromHex(<TXHex>);
In a MuSig wallet, the public keys need to be aggregated before generating the combined public key. The specific functions for combining public keys may depend on the cryptographic library or framework you are using.
Assuming you are using a library like BitcoinJS, you would typically perform the following steps:
javascript Copy code const pubkeys = [pubkey1, pubkey2, pubkey3]; // Replace with your actual public keys
// Combine public keys const combinedPubkey = bitcoin.payments.p2tr({pubkeys}).output;
// Use combinedPubkey in your transaction Always refer to the documentation of the library you are using for the exact method to combine public keys.
Found it finnaly
To extract your signatures :
console.log(txb.data.inputs[0].partialSig[0].pubkey.toString('hex')) console.log(txb.data.inputs[0].partialSig[0].signature.toString('hex'))To import signatures:
txb.data.inputs[0].partialSig.push({ pubkey: Buffer.from('0305cc4dceb1d8f8ef19f084cfbbc01fc60a91410c4d95617466183b098b781993', 'hex'), signature: Buffer.from('304402207dad5ee98ff738d627d17dd0b4021d45f370caca141a7cd71aacff429891c17d022009c276d1db69e920f6c4857f04cc203bb53f5488f1e121b6baa32b3f8498ead001', 'hex'), });To extract the Transaction:
txb.toHex()To import the Transaction:
const txb = bitcoin.Psbt.fromHex(<TXHex>);
Thanks for the response, I will check this solution. Have you found a way to properly sign the transaction?
For now, in your solution, I found two questions:
- How did you create your aggregated pub key? Did you use a specific tweak?
- How did you sign the tx data and create an aggregated signature? Did you use nonce for signature? NOTE: Did you use only bitcoinjs instruments or not?
In a MuSig wallet, the public keys need to be aggregated before generating the combined public key. The specific functions for combining public keys may depend on the cryptographic library or framework you are using.
Assuming you are using a library like BitcoinJS, you would typically perform the following steps:
javascript Copy code const pubkeys = [pubkey1, pubkey2, pubkey3]; // Replace with your actual public keys
// Combine public keys const combinedPubkey = bitcoin.payments.p2tr({pubkeys}).output;
// Use combinedPubkey in your transaction Always refer to the documentation of the library you are using for the exact method to combine public keys.
Thanks for the response, do you know the way how can I create an aggregated signature for MuSig wallet using bitcoinjs lib?
In a MuSig wallet, the public keys need to be aggregated before generating the combined public key. The specific functions for combining public keys may depend on the cryptographic library or framework you are using. Assuming you are using a library like BitcoinJS, you would typically perform the following steps: javascript Copy code const pubkeys = [pubkey1, pubkey2, pubkey3]; // Replace with your actual public keys // Combine public keys const combinedPubkey = bitcoin.payments.p2tr({pubkeys}).output; // Use combinedPubkey in your transaction Always refer to the documentation of the library you are using for the exact method to combine public keys.
Thanks for the response, do you know the way how can I create an aggregated signature for MuSig wallet using bitcoinjs lib?
Just txb.finalizeAllInputs(); after you added all the signatures
- How did you create your aggregated pub key? Did you use a specific tweak?
To generate the address controlled by the multisig you can
const p2shAddress = bitcoin.payments.p2wsh({
redeem: bitcoin.payments.p2ms({ m: config.m , pubkeys:[ <Publickey list>] ,
network: bitcoin.networks[config.Bitcoin.network], }),
network: bitcoin.networks[config.Bitcoin.network],
});
return p2shAddress.address;
You create the tx object using :
const txb = new bitcoin.Psbt({network : bitcoin.networks[config.Bitcoin.network] });
and consume inputs from the multisig address like this :
txb.addInput({
hash: addressUtxos[i].txid,
index: addressUtxos[i].vout,
witnessUtxo: {
script: Buffer.from(addressUtxos[i].scriptPubKey, 'hex'),
value: Math.round(addressUtxos[i].amount * 100_000_000),
},
witnessScript: redeemScript,
});
}
sign all the inputs with a single private key :
txb.signAllInputs(this.watcherKey);
And then you finalize and get the completed hex string:
txb.finalizeAllInputs();
const tx = txb.extractTransaction();
const txHex = tx.toHex();
If you make progress on this I really want to know if there is a way to generate multiple address with the same multisig using BitcoinJS (working for a Typescript project that needs it atm)
In a MuSig wallet, the public keys need to be aggregated before generating the combined public key. The specific functions for combining public keys may depend on the cryptographic library or framework you are using. Assuming you are using a library like BitcoinJS, you would typically perform the following steps: javascript Copy code const pubkeys = [pubkey1, pubkey2, pubkey3]; // Replace with your actual public keys // Combine public keys const combinedPubkey = bitcoin.payments.p2tr({pubkeys}).output; // Use combinedPubkey in your transaction Always refer to the documentation of the library you are using for the exact method to combine public keys.
Thanks for the response, do you know the way how can I create an aggregated signature for MuSig wallet using bitcoinjs lib?
Just txb.finalizeAllInputs(); after you added all the signatures
- How did you create your aggregated pub key? Did you use a specific tweak?
To generate the address controlled by the multisig you can
const p2shAddress = bitcoin.payments.p2wsh({ redeem: bitcoin.payments.p2ms({ m: config.m , pubkeys:[ <Publickey list>] , network: bitcoin.networks[config.Bitcoin.network], }), network: bitcoin.networks[config.Bitcoin.network], }); return p2shAddress.address;You create the tx object using :
const txb = new bitcoin.Psbt({network : bitcoin.networks[config.Bitcoin.network] });and consume inputs from the multisig address like this :
txb.addInput({ hash: addressUtxos[i].txid, index: addressUtxos[i].vout, witnessUtxo: { script: Buffer.from(addressUtxos[i].scriptPubKey, 'hex'), value: Math.round(addressUtxos[i].amount * 100_000_000), }, witnessScript: redeemScript, }); }sign all the inputs with a single private key :
txb.signAllInputs(this.watcherKey);And then you finalize and get the completed hex string:
txb.finalizeAllInputs(); const tx = txb.extractTransaction(); const txHex = tx.toHex();If you make progress on this I really want to know if there is a way to generate multiple address with the same multisig using BitcoinJS (working for a Typescript project that needs it atm)
Thanks for the detailed response, but how did you compute this.watcherKey? About your question, unfortenly I didn't make progress with it, because I changed direction for some time, but If you want to create different MuSig wallets using the same public keys, you should use tweak operation when you create your wallet and then when you create an aggregated signature, but I don't know how to implement it using bitcoins lib.
In a MuSig wallet, the public keys need to be aggregated before generating the combined public key. The specific functions for combining public keys may depend on the cryptographic library or framework you are using. Assuming you are using a library like BitcoinJS, you would typically perform the following steps: javascript Copy code const pubkeys = [pubkey1, pubkey2, pubkey3]; // Replace with your actual public keys // Combine public keys const combinedPubkey = bitcoin.payments.p2tr({pubkeys}).output; // Use combinedPubkey in your transaction Always refer to the documentation of the library you are using for the exact method to combine public keys.
Thanks for the response, do you know the way how can I create an aggregated signature for MuSig wallet using bitcoinjs lib?
Just txb.finalizeAllInputs(); after you added all the signatures
- How did you create your aggregated pub key? Did you use a specific tweak?
To generate the address controlled by the multisig you can
const p2shAddress = bitcoin.payments.p2wsh({ redeem: bitcoin.payments.p2ms({ m: config.m , pubkeys:[ <Publickey list>] , network: bitcoin.networks[config.Bitcoin.network], }), network: bitcoin.networks[config.Bitcoin.network], }); return p2shAddress.address;You create the tx object using :
const txb = new bitcoin.Psbt({network : bitcoin.networks[config.Bitcoin.network] });and consume inputs from the multisig address like this :txb.addInput({ hash: addressUtxos[i].txid, index: addressUtxos[i].vout, witnessUtxo: { script: Buffer.from(addressUtxos[i].scriptPubKey, 'hex'), value: Math.round(addressUtxos[i].amount * 100_000_000), }, witnessScript: redeemScript, }); }sign all the inputs with a single private key :
txb.signAllInputs(this.watcherKey);And then you finalize and get the completed hex string:
txb.finalizeAllInputs(); const tx = txb.extractTransaction(); const txHex = tx.toHex();If you make progress on this I really want to know if there is a way to generate multiple address with the same multisig using BitcoinJS (working for a Typescript project that needs it atm)
Thanks for the detailed response, but how did you compute
this.watcherKey? About your question, unfortenly I didn't make progress with it, because I changed direction for some time, but If you want to create different MuSig wallets using the same public keys, you should usetweakoperation when you create your wallet and then when you create an aggregated signature, but I don't know how to implement it using bitcoins lib.
import {ECPairFactory} from 'ecpair'
const ECPair = ECPairFactory(ecc);
this.watcherKey = ECPair.fromPrivateKey(Buffer.from(config.Bitcoin.BTCPrivKey,'hex'), { network: bitcoin.networks[config.Bitcoin.network] })
Does tweak work by changing the order of address ? I cannot find anything implemented in the BitcoinJS library called tweak.
@leo42
export function tweakKey(
pubKey: Buffer,
h: Buffer | undefined,
): TweakedPublicKey | null {
if (!NBuffer.isBuffer(pubKey)) return null;
if (pubKey.length !== 32) return null;
if (h && h.length !== 32) return null;
const tweakHash = tapTweakHash(pubKey, h);
const res = getEccLib().xOnlyPointAddTweak(pubKey, tweakHash);
if (!res || res.xOnlyPubkey === null) return null;
return {
parity: res.parity,
x: NBuffer.from(res.xOnlyPubkey),
};
}`
In bitcoinjs I found this function for tweaking. And this resource can explain tweak operation in more detail. https://github.com/bitcoinops/taproot-workshop/blob/master/2.2-taptweak.ipynb
And about your last response, are you sure you created a correct key-path spend n-n MuSig wallet? Because I can't understand where you create aggregated signature. In my case, the scenario looks like this:
- create aggregated pub key
- build transaction which have MuSig input
- then need to extract transaction hash for signing(I also didn't find correct way to do it with bitcoinjs)
- sign transaction hash with each private key of MuSig wallet
- get signatures and aggregate it into one(this also i don't know how to do with bitcoinjs)
- add this signature to input
- finalize transaction & broadcast
Do you have the same scenario?
@leo42 @IvanKodak Here are the things you care about:
-
get MuSig address: you can use p2ms https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/addresses.spec.ts#L94-L103
-
extract transaction hash for signing: you can use transaction.hashForSignature https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/transaction.ts#L272
-
aggregate signatures into one:Indeed, there is none. You can refer to taproot's sortSignatures. https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/ts_src/psbt/bip371.ts#L400
Let me know if this helps you or if you have any questions