+impl InMemoryChannelKeys {
+ /// Create a new InMemoryChannelKeys
+ pub fn new<C: Signing>(
+ secp_ctx: &Secp256k1<C>,
+ funding_key: SecretKey,
+ revocation_base_key: SecretKey,
+ payment_base_key: SecretKey,
+ delayed_payment_base_key: SecretKey,
+ htlc_base_key: SecretKey,
+ commitment_seed: [u8; 32],
+ channel_value_satoshis: u64) -> InMemoryChannelKeys {
+ let local_channel_pubkeys =
+ InMemoryChannelKeys::make_local_keys(secp_ctx, &funding_key, &revocation_base_key,
+ &payment_base_key, &delayed_payment_base_key,
+ &htlc_base_key);
+ InMemoryChannelKeys {
+ funding_key,
+ revocation_base_key,
+ payment_base_key,
+ delayed_payment_base_key,
+ htlc_base_key,
+ commitment_seed,
+ channel_value_satoshis,
+ local_channel_pubkeys,
+ remote_channel_pubkeys: None,
+ }
+ }
+
+ fn make_local_keys<C: Signing>(secp_ctx: &Secp256k1<C>,
+ funding_key: &SecretKey,
+ revocation_base_key: &SecretKey,
+ payment_base_key: &SecretKey,
+ delayed_payment_base_key: &SecretKey,
+ htlc_base_key: &SecretKey) -> ChannelPublicKeys {
+ let from_secret = |s: &SecretKey| PublicKey::from_secret_key(secp_ctx, s);
+ ChannelPublicKeys {
+ funding_pubkey: from_secret(&funding_key),
+ revocation_basepoint: from_secret(&revocation_base_key),
+ payment_basepoint: from_secret(&payment_base_key),
+ delayed_payment_basepoint: from_secret(&delayed_payment_base_key),
+ htlc_basepoint: from_secret(&htlc_base_key),
+ }
+ }
+}
+
+impl ChannelKeys for InMemoryChannelKeys {
+ fn funding_key(&self) -> &SecretKey { &self.funding_key }
+ fn revocation_base_key(&self) -> &SecretKey { &self.revocation_base_key }
+ fn payment_base_key(&self) -> &SecretKey { &self.payment_base_key }
+ fn delayed_payment_base_key(&self) -> &SecretKey { &self.delayed_payment_base_key }
+ fn htlc_base_key(&self) -> &SecretKey { &self.htlc_base_key }
+ fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed }
+ fn pubkeys<'a>(&'a self) -> &'a ChannelPublicKeys { &self.local_channel_pubkeys }
+
+ fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+ if commitment_tx.input.len() != 1 { return Err(()); }
+
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing");
+ let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey);
+
+ let commitment_sighash = hash_to_message!(&bip143::SighashComponents::new(&commitment_tx).sighash_all(&commitment_tx.input[0], &channel_funding_redeemscript, self.channel_value_satoshis)[..]);
+ let commitment_sig = secp_ctx.sign(&commitment_sighash, &self.funding_key);
+
+ let commitment_txid = commitment_tx.txid();
+
+ let mut htlc_sigs = Vec::with_capacity(htlcs.len());
+ for ref htlc in htlcs {
+ if let Some(_) = htlc.transaction_output_index {
+ let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, feerate_per_kw, to_self_delay, htlc, &keys.a_delayed_payment_key, &keys.revocation_key);
+ let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
+ let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
+ let our_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, &our_htlc_key));
+ }
+ }
+
+ Ok((commitment_sig, htlc_sigs))
+ }
+
+ 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 remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing");
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey);
+
+ let sighash = hash_to_message!(&bip143::SighashComponents::new(closing_tx)
+ .sighash_all(&closing_tx.input[0], &channel_funding_redeemscript, self.channel_value_satoshis)[..]);
+ Ok(secp_ctx.sign(&sighash, &self.funding_key))
+ }
+
+ fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::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 set_remote_channel_pubkeys(&mut self, channel_pubkeys: &ChannelPublicKeys) {
+ assert!(self.remote_channel_pubkeys.is_none(), "Already set remote channel pubkeys");
+ self.remote_channel_pubkeys = Some(channel_pubkeys.clone());
+ }
+}
+
+impl Writeable for InMemoryChannelKeys {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
+ self.funding_key.write(writer)?;
+ self.revocation_base_key.write(writer)?;
+ self.payment_base_key.write(writer)?;
+ self.delayed_payment_base_key.write(writer)?;
+ self.htlc_base_key.write(writer)?;
+ self.commitment_seed.write(writer)?;
+ self.remote_channel_pubkeys.write(writer)?;
+ self.channel_value_satoshis.write(writer)?;
+
+ Ok(())
+ }
+}
+
+impl<R: ::std::io::Read> Readable<R> for InMemoryChannelKeys {
+ fn read(reader: &mut R) -> Result<Self, DecodeError> {
+ let funding_key = Readable::read(reader)?;
+ let revocation_base_key = Readable::read(reader)?;
+ let payment_base_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 remote_channel_pubkeys = Readable::read(reader)?;
+ let channel_value_satoshis = Readable::read(reader)?;
+ let secp_ctx = Secp256k1::signing_only();
+ let local_channel_pubkeys =
+ InMemoryChannelKeys::make_local_keys(&secp_ctx, &funding_key, &revocation_base_key,
+ &payment_base_key, &delayed_payment_base_key,
+ &htlc_base_key);
+
+ Ok(InMemoryChannelKeys {
+ funding_key,
+ revocation_base_key,
+ payment_base_key,
+ delayed_payment_base_key,
+ htlc_base_key,
+ commitment_seed,
+ channel_value_satoshis,
+ local_channel_pubkeys,
+ remote_channel_pubkeys
+ })
+ }
+}