use chain::transaction::OutPoint;
use util::{transaction_utils,rng};
use util::sha2::Sha256;
+use util::logger::{Logger, Record};
use std;
use std::default::Default;
use std::{cmp,mem};
use std::time::Instant;
+use std::sync::{Arc};
pub struct ChannelKeys {
pub funding_key: SecretKey,
their_shutdown_scriptpubkey: Option<Script>,
channel_monitor: ChannelMonitor,
+
+ logger: Arc<Logger>,
}
const OUR_MAX_HTLCS: u16 = 5; //TODO
// Constructors:
/// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`
- 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 {
if channel_value_satoshis >= MAX_FUNDING_SATOSHIS {
panic!("funding value > 2^24");
}
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
+
+ logger,
}
}
/// 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, require_announce: bool, allow_announce: 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 })});
their_shutdown_scriptpubkey: None,
channel_monitor: channel_monitor,
+
+ logger,
};
let obscure_factor = chan.get_commitment_transaction_number_obscure_factor();
match self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey) {
Ok(_) => {},
- Err(_) => {
+ Err(_e) => {
// 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;
self.last_block_connected = header.bitcoin_hash();
self.funding_tx_confirmations += 1;
if self.funding_tx_confirmations == CONF_TARGET as u64 {
- if non_shutdown_state == ChannelState::FundingSent as u32 {
+ let need_commitment_update = if non_shutdown_state == ChannelState::FundingSent as u32 {
self.channel_state |= ChannelState::OurFundingLocked as u32;
+ true
} 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
} else if self.channel_state < ChannelState::ChannelFunded as u32 {
- panic!("Started confirming a channel in a state pre-FundingSent?");
- }
+ 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.
- 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,
- }));
+ 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,
+ }));
+ }
}
}
}
let (our_signature, commitment_tx) = match self.get_outbound_funding_created_signature() {
Ok(res) => res,
Err(e) => {
+ log_error!(self, "Got bad signatures: {}!", e.err);
self.channel_monitor.unset_funding_info();
return Err(e);
}
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::transaction::OutPoint;
+ use util::test_utils;
+ use util::logger::Logger;
use secp256k1::{Secp256k1,Message,Signature};
use secp256k1::key::{SecretKey,PublicKey};
use crypto::sha2::Sha256;
use crypto::digest::Digest;
+ use std::sync::Arc;
struct TestFeeEstimator {
fee_est: u64
fn outbound_commitment_test() {
// Test vectors from BOLT 3 Appendix C:
let feeest = TestFeeEstimator{fee_est: 15000};
+ let logger : Arc<Logger> = Arc::new(test_utils::TestLogger::new());
let secp_ctx = Secp256k1::new();
let chan_keys = ChannelKeys {
assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan_keys.funding_key).unwrap().serialize()[..],
hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
- 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;