-
-
Save stevenroose/e32173d7f4213bf71ccc848431dc5379 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let mut unsigned_tx: Transaction = deserialize(&funded_result.hex)?; | |
// Gather the details for the inputs. | |
let mut input_details = Vec::with_capacity(unsigned_tx.input.len()); | |
for input in &unsigned_tx.input { | |
let prevout = input.previous_output; | |
let prevtx = self.rpc.get_transaction(&prevout.txid, Some(true))?; | |
let details = match prevtx.details.into_iter().find(|d| d.vout == prevout.vout) { | |
None => bail!("transaction has unknown input: {}", prevout), | |
Some(det) => det, | |
}; | |
// If the output is not p2wpkh, we can't spend it for now. | |
//TODO(stevenroose) implement non-p2wpkh spending | |
//TODO(stevenroose) make this check better after https://github.com/rust-bitcoin/rust-bitcoin/pull/255 | |
let is_p2wpkh = match details.address.payload { | |
bitcoin::util::address::Payload::WitnessProgram(ref prog) => { | |
prog.program().len() == 20 | |
} | |
_ => false, | |
}; | |
if !is_p2wpkh { | |
warn!("Wallet received a tx on a non-p2wpkh address {}: {}", details.address, prevout); | |
// We lock the unspent so it doesn't get selected anymore. | |
self.rpc.lock_unspent(&[prevout])?; | |
continue 'outer; | |
} | |
input_details.push(details); | |
} | |
debug!("unsigned_tx: {:?}", unsigned_tx); | |
// Sign the tx. | |
let sighash_components = bip143::SighashComponents::new(&unsigned_tx); | |
for (idx, details) in input_details.into_iter().enumerate() { | |
if details.label.is_none() { | |
bail!("no label on address {}", details.address); | |
} | |
let label = AddressMeta::from_label(details.label.as_ref())?; | |
let xpriv = if label.fp == self.external_xpriv.as_ref().unwrap().fingerprint(&SECP) | |
{ | |
self.external_xpriv.as_ref().unwrap() | |
} else if label.fp == self.internal_xpriv.as_ref().unwrap().fingerprint(&SECP) { | |
self.internal_xpriv.as_ref().unwrap() | |
} else { | |
bail!( | |
"address is labeled with unknown master xpriv fingerprint: {:?}", | |
label.fp | |
) | |
}; | |
let privkey = xpriv.derive_priv(&SECP, &[label.child])?.private_key; | |
let pubkey = privkey.public_key(&SECP); | |
let script_code = bitcoin::Address::p2pkh(&pubkey, privkey.network).script_pubkey(); | |
let sighash = sighash_components.sighash_all( | |
&unsigned_tx.input[idx], | |
&script_code, | |
details.amount.into_inner() as u64, | |
); | |
let msg = secp256k1::Message::from_slice(&sighash[..])?; | |
let mut signature = SECP.sign(&msg, &xpriv.private_key.key).serialize_der(); | |
signature.push(0x01); | |
unsigned_tx.input[idx].witness = vec![signature, pubkey.to_bytes()]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment