use bitcoin::blockdata::script::{Script,Builder};
use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
use bitcoin::blockdata::opcodes;
-use bitcoin::util::hash::{Sha256dHash, Hash160};
+use bitcoin::util::hash::{BitcoinHash, Sha256dHash, Hash160};
use bitcoin::util::bip143;
-use bitcoin::network;
-use bitcoin::network::serialize::{BitcoinHash, RawDecoder, RawEncoder};
-use bitcoin::network::encodable::{ConsensusEncodable, ConsensusDecodable};
+use bitcoin::consensus::encode::{self, Encodable, Decodable};
use secp256k1::key::{PublicKey,SecretKey};
use secp256k1::{Secp256k1,Message,Signature};
let secp_ctx = Secp256k1::new();
let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key,
- &chan_keys.htlc_base_key, BREAKDOWN_TIMEOUT,
+ &chan_keys.htlc_base_key, &chan_keys.payment_base_key, BREAKDOWN_TIMEOUT,
keys_provider.get_destination_script(), logger.clone());
Ok(Channel {
let secp_ctx = Secp256k1::new();
let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key, &chan_keys.delayed_payment_base_key,
- &chan_keys.htlc_base_key, BREAKDOWN_TIMEOUT,
+ &chan_keys.htlc_base_key, &chan_keys.payment_base_key, BREAKDOWN_TIMEOUT,
keys_provider.get_destination_script(), logger.clone());
channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint);
+ channel_monitor.provide_their_next_revocation_point(Some((INITIAL_COMMITMENT_NUMBER, msg.first_per_commitment_point)));
channel_monitor.set_their_to_self_delay(msg.to_self_delay);
let mut chan = Channel {
}
self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint);
+ self.channel_monitor.provide_their_next_revocation_point(Some((INITIAL_COMMITMENT_NUMBER, msg.first_per_commitment_point)));
self.their_dust_limit_satoshis = msg.dust_limit_satoshis;
self.their_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.channel_value_satoshis * 1000);
Ok(())
}
- fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Signature), HandleError> {
+ fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Transaction, Signature, TxCreationKeys), HandleError> {
let funding_script = self.get_funding_redeemscript();
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
- let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
+ let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
- // They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
+ // They sign the "local" commitment transaction...
secp_call!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer", self.channel_id());
+ // ...and we sign it, allowing us to broadcast the tx if we wish
+ self.sign_commitment_transaction(&mut local_initial_commitment_tx, sig);
+
let remote_keys = self.build_remote_transaction_keys()?;
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
- Ok((remote_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key)))
+ Ok((remote_initial_commitment_tx, local_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key), local_keys))
}
pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), HandleError> {
let funding_txo_script = self.get_funding_redeemscript().to_v0_p2wsh();
self.channel_monitor.set_funding_info((funding_txo, funding_txo_script));
- let (remote_initial_commitment_tx, our_signature) = match self.funding_created_signature(&msg.signature) {
+ let (remote_initial_commitment_tx, local_initial_commitment_tx, our_signature, local_keys) = match self.funding_created_signature(&msg.signature) {
Ok(res) => res,
Err(e) => {
self.channel_monitor.unset_funding_info();
// Now that we're past error-generating stuff, update our local state:
self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number);
+ self.last_local_commitment_txn = vec![local_initial_commitment_tx.clone()];
+ self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new());
self.channel_state = ChannelState::FundingSent as u32;
self.channel_id = funding_txo.to_channel_id();
self.cur_remote_commitment_transaction_number -= 1;
return Err(ChannelError::Close("Peer sent a funding_locked at a strange time"));
}
+ self.channel_monitor.provide_their_next_revocation_point(Some((INITIAL_COMMITMENT_NUMBER - 1 , msg.next_per_commitment_point)));
self.their_prev_commitment_point = self.their_cur_commitment_point;
self.their_cur_commitment_point = Some(msg.next_per_commitment_point);
Ok(())
return Err(HandleError{err: "Got a revoke commitment secret which didn't correspond to their current pubkey", action: None});
}
}
- self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret, Some((self.cur_remote_commitment_transaction_number - 1, msg.next_per_commitment_point)))?;
+ self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret)?;
+ self.channel_monitor.provide_their_next_revocation_point(Some((self.cur_remote_commitment_transaction_number - 1, msg.next_per_commitment_point)));
// Update state now that we've passed all the can-fail calls...
// (note that we may still fail to generate the new commitment_signed message, but that's
self.channel_state = ChannelState::ShutdownComplete as u32;
return outbound_drops;
}
+ // Upon reconnect we have to start the closing_signed dance over, but shutdown messages
+ // will be retransmitted.
+ self.last_sent_closing_fee = None;
let mut inbound_drop_count = 0;
self.pending_inbound_htlcs.retain(|htlc| {
/// May panic if some calls other than message-handling calls (which will all Err immediately)
/// have been called between remove_uncommitted_htlcs_and_mark_paused and this call.
- pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option<msgs::FundingLocked>, Option<msgs::RevokeAndACK>, Option<msgs::CommitmentUpdate>, Option<ChannelMonitor>, RAACommitmentOrder), ChannelError> {
+ pub fn channel_reestablish(&mut self, msg: &msgs::ChannelReestablish) -> Result<(Option<msgs::FundingLocked>, Option<msgs::RevokeAndACK>, Option<msgs::CommitmentUpdate>, Option<ChannelMonitor>, RAACommitmentOrder, Option<msgs::Shutdown>), ChannelError> {
if self.channel_state & (ChannelState::PeerDisconnected as u32) == 0 {
// While BOLT 2 doesn't indicate explicitly we should error this channel here, it
// almost certainly indicates we are going to end up out-of-sync in some way, so we
// remaining cases either succeed or ErrorMessage-fail).
self.channel_state &= !(ChannelState::PeerDisconnected as u32);
+ let shutdown_msg = if self.channel_state & (ChannelState::LocalShutdownSent as u32) != 0 {
+ Some(msgs::Shutdown {
+ channel_id: self.channel_id,
+ scriptpubkey: self.get_closing_scriptpubkey(),
+ })
+ } else { None };
+
if self.channel_state & (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) == ChannelState::FundingSent as u32 {
// Short circuit the whole handler as there is nothing we can resend them
- return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst));
+ return Ok((None, None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg));
}
if msg.next_local_commitment_number == 0 || msg.next_remote_commitment_number == 0 {
return Ok((Some(msgs::FundingLocked {
channel_id: self.channel_id(),
next_per_commitment_point: next_per_commitment_point,
- }), None, None, None, RAACommitmentOrder::CommitmentFirst));
+ }), None, None, None, RAACommitmentOrder::CommitmentFirst, shutdown_msg));
}
let required_revoke = if msg.next_remote_commitment_number == INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number {
panic!("Got non-channel-failing result from free_holding_cell_htlcs");
}
},
- Ok(Some((commitment_update, channel_monitor))) => return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(channel_monitor), order)),
- Ok(None) => return Ok((resend_funding_locked, required_revoke, None, None, order)),
+ Ok(Some((commitment_update, channel_monitor))) => return Ok((resend_funding_locked, required_revoke, Some(commitment_update), Some(channel_monitor), order, shutdown_msg)),
+ Ok(None) => return Ok((resend_funding_locked, required_revoke, None, None, order, shutdown_msg)),
}
} else {
- return Ok((resend_funding_locked, required_revoke, None, None, order));
+ return Ok((resend_funding_locked, required_revoke, None, None, order, shutdown_msg));
}
} else if msg.next_local_commitment_number == our_next_remote_commitment_number - 1 {
if required_revoke.is_some() {
if self.channel_state & (ChannelState::MonitorUpdateFailed as u32) != 0 {
self.monitor_pending_commitment_signed = true;
- return Ok((resend_funding_locked, None, None, None, order));
+ return Ok((resend_funding_locked, None, None, None, order, shutdown_msg));
}
- return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update()), None, order));
+ return Ok((resend_funding_locked, required_revoke, Some(self.get_last_commitment_update()), None, order, shutdown_msg));
} else {
return Err(ChannelError::Close("Peer attempted to reestablish channel with a very old remote commitment transaction"));
}
return Err(ChannelError::Close("Got shutdown with remote pending HTLCs"));
}
}
- if (self.channel_state & ChannelState::RemoteShutdownSent as u32) == ChannelState::RemoteShutdownSent as u32 {
- return Err(ChannelError::Ignore("Remote peer sent duplicate shutdown message"));
- }
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
// BOLT 2 says we must only send a scriptpubkey of certain standard forms, which are up to
(self.last_local_commitment_txn.len() as u64).write(writer)?;
for tx in self.last_local_commitment_txn.iter() {
- if let Err(e) = tx.consensus_encode(&mut RawEncoder::new(WriterWriteAdaptor(writer))) {
+ if let Err(e) = tx.consensus_encode(&mut WriterWriteAdaptor(writer)) {
match e {
- network::serialize::Error::Io(e) => return Err(e),
+ encode::Error::Io(e) => return Err(e),
_ => panic!("last_local_commitment_txn must have been well-formed!"),
}
}
let last_local_commitment_txn_count: u64 = Readable::read(reader)?;
let mut last_local_commitment_txn = Vec::with_capacity(cmp::min(last_local_commitment_txn_count as usize, OUR_MAX_HTLCS as usize*2 + 1));
for _ in 0..last_local_commitment_txn_count {
- last_local_commitment_txn.push(match Transaction::consensus_decode(&mut RawDecoder::new(reader.by_ref())) {
+ last_local_commitment_txn.push(match Transaction::consensus_decode(reader.by_ref()) {
Ok(tx) => tx,
Err(_) => return Err(DecodeError::InvalidValue),
});
mod tests {
use bitcoin::util::hash::{Sha256dHash, Hash160};
use bitcoin::util::bip143;
- use bitcoin::network::serialize::serialize;
+ use bitcoin::consensus::encode::serialize;
use bitcoin::blockdata::script::{Script, Builder};
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::opcodes;
chan.sign_commitment_transaction(&mut unsigned_tx.0, &their_signature);
- assert_eq!(serialize(&unsigned_tx.0).unwrap()[..],
+ assert_eq!(serialize(&unsigned_tx.0)[..],
hex::decode($tx_hex).unwrap()[..]);
};
}
}
chan.sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys).unwrap();
- assert_eq!(serialize(&htlc_tx).unwrap()[..],
+ assert_eq!(serialize(&htlc_tx)[..],
hex::decode($tx_hex).unwrap()[..]);
};
}