+impl Sign for InMemorySigner {
+ fn get_per_commitment_point<T: secp256k1::Signing + secp256k1::Verification>(&self, idx: u64, secp_ctx: &Secp256k1<T>) -> PublicKey {
+ let commitment_secret = SecretKey::from_slice(&chan_utils::build_commitment_secret(&self.commitment_seed, idx)).unwrap();
+ PublicKey::from_secret_key(secp_ctx, &commitment_secret)
+ }
+
+ fn release_commitment_secret(&self, idx: u64) -> [u8; 32] {
+ chan_utils::build_commitment_secret(&self.commitment_seed, idx)
+ }
+
+ fn pubkeys(&self) -> &ChannelPublicKeys { &self.holder_channel_pubkeys }
+ fn channel_keys_id(&self) -> [u8; 32] { self.channel_keys_id }
+
+ fn sign_counterparty_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &CommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+ let trusted_tx = commitment_tx.trust();
+ let keys = trusted_tx.keys();
+
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
+
+ let built_tx = trusted_tx.built_transaction();
+ let commitment_sig = built_tx.sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx);
+ let commitment_txid = built_tx.txid;
+
+ let mut htlc_sigs = Vec::with_capacity(commitment_tx.htlcs().len());
+ for htlc in commitment_tx.htlcs() {
+ let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_tx.feerate_per_kw(), self.holder_selected_contest_delay(), htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
+ let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
+ let htlc_sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, htlc.amount_msat / 1000, SigHashType::All)[..]);
+ let holder_htlc_key = match chan_utils::derive_private_key(&secp_ctx, &keys.per_commitment_point, &self.htlc_base_key) {
+ Ok(s) => s,
+ Err(_) => return Err(()),
+ };
+ htlc_sigs.push(secp_ctx.sign(&htlc_sighash, &holder_htlc_key));
+ }
+
+ Ok((commitment_sig, htlc_sigs))
+ }
+
+ fn sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
+ let trusted_tx = commitment_tx.trust();
+ let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
+ let channel_parameters = self.get_channel_parameters();
+ let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
+ Ok((sig, htlc_sigs))
+ }
+
+ #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
+ fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
+ let trusted_tx = commitment_tx.trust();
+ let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
+ let channel_parameters = self.get_channel_parameters();
+ let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
+ Ok((sig, htlc_sigs))
+ }
+
+ fn sign_justice_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+ let revocation_key = match chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_key, &self.revocation_base_key) {
+ Ok(revocation_key) => revocation_key,
+ Err(_) => return Err(())
+ };
+ let per_commitment_point = PublicKey::from_secret_key(secp_ctx, &per_commitment_key);
+ let revocation_pubkey = match chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint) {
+ Ok(revocation_pubkey) => revocation_pubkey,
+ Err(_) => return Err(())
+ };
+ let witness_script = if let &Some(ref htlc) = htlc {
+ let counterparty_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().htlc_basepoint) {
+ Ok(counterparty_htlcpubkey) => counterparty_htlcpubkey,
+ Err(_) => return Err(())
+ };
+ let holder_htlcpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint) {
+ Ok(holder_htlcpubkey) => holder_htlcpubkey,
+ Err(_) => return Err(())
+ };
+ chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &counterparty_htlcpubkey, &holder_htlcpubkey, &revocation_pubkey)
+ } else {
+ let counterparty_delayedpubkey = match chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().delayed_payment_basepoint) {
+ Ok(counterparty_delayedpubkey) => counterparty_delayedpubkey,
+ Err(_) => return Err(())
+ };
+ chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.holder_selected_contest_delay(), &counterparty_delayedpubkey)
+ };
+ let mut sighash_parts = bip143::SigHashCache::new(justice_tx);
+ let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
+ return Ok(secp_ctx.sign(&sighash, &revocation_key))
+ }
+
+ fn sign_counterparty_htlc_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+ if let Ok(htlc_key) = chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &self.htlc_base_key) {
+ let witness_script = if let Ok(revocation_pubkey) = chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &self.pubkeys().revocation_basepoint) {
+ if let Ok(counterparty_htlcpubkey) = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.counterparty_pubkeys().htlc_basepoint) {
+ if let Ok(htlcpubkey) = chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &self.pubkeys().htlc_basepoint) {
+ chan_utils::get_htlc_redeemscript_with_explicit_keys(&htlc, &counterparty_htlcpubkey, &htlcpubkey, &revocation_pubkey)
+ } else { return Err(()) }
+ } else { return Err(()) }
+ } else { return Err(()) };
+ let mut sighash_parts = bip143::SigHashCache::new(htlc_tx);
+ let sighash = hash_to_message!(&sighash_parts.signature_hash(input, &witness_script, amount, SigHashType::All)[..]);
+ return Ok(secp_ctx.sign(&sighash, &htlc_key))
+ }
+ Err(())
+ }
+
+ fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+ if closing_tx.input.len() != 1 { return Err(()); }
+ if closing_tx.input[0].witness.len() != 0 { return Err(()); }
+ if closing_tx.output.len() > 2 { return Err(()); }
+
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
+
+ let sighash = hash_to_message!(&bip143::SigHashCache::new(closing_tx)
+ .signature_hash(0, &channel_funding_redeemscript, self.channel_value_satoshis, SigHashType::All)[..]);
+ Ok(secp_ctx.sign(&sighash, &self.funding_key))
+ }
+
+ fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+ let msghash = hash_to_message!(&Sha256dHash::hash(&msg.encode()[..])[..]);
+ Ok(secp_ctx.sign(&msghash, &self.funding_key))
+ }
+
+ fn ready_channel(&mut self, channel_parameters: &ChannelTransactionParameters) {
+ assert!(self.channel_parameters.is_none(), "Acceptance already noted");
+ assert!(channel_parameters.is_populated(), "Channel parameters must be fully populated");
+ self.channel_parameters = Some(channel_parameters.clone());
+ }
+}
+
+impl Writeable for InMemorySigner {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
+ self.funding_key.write(writer)?;
+ self.revocation_base_key.write(writer)?;
+ self.payment_key.write(writer)?;
+ self.delayed_payment_base_key.write(writer)?;
+ self.htlc_base_key.write(writer)?;
+ self.commitment_seed.write(writer)?;
+ self.channel_parameters.write(writer)?;
+ self.channel_value_satoshis.write(writer)?;
+ self.channel_keys_id.write(writer)?;
+
+ Ok(())
+ }
+}
+
+impl Readable for InMemorySigner {
+ fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ let funding_key = Readable::read(reader)?;
+ let revocation_base_key = Readable::read(reader)?;
+ let payment_key = Readable::read(reader)?;
+ let delayed_payment_base_key = Readable::read(reader)?;
+ let htlc_base_key = Readable::read(reader)?;
+ let commitment_seed = Readable::read(reader)?;
+ let counterparty_channel_data = Readable::read(reader)?;
+ let channel_value_satoshis = Readable::read(reader)?;
+ let secp_ctx = Secp256k1::signing_only();
+ let holder_channel_pubkeys =
+ InMemorySigner::make_holder_keys(&secp_ctx, &funding_key, &revocation_base_key,
+ &payment_key, &delayed_payment_base_key,
+ &htlc_base_key);
+ let keys_id = Readable::read(reader)?;
+
+ Ok(InMemorySigner {
+ funding_key,
+ revocation_base_key,
+ payment_key,
+ delayed_payment_base_key,
+ htlc_base_key,
+ commitment_seed,
+ channel_value_satoshis,
+ holder_channel_pubkeys,
+ channel_parameters: counterparty_channel_data,
+ channel_keys_id: keys_id,
+ })
+ }
+}