use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingForwardHTLCInfo, HTLCFailReason};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingForwardHTLCInfo, HTLCFailReason};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
use chain::transaction::OutPoint;
use util::{transaction_utils,rng};
use util::sha2::Sha256;
use chain::transaction::OutPoint;
use util::{transaction_utils,rng};
use util::sha2::Sha256;
/// to detect unconfirmation after a serialize-unserialize roudtrip where we may not see a full
/// series of block_connected/block_disconnected calls. Obviously this is not a guarantee as we
/// could miss the funding_tx_confirmed_in block as well, but it serves as a useful fallback.
/// to detect unconfirmation after a serialize-unserialize roudtrip where we may not see a full
/// series of block_connected/block_disconnected calls. Obviously this is not a guarantee as we
/// could miss the funding_tx_confirmed_in block as well, but it serves as a useful fallback.
short_channel_id: Option<u64>,
/// Used to deduplicate block_connected callbacks
last_block_connected: Sha256dHash,
short_channel_id: Option<u64>,
/// Used to deduplicate block_connected callbacks
last_block_connected: Sha256dHash,
their_shutdown_scriptpubkey: Option<Script>,
channel_monitor: ChannelMonitor,
their_shutdown_scriptpubkey: Option<Script>,
channel_monitor: ChannelMonitor,
- pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, announce_publicly: bool, user_id: u64) -> Channel {
+ pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, announce_publicly: bool, user_id: u64, logger: Arc<Logger>) -> Channel {
short_channel_id: None,
last_block_connected: Default::default(),
funding_tx_confirmations: 0,
short_channel_id: None,
last_block_connected: Default::default(),
funding_tx_confirmations: 0,
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
/// Assumes chain_hash has already been checked and corresponds with what we expect!
/// Generally prefers to take the DisconnectPeer action on failure, as a notice to the sender
/// that we're rejecting the new channel.
/// Assumes chain_hash has already been checked and corresponds with what we expect!
/// Generally prefers to take the DisconnectPeer action on failure, as a notice to the sender
/// that we're rejecting the new channel.
- pub fn new_from_req(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, announce_publicly: bool) -> Result<Channel, HandleError> {
+ pub fn new_from_req(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, require_announce: bool, allow_announce: bool, logger: Arc<Logger>) -> Result<Channel, HandleError> {
// Check sanity of message fields:
if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS {
return Err(HandleError{err: "funding value > 2^24", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
// Check sanity of message fields:
if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS {
return Err(HandleError{err: "funding value > 2^24", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })});
// Convert things into internal flags and prep our state:
let their_announce = if (msg.channel_flags & 1) == 1 { true } else { false };
// Convert things into internal flags and prep our state:
let their_announce = if (msg.channel_flags & 1) == 1 { true } else { false };
+ if require_announce && !their_announce {
+ return Err(HandleError{err: "Peer tried to open unannounced channel, but we require public ones", action: Some(msgs::ErrorAction::IgnoreError) });
+ }
+ if !allow_announce && their_announce {
+ return Err(HandleError{err: "Peer tried to open announced channel, but we require private ones", action: Some(msgs::ErrorAction::IgnoreError) });
+ }
short_channel_id: None,
last_block_connected: Default::default(),
funding_tx_confirmations: 0,
short_channel_id: None,
last_block_connected: Default::default(),
funding_tx_confirmations: 0,
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
- pub fn get_update_fulfill_htlc(&mut self, payment_preimage_arg: [u8; 32]) -> Result<Option<(msgs::UpdateFulfillHTLC, ChannelMonitor)>, HandleError> {
+ fn get_update_fulfill_htlc(&mut self, payment_preimage_arg: [u8; 32]) -> Result<(Option<msgs::UpdateFulfillHTLC>, Option<ChannelMonitor>), HandleError> {
// Either ChannelFunded got set (which means it wont bet unset) or there is no way any
// caller thought we could have something claimed (cause we wouldn't have accepted in an
// incoming HTLC anyway). If we got to ShutdownComplete, callers aren't allowed to call us,
// Either ChannelFunded got set (which means it wont bet unset) or there is no way any
// caller thought we could have something claimed (cause we wouldn't have accepted in an
// incoming HTLC anyway). If we got to ShutdownComplete, callers aren't allowed to call us,
+ let mut pending_idx = std::usize::MAX;
+ for (idx, htlc) in self.pending_htlcs.iter().enumerate() {
+ if !htlc.outbound && htlc.payment_hash == payment_hash_calc {
+ if pending_idx != std::usize::MAX {
+ panic!("Duplicate HTLC payment_hash, you probably re-used payment preimages, NEVER DO THIS!");
+ }
+ pending_idx = idx;
+ }
+ }
+ if pending_idx == std::usize::MAX {
+ return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", action: None});
+ }
+
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
for pending_update in self.holding_cell_htlc_updates.iter() {
match pending_update {
&HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, .. } => {
if payment_preimage_arg == *payment_preimage {
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
for pending_update in self.holding_cell_htlc_updates.iter() {
match pending_update {
&HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, .. } => {
if payment_preimage_arg == *payment_preimage {
self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::ClaimHTLC {
payment_preimage: payment_preimage_arg, payment_hash: payment_hash_calc,
});
self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::ClaimHTLC {
payment_preimage: payment_preimage_arg, payment_hash: payment_hash_calc,
});
- return Ok(None);
- }
-
- let mut htlc_id = 0;
- let mut htlc_amount_msat = 0;
- for htlc in self.pending_htlcs.iter_mut() {
- if !htlc.outbound && htlc.payment_hash == payment_hash_calc {
- if htlc_id != 0 {
- panic!("Duplicate HTLC payment_hash, you probably re-used payment preimages, NEVER DO THIS!");
- }
- htlc_id = htlc.htlc_id;
- htlc_amount_msat += htlc.amount_msat;
- if htlc.state == HTLCState::Committed {
- htlc.state = HTLCState::LocalRemoved;
- htlc.local_removed_fulfilled = true;
- } else if htlc.state == HTLCState::RemoteAnnounced {
- panic!("Somehow forwarded HTLC prior to remote revocation!");
- } else if htlc.state == HTLCState::LocalRemoved || htlc.state == HTLCState::LocalRemovedAwaitingCommitment {
- return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", action: None});
- } else {
- panic!("Have an inbound HTLC when not awaiting remote revoke that had a garbage state");
- }
+ return Ok((None, Some(self.channel_monitor.clone())));
+ }
+
+ let htlc_id = {
+ let htlc = &mut self.pending_htlcs[pending_idx];
+ if htlc.state == HTLCState::Committed {
+ htlc.state = HTLCState::LocalRemoved;
+ htlc.local_removed_fulfilled = true;
+ } else if htlc.state == HTLCState::RemoteAnnounced {
+ panic!("Somehow forwarded HTLC prior to remote revocation!");
+ } else if htlc.state == HTLCState::LocalRemoved || htlc.state == HTLCState::LocalRemovedAwaitingCommitment {
+ return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", action: None});
+ } else {
+ panic!("Have an inbound HTLC when not awaiting remote revoke that had a garbage state");
- }
- if htlc_amount_msat == 0 {
- return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", action: None});
- }
- self.channel_monitor.provide_payment_preimage(&payment_hash_calc, &payment_preimage_arg);
channel_id: self.channel_id(),
htlc_id: htlc_id,
payment_preimage: payment_preimage_arg,
channel_id: self.channel_id(),
htlc_id: htlc_id,
payment_preimage: payment_preimage_arg,
- pub fn get_update_fulfill_htlc_and_commit(&mut self, payment_preimage: [u8; 32]) -> Result<Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned, ChannelMonitor)>, HandleError> {
+ pub fn get_update_fulfill_htlc_and_commit(&mut self, payment_preimage: [u8; 32]) -> Result<(Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)>, Option<ChannelMonitor>), HandleError> {
+ (None, Some(channel_monitor)) => Ok((None, Some(channel_monitor))),
+ (None, None) => Ok((None, None))
- pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<ChannelMonitor, HandleError> {
+ pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<(), HandleError> {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
}
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", action: None});
}
}
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<[u8; 32], HandleError> {
}
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<[u8; 32], HandleError> {
},
&HTLCUpdateAwaitingACK::ClaimHTLC { payment_preimage, .. } => {
match self.get_update_fulfill_htlc(payment_preimage) {
},
&HTLCUpdateAwaitingACK::ClaimHTLC { payment_preimage, .. } => {
match self.get_update_fulfill_htlc(payment_preimage) {
// The remote end may have decided to revoke their output due to inconsistent dust
// limits, so check for that case by re-checking the signature here.
closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
// The remote end may have decided to revoke their output due to inconsistent dust
// limits, so check for that case by re-checking the signature here.
closing_tx = self.build_closing_transaction(msg.fee_satoshis, true).0;
pub fn channel_monitor(&self) -> ChannelMonitor {
if self.channel_state < ChannelState::FundingCreated as u32 {
panic!("Can't get a channel monitor until funding has been created");
pub fn channel_monitor(&self) -> ChannelMonitor {
if self.channel_state < ChannelState::FundingCreated as u32 {
panic!("Can't get a channel monitor until funding has been created");
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
/// is_usable() returns true).
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
/// is_usable() returns true).
pub fn get_our_fee_base_msat(&self, fee_estimator: &FeeEstimator) -> u32 {
// For lack of a better metric, we calculate what it would cost to consolidate the new HTLC
// output value back into a transaction with the regular channel output:
pub fn get_our_fee_base_msat(&self, fee_estimator: &FeeEstimator) -> u32 {
// For lack of a better metric, we calculate what it would cost to consolidate the new HTLC
// output value back into a transaction with the regular channel output:
pub fn is_usable(&self) -> bool {
let mask = ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK;
(self.channel_state & mask) == (ChannelState::ChannelFunded as u32)
pub fn is_usable(&self) -> bool {
let mask = ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK;
(self.channel_state & mask) == (ChannelState::ChannelFunded as u32)
/// Returns true if this channel is currently available for use. This is a superset of
/// is_usable() and considers things like the channel being temporarily disabled.
/// Returns true if this channel is currently available for use. This is a superset of
/// is_usable() and considers things like the channel being temporarily disabled.
/// Returns true if this channel is fully shut down. True here implies that no further actions
/// may/will be taken on this channel, and thus this object should be freed. Any future changes
/// will be handled appropriately by the chain monitor.
/// Returns true if this channel is fully shut down. True here implies that no further actions
/// may/will be taken on this channel, and thus this object should be freed. Any future changes
/// will be handled appropriately by the chain monitor.
/// Called by channelmanager based on chain blocks being connected.
/// Note that we only need to use this to detect funding_signed, anything else is handled by
/// the channel_monitor.
/// Called by channelmanager based on chain blocks being connected.
/// Note that we only need to use this to detect funding_signed, anything else is handled by
/// the channel_monitor.
- pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Option<msgs::FundingLocked> {
+ /// In case of Err, the channel may have been closed, at which point the standard requirements
+ /// apply - no calls may be made except those explicitly stated to be allowed post-shutdown.
+ /// Only returns an ErrorAction of DisconnectPeer, if Err.
+ pub fn block_connected(&mut self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], indexes_of_txn_matched: &[u32]) -> Result<Option<msgs::FundingLocked>, HandleError> {
let non_shutdown_state = self.channel_state & (!BOTH_SIDES_SHUTDOWN_MASK);
if self.funding_tx_confirmations > 0 {
if header.bitcoin_hash() != self.last_block_connected {
self.last_block_connected = header.bitcoin_hash();
self.funding_tx_confirmations += 1;
if self.funding_tx_confirmations == CONF_TARGET as u64 {
let non_shutdown_state = self.channel_state & (!BOTH_SIDES_SHUTDOWN_MASK);
if self.funding_tx_confirmations > 0 {
if header.bitcoin_hash() != self.last_block_connected {
self.last_block_connected = header.bitcoin_hash();
self.funding_tx_confirmations += 1;
if self.funding_tx_confirmations == CONF_TARGET as u64 {
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) {
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK);
self.channel_update_count += 1;
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) {
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & BOTH_SIDES_SHUTDOWN_MASK);
self.channel_update_count += 1;
- //TODO: Something about a state where we "lost confirmation"
+ true
+ } else if self.channel_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
+ // We got a reorg but not enough to trigger a force close, just update
+ // funding_tx_confirmed_in and return.
+ false
- panic!("Started confirming a channel in a state pre-FundingSent?");
- }
- self.funding_tx_confirmed_in = header.bitcoin_hash();
+ panic!("Started confirming a channel in a state pre-FundingSent?: {}", self.channel_state);
+ } else {
+ // We got a reorg but not enough to trigger a force close, just update
+ // funding_tx_confirmed_in and return.
+ false
+ };
+ self.funding_tx_confirmed_in = Some(header.bitcoin_hash());
//TODO: Note that this must be a duplicate of the previous commitment point they sent us,
//as otherwise we will have a commitment transaction that they can't revoke (well, kinda,
//they can by sending two revoke_and_acks back-to-back, but not really). This appears to be
//a protocol oversight, but I assume I'm just missing something.
//TODO: Note that this must be a duplicate of the previous commitment point they sent us,
//as otherwise we will have a commitment transaction that they can't revoke (well, kinda,
//they can by sending two revoke_and_acks back-to-back, but not really). This appears to be
//a protocol oversight, but I assume I'm just missing something.
- let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
- let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret).unwrap();
- return Some(msgs::FundingLocked {
- channel_id: self.channel_id,
- next_per_commitment_point: next_per_commitment_point,
- });
+ if need_commitment_update {
+ let next_per_commitment_secret = self.build_local_commitment_secret(self.cur_local_commitment_transaction_number);
+ let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &next_per_commitment_secret).unwrap();
+ return Ok(Some(msgs::FundingLocked {
+ channel_id: self.channel_id,
+ next_per_commitment_point: next_per_commitment_point,
+ }));
+ }
tx.output[txo_idx].value != self.channel_value_satoshis {
self.channel_state = ChannelState::ShutdownComplete as u32;
self.channel_update_count += 1;
tx.output[txo_idx].value != self.channel_value_satoshis {
self.channel_state = ChannelState::ShutdownComplete as u32;
self.channel_update_count += 1;
- /// shutdown of this channel - no more calls into this Channel may be made afterwards.
- pub fn force_shutdown(&mut self) -> Vec<Transaction> {
+ /// shutdown of this channel - no more calls into this Channel may be made afterwards except
+ /// those explicitly stated to be allowed after shutdown completes, eg some simple getters).
+ /// Also returns the list of payment_hashes for channels which we can safely fail backwards
+ /// immediately (others we will have to allow to time out).
+ pub fn force_shutdown(&mut self) -> (Vec<Transaction>, Vec<[u8; 32]>) {
+
+ // We go ahead and "free" any holding cell HTLCs or HTLCs we haven't yet committed to and
+ // return them to fail the payment.
+ let mut dropped_outbound_htlcs = Vec::with_capacity(self.holding_cell_htlc_updates.len());
+ for htlc_update in self.holding_cell_htlc_updates.drain(..) {
+ match htlc_update {
+ HTLCUpdateAwaitingACK::AddHTLC { payment_hash, .. } => {
+ dropped_outbound_htlcs.push(payment_hash);
+ },
+ _ => {}
+ }
+ }
+
+ for htlc in self.pending_htlcs.drain(..) {
+ if htlc.state == HTLCState::LocalAnnounced {
+ dropped_outbound_htlcs.push(htlc.payment_hash);
+ }
+ //TODO: Do something with the remaining HTLCs
+ //(we need to have the ChannelManager monitor them so we can claim the inbound HTLCs
+ //which correspond)
+ }
+
self.channel_state = ChannelState::ShutdownComplete as u32;
self.channel_update_count += 1;
let mut res = Vec::new();
mem::swap(&mut res, &mut self.last_local_commitment_txn);
self.channel_state = ChannelState::ShutdownComplete as u32;
self.channel_update_count += 1;
let mut res = Vec::new();
mem::swap(&mut res, &mut self.last_local_commitment_txn);
use bitcoin::util::hash::Sha256dHash;
use bitcoin::util::bip143;
use bitcoin::network::serialize::serialize;
use bitcoin::blockdata::script::Script;
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::util::hash::Sha256dHash;
use bitcoin::util::bip143;
use bitcoin::network::serialize::serialize;
use bitcoin::blockdata::script::Script;
use bitcoin::blockdata::transaction::Transaction;
use ln::channel::{Channel,ChannelKeys,HTLCOutput,HTLCState,HTLCOutputInCommitment,TxCreationKeys};
use ln::channel::MAX_FUNDING_SATOSHIS;
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::transaction::OutPoint;
use ln::channel::{Channel,ChannelKeys,HTLCOutput,HTLCState,HTLCOutputInCommitment,TxCreationKeys};
use ln::channel::MAX_FUNDING_SATOSHIS;
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::transaction::OutPoint;
use secp256k1::{Secp256k1,Message,Signature};
use secp256k1::key::{SecretKey,PublicKey};
use crypto::sha2::Sha256;
use crypto::digest::Digest;
use secp256k1::{Secp256k1,Message,Signature};
use secp256k1::key::{SecretKey,PublicKey};
use crypto::sha2::Sha256;
use crypto::digest::Digest;
fn outbound_commitment_test() {
// Test vectors from BOLT 3 Appendix C:
let feeest = TestFeeEstimator{fee_est: 15000};
fn outbound_commitment_test() {
// Test vectors from BOLT 3 Appendix C:
let feeest = TestFeeEstimator{fee_est: 15000};
- funding_key: SecretKey::from_slice(&secp_ctx, &hex_bytes("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(),
- payment_base_key: SecretKey::from_slice(&secp_ctx, &hex_bytes("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(),
- delayed_payment_base_key: SecretKey::from_slice(&secp_ctx, &hex_bytes("3333333333333333333333333333333333333333333333333333333333333333").unwrap()[..]).unwrap(),
- htlc_base_key: SecretKey::from_slice(&secp_ctx, &hex_bytes("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(),
+ funding_key: SecretKey::from_slice(&secp_ctx, &hex::decode("30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f3749").unwrap()[..]).unwrap(),
+ payment_base_key: SecretKey::from_slice(&secp_ctx, &hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(),
+ delayed_payment_base_key: SecretKey::from_slice(&secp_ctx, &hex::decode("3333333333333333333333333333333333333333333333333333333333333333").unwrap()[..]).unwrap(),
+ htlc_base_key: SecretKey::from_slice(&secp_ctx, &hex::decode("1111111111111111111111111111111111111111111111111111111111111111").unwrap()[..]).unwrap(),
- revocation_base_key: SecretKey::from_slice(&secp_ctx, &hex_bytes("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
- channel_close_key: SecretKey::from_slice(&secp_ctx, &hex_bytes("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
- channel_monitor_claim_key: SecretKey::from_slice(&secp_ctx, &hex_bytes("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
+ revocation_base_key: SecretKey::from_slice(&secp_ctx, &hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
+ channel_close_key: SecretKey::from_slice(&secp_ctx, &hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
+ channel_monitor_claim_key: SecretKey::from_slice(&secp_ctx, &hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
commitment_seed: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
};
assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan_keys.funding_key).unwrap().serialize()[..],
commitment_seed: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
};
assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan_keys.funding_key).unwrap().serialize()[..],
- let mut chan = Channel::new_outbound(&feeest, chan_keys, PublicKey::new(), 10000000, false, 42); // Nothing uses their network key in this test
+ let mut chan = Channel::new_outbound(&feeest, chan_keys, PublicKey::new(), 10000000, false, 42, Arc::clone(&logger)); // Nothing uses their network key in this test
chan.their_to_self_delay = 144;
chan.our_dust_limit_satoshis = 546;
let funding_info = OutPoint::new(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0);
chan.channel_monitor.set_funding_info((funding_info, Script::new()));
chan.their_to_self_delay = 144;
chan.our_dust_limit_satoshis = 546;
let funding_info = OutPoint::new(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0);
chan.channel_monitor.set_funding_info((funding_info, Script::new()));
- chan.their_payment_basepoint = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()).unwrap();
+ chan.their_payment_basepoint = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()).unwrap();
- chan.their_funding_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13").unwrap()[..]).unwrap()).unwrap();
+ chan.their_funding_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("1552dfba4f6cf29a62a0af13c8d6981d36d0ef8d61ba10fb0fe90da7634d7e13").unwrap()[..]).unwrap()).unwrap();
- chan.their_htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex_bytes("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()).unwrap();
+ chan.their_htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &hex::decode("4444444444444444444444444444444444444444444444444444444444444444").unwrap()[..]).unwrap()).unwrap();
// We can't just use build_local_transaction_keys here as the per_commitment_secret is not
// derived from a commitment_seed, so instead we copy it here and call
// build_commitment_transaction.
let delayed_payment_base = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.delayed_payment_base_key).unwrap();
// We can't just use build_local_transaction_keys here as the per_commitment_secret is not
// derived from a commitment_seed, so instead we copy it here and call
// build_commitment_transaction.
let delayed_payment_base = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.delayed_payment_base_key).unwrap();
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret).unwrap();
let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.htlc_base_key).unwrap();
let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &chan.their_revocation_basepoint, &chan.their_payment_basepoint, &chan.their_htlc_basepoint).unwrap();
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret).unwrap();
let htlc_basepoint = PublicKey::from_secret_key(&secp_ctx, &chan.local_keys.htlc_base_key).unwrap();
let keys = TxCreationKeys::new(&secp_ctx, &per_commitment_point, &delayed_payment_base, &htlc_basepoint, &chan.their_revocation_basepoint, &chan.their_payment_basepoint, &chan.their_htlc_basepoint).unwrap();
macro_rules! test_commitment {
( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false);
macro_rules! test_commitment {
( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false);
let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap();
secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey).unwrap();
chan.sign_commitment_transaction(&mut unsigned_tx.0, &their_signature);
assert_eq!(serialize(&unsigned_tx.0).unwrap()[..],
let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap();
secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey).unwrap();
chan.sign_commitment_transaction(&mut unsigned_tx.0, &their_signature);
assert_eq!(serialize(&unsigned_tx.0).unwrap()[..],
};
}
macro_rules! test_htlc_output {
( $htlc_idx: expr, $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr ) => {
};
}
macro_rules! test_htlc_output {
( $htlc_idx: expr, $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr ) => {
let ref htlc = unsigned_tx.1[$htlc_idx];
let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys);
let ref htlc = unsigned_tx.1[$htlc_idx];
let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys);
chan.sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys).unwrap();
assert_eq!(serialize(&htlc_tx).unwrap()[..],
chan.sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys).unwrap();
assert_eq!(serialize(&htlc_tx).unwrap()[..],
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
pending_forward_state: None,
};
let mut sha = Sha256::new();
- let base_secret = SecretKey::from_slice(&secp_ctx, &hex_bytes("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap();
- let per_commitment_secret = SecretKey::from_slice(&secp_ctx, &hex_bytes("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
+ let base_secret = SecretKey::from_slice(&secp_ctx, &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap()[..]).unwrap();
+ let per_commitment_secret = SecretKey::from_slice(&secp_ctx, &hex::decode("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100").unwrap()[..]).unwrap();
assert_eq!(chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &base_point).unwrap().serialize()[..],
assert_eq!(chan_utils::derive_public_key(&secp_ctx, &per_commitment_point, &base_point).unwrap().serialize()[..],
assert_eq!(chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &base_secret).unwrap(),
assert_eq!(chan_utils::derive_private_key(&secp_ctx, &per_commitment_point, &base_secret).unwrap(),
assert_eq!(chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &base_point).unwrap().serialize()[..],
assert_eq!(chan_utils::derive_public_revocation_key(&secp_ctx, &per_commitment_point, &base_point).unwrap().serialize()[..],
assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret).unwrap(),
assert_eq!(chan_utils::derive_private_revocation_key(&secp_ctx, &per_commitment_secret, &base_secret).unwrap(),