How to construct a partially signed transaction
Opened this issue · 6 comments
Can you give me a demo of a transaction involving partial signatures from multiple people?
In addition, I have a question: For example, a transaction requires three people to sign. If the first two people have signed, and it is the third person's turn to sign, will the third person see the private keys of the first two people?
You only see signatures from other parties. Private keys never get exposed.
Which language/framework are you using (direct Rust or JavaScript/TypeScript)?
The language I use is JavaScript/TypeScript, thank you for your reply
I still have a question. For example, a transaction requires three people to sign. Now the first two people have signed, and now it is the third person's turn to sign. Does privkeys need to pass in the private keys of the three people, or does it mean that you only need to pass in your own private key? That's it
pub fn sign_with_multiple_v2(mut mutable_tx: SignableTransaction, privkeys: Vec<[u8; 32]>) -> Signed {
let mut map = BTreeMap::new();
for privkey in privkeys {
let schnorr_key = secp256k1::KeyPair::from_seckey_slice(secp256k1::SECP256K1, &privkey).unwrap();
let schnorr_public_key = schnorr_key.public_key().x_only_public_key().0;
let script_pub_key_script = once(0x20).chain(schnorr_public_key.serialize().into_iter()).chain(once(0xac)).collect_vec();
map.insert(script_pub_key_script, schnorr_key);
}
let mut reused_values = SigHashReusedValues::new();
let mut additional_signatures_required = false;
for i in 0..mutable_tx.tx.inputs.len() {
let script = mutable_tx.entries[i].as_ref().unwrap().script_public_key.script();
if let Some(schnorr_key) = map.get(&script.to_vec()) {
let sig_hash = calc_schnorr_signature_hash(&mutable_tx.as_verifiable(), i, SIG_HASH_ALL, &mut reused_values);
let msg = secp256k1::Message::from_slice(sig_hash.as_bytes().as_slice()).unwrap();
let sig: [u8; 64] = *schnorr_key.sign_schnorr(msg).as_ref();
// This represents OP_DATA_65 <SIGNATURE+SIGHASH_TYPE> (since signature length is 64 bytes and SIGHASH_TYPE is one byte)
mutable_tx.tx.inputs[i].signature_script = std::iter::once(65u8).chain(sig).chain([SIG_HASH_ALL.to_u8()]).collect();
} else {
additional_signatures_required = true;
}
}
if additional_signatures_required {
Signed::Partially(mutable_tx)
} else {
Signed::Fully(mutable_tx)
}
}
Passing private keys around would defeat the purpose of any multi-party signing.
https://kaspa.aspectron.org/docs/classes/Transaction.html has serializeToJSON
and serializeToSafeJSON
(and the opposites) which allow ser/deser of transactions to/from JSON. "SafeJSON" converts all bigint
values to strings; there is also serializeToObject
that returns a pure JavaScript Object.
You should ask for feedback to your questions on Discord#development
Hi. I would like a sample o PSKT building in javascript also.
I want to create a transaction with unpredictable inputs, and unpredictable outputs, till the creator decides to finalize it. It is possible?