use bitcoin::util::bip143;
use bitcoin::consensus::encode;
-use bitcoin_hashes::{Hash, HashEngine};
-use bitcoin_hashes::sha256::Hash as Sha256;
-use bitcoin_hashes::hash160::Hash as Hash160;
-use bitcoin_hashes::sha256d::Hash as Sha256dHash;
+use bitcoin::hashes::{Hash, HashEngine};
+use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
-use secp256k1::key::{PublicKey,SecretKey};
-use secp256k1::{Secp256k1,Signature};
-use secp256k1;
+use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+use bitcoin::secp256k1::{Secp256k1,Signature};
+use bitcoin::secp256k1;
use ln::features::{ChannelFeatures, InitFeatures};
use ln::msgs;
/// to detect unconfirmation after a serialize-unserialize roundtrip 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.
- funding_tx_confirmed_in: Option<Sha256dHash>,
+ funding_tx_confirmed_in: Option<BlockHash>,
short_channel_id: Option<u64>,
/// Used to deduplicate block_connected callbacks, also used to verify consistency during
/// ChannelManager deserialization (hence pub(super))
- pub(super) last_block_connected: Sha256dHash,
+ pub(super) last_block_connected: BlockHash,
funding_tx_confirmations: u64,
their_dust_limit_satoshis: u64,
#[cfg(not(test))]
their_max_htlc_value_in_flight_msat: u64,
//get_our_max_htlc_value_in_flight_msat(): u64,
- /// minimum channel reserve for **self** to maintain - set by them.
- their_channel_reserve_satoshis: u64,
- //get_our_channel_reserve_satoshis(): u64,
+ /// minimum channel reserve for self to maintain - set by them.
+ local_channel_reserve_satoshis: u64,
+ // get_remote_channel_reserve_satoshis(channel_value_sats: u64): u64
their_htlc_minimum_msat: u64,
our_htlc_minimum_msat: u64,
their_to_self_delay: u16,
channel_value_satoshis * 1000 / 10 //TODO
}
- /// Returns a minimum channel reserve value **they** need to maintain
+ /// Returns a minimum channel reserve value the remote needs to maintain,
+ /// required by us.
///
/// Guaranteed to return a value no larger than channel_value_satoshis
- pub(crate) fn get_our_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 {
+ pub(crate) fn get_remote_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 {
let (q, _) = channel_value_satoshis.overflowing_div(100);
cmp::min(channel_value_satoshis, cmp::max(q, 1000)) //TODO
}
let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
- if Channel::<ChanSigner>::get_our_channel_reserve_satoshis(channel_value_satoshis) < Channel::<ChanSigner>::derive_our_dust_limit_satoshis(background_feerate) {
+ if Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(channel_value_satoshis) < Channel::<ChanSigner>::derive_our_dust_limit_satoshis(background_feerate) {
return Err(APIError::FeeRateTooHigh{err: format!("Not enough reserve above dust limit can be found at current fee rate({})", background_feerate), feerate: background_feerate});
}
their_dust_limit_satoshis: 0,
our_dust_limit_satoshis: Channel::<ChanSigner>::derive_our_dust_limit_satoshis(background_feerate),
their_max_htlc_value_in_flight_msat: 0,
- their_channel_reserve_satoshis: 0,
+ local_channel_reserve_satoshis: 0,
their_htlc_minimum_msat: 0,
our_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
their_to_self_delay: 0,
let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
let our_dust_limit_satoshis = Channel::<ChanSigner>::derive_our_dust_limit_satoshis(background_feerate);
- let our_channel_reserve_satoshis = Channel::<ChanSigner>::get_our_channel_reserve_satoshis(msg.funding_satoshis);
- if our_channel_reserve_satoshis < our_dust_limit_satoshis {
+ let remote_channel_reserve_satoshis = Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(msg.funding_satoshis);
+ if remote_channel_reserve_satoshis < our_dust_limit_satoshis {
return Err(ChannelError::Close("Suitable channel reserve not found. aborting"));
}
if msg.channel_reserve_satoshis < our_dust_limit_satoshis {
return Err(ChannelError::Close("channel_reserve_satoshis too small"));
}
- if our_channel_reserve_satoshis < msg.dust_limit_satoshis {
- return Err(ChannelError::Close("Dust limit too high for our channel reserve"));
+ if remote_channel_reserve_satoshis < msg.dust_limit_satoshis {
+ return Err(ChannelError::Close("Dust limit too high for the channel reserve we require the remote to keep"));
}
// check if the funder's amount for the initial commitment tx is sufficient
let to_local_msat = msg.push_msat;
let to_remote_msat = funders_amount_msat - background_feerate * COMMITMENT_TX_BASE_WEIGHT;
- if to_local_msat <= msg.channel_reserve_satoshis * 1000 && to_remote_msat <= our_channel_reserve_satoshis * 1000 {
+ if to_local_msat <= msg.channel_reserve_satoshis * 1000 && to_remote_msat <= remote_channel_reserve_satoshis * 1000 {
return Err(ChannelError::Close("Insufficient funding amount for initial commitment"));
}
their_dust_limit_satoshis: msg.dust_limit_satoshis,
our_dust_limit_satoshis: our_dust_limit_satoshis,
their_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000),
- their_channel_reserve_satoshis: msg.channel_reserve_satoshis,
+ local_channel_reserve_satoshis: msg.channel_reserve_satoshis,
their_htlc_minimum_msat: msg.htlc_minimum_msat,
our_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
their_to_self_delay: msg.to_self_delay,
} else {
self.max_commitment_tx_output_remote.lock().unwrap()
};
- debug_assert!(max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.their_channel_reserve_satoshis as i64);
+ debug_assert!(max_commitment_tx_output.0 <= value_to_self_msat as u64 || value_to_self_msat / 1000 >= self.local_channel_reserve_satoshis as i64);
max_commitment_tx_output.0 = cmp::max(max_commitment_tx_output.0, value_to_self_msat as u64);
- debug_assert!(max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::<ChanSigner>::get_our_channel_reserve_satoshis(self.channel_value_satoshis) as i64);
+ debug_assert!(max_commitment_tx_output.1 <= value_to_remote_msat as u64 || value_to_remote_msat / 1000 >= Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis) as i64);
max_commitment_tx_output.1 = cmp::max(max_commitment_tx_output.1, value_to_remote_msat as u64);
}
log_trace!(self, " ...including {} output with value {}", if local { "to_remote" } else { "to_local" }, value_to_b);
txouts.push((TxOut {
script_pubkey: Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
- .push_slice(&Hash160::hash(&keys.b_payment_key.serialize())[..])
+ .push_slice(&WPubkeyHash::hash(&keys.b_payment_key.serialize())[..])
.into_script(),
value: value_to_b as u64
}, None));
#[inline]
fn get_closing_scriptpubkey(&self) -> Script {
- let our_channel_close_key_hash = Hash160::hash(&self.shutdown_pubkey.serialize());
+ let our_channel_close_key_hash = WPubkeyHash::hash(&self.shutdown_pubkey.serialize());
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script()
}
/// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output
/// @local is used only to convert relevant internal structures which refer to remote vs local
/// to decide value of outputs and direction of HTLCs.
- fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys, feerate_per_kw: u64) -> Transaction {
+ fn build_htlc_transaction(&self, prev_hash: &Txid, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys, feerate_per_kw: u64) -> Transaction {
chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { self.our_to_self_delay }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key)
}
if msg.channel_reserve_satoshis < self.our_dust_limit_satoshis {
return Err(ChannelError::Close("Peer never wants payout outputs?"));
}
- if msg.dust_limit_satoshis > Channel::<ChanSigner>::get_our_channel_reserve_satoshis(self.channel_value_satoshis) {
+ if msg.dust_limit_satoshis > Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis) {
return Err(ChannelError::Close("Dust limit is bigger than our channel reverse"));
}
if msg.htlc_minimum_msat >= (self.channel_value_satoshis - msg.channel_reserve_satoshis) * 1000 {
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);
- self.their_channel_reserve_satoshis = msg.channel_reserve_satoshis;
+ self.local_channel_reserve_satoshis = msg.channel_reserve_satoshis;
self.their_htlc_minimum_msat = msg.htlc_minimum_msat;
self.their_to_self_delay = msg.to_self_delay;
self.their_max_accepted_htlcs = msg.max_accepted_htlcs;
// They sign the "local" commitment transaction...
secp_check!(self.secp_ctx.verify(&local_sighash, &sig, self.their_funding_pubkey()), "Invalid funding_created signature from peer");
- let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey(), local_keys, self.feerate_per_kw, Vec::new());
+ let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig.clone(), &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey(), local_keys, self.feerate_per_kw, Vec::new());
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 funding_txo_script = funding_redeemscript.to_v0_p2wsh();
macro_rules! create_monitor {
() => { {
- let local_commitment_tx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx.clone(), &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey, local_keys.clone(), self.feerate_per_kw, Vec::new());
+ let local_commitment_tx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx.clone(), msg.signature.clone(), &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), their_funding_pubkey, local_keys.clone(), self.feerate_per_kw, Vec::new());
let mut channel_monitor = ChannelMonitor::new(self.local_keys.clone(),
&self.shutdown_pubkey, self.our_to_self_delay,
&self.destination_script, (funding_txo.clone(), funding_txo_script.clone()),
if htlc_inbound_value_msat + msg.amount_msat > Channel::<ChanSigner>::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis) {
return Err(ChannelError::Close("Remote HTLC add would put them over our max HTLC value"));
}
- // Check our_channel_reserve_satoshis (we're getting paid, so they have to at least meet
+ // Check remote_channel_reserve_satoshis (we're getting paid, so they have to at least meet
// the reserve_satoshis we told them to always have as direct payment so that they lose
// something if we punish them for broadcasting an old state).
// Note that we don't really care about having a small/no to_remote output in our local
removed_outbound_total_msat += htlc.amount_msat;
}
}
- if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::<ChanSigner>::get_our_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 + removed_outbound_total_msat {
- return Err(ChannelError::Close("Remote HTLC add would put them over their reserve value"));
+ if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 + removed_outbound_total_msat {
+ return Err(ChannelError::Close("Remote HTLC add would put them under their reserve value"));
}
if self.next_remote_htlc_id != msg.htlc_id {
return Err(ChannelError::Close("Remote skipped HTLC ID"));
let num_htlcs = local_commitment_tx.1;
let total_fee: u64 = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
- if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + self.their_channel_reserve_satoshis {
+ let remote_reserve_we_require = Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis);
+ if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + remote_reserve_we_require {
return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee")));
}
}
let mut monitor_update = ChannelMonitorUpdate {
update_id: self.latest_monitor_update_id,
updates: vec![ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo {
- commitment_tx: LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), &their_funding_pubkey, local_keys, self.feerate_per_kw, htlcs_without_source),
+ commitment_tx: LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, msg.signature.clone(), &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), &their_funding_pubkey, local_keys, self.feerate_per_kw, htlcs_without_source),
htlc_outputs: htlcs_and_sigs
}]
};
ChannelValueStat {
value_to_self_msat: self.value_to_self_msat,
channel_value_msat: self.channel_value_satoshis * 1000,
- channel_reserve_msat: self.their_channel_reserve_satoshis * 1000,
+ channel_reserve_msat: self.local_channel_reserve_satoshis * 1000,
pending_outbound_htlcs_amount_msat: self.pending_outbound_htlcs.iter().map(|ref h| h.amount_msat).sum::<u64>(),
pending_inbound_htlcs_amount_msat: self.pending_inbound_htlcs.iter().map(|ref h| h.amount_msat).sum::<u64>(),
holding_cell_outbound_amount_msat: {
// Methods to get unprompted messages to send to the remote end (or where we already returned
// something in the handler for the message that prompted this message):
- pub fn get_open_channel<F: Deref>(&self, chain_hash: Sha256dHash, fee_estimator: &F) -> msgs::OpenChannel
+ pub fn get_open_channel<F: Deref>(&self, chain_hash: BlockHash, fee_estimator: &F) -> msgs::OpenChannel
where F::Target: FeeEstimator
{
if !self.channel_outbound {
push_msat: self.channel_value_satoshis * 1000 - self.value_to_self_msat,
dust_limit_satoshis: self.our_dust_limit_satoshis,
max_htlc_value_in_flight_msat: Channel::<ChanSigner>::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis),
- channel_reserve_satoshis: Channel::<ChanSigner>::get_our_channel_reserve_satoshis(self.channel_value_satoshis),
+ channel_reserve_satoshis: Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis),
htlc_minimum_msat: self.our_htlc_minimum_msat,
feerate_per_kw: fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) as u32,
to_self_delay: self.our_to_self_delay,
temporary_channel_id: self.channel_id,
dust_limit_satoshis: self.our_dust_limit_satoshis,
max_htlc_value_in_flight_msat: Channel::<ChanSigner>::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis),
- channel_reserve_satoshis: Channel::<ChanSigner>::get_our_channel_reserve_satoshis(self.channel_value_satoshis),
+ channel_reserve_satoshis: Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis),
htlc_minimum_msat: self.our_htlc_minimum_msat,
minimum_depth: self.minimum_depth,
to_self_delay: self.our_to_self_delay,
/// closing).
/// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see
/// https://github.com/lightningnetwork/lightning-rfc/issues/468
- pub fn get_channel_announcement(&self, our_node_id: PublicKey, chain_hash: Sha256dHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), ChannelError> {
+ pub fn get_channel_announcement(&self, our_node_id: PublicKey, chain_hash: BlockHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), ChannelError> {
if !self.config.announced_channel {
return Err(ChannelError::Ignore("Channel is not available for public announcements"));
}
let our_bitcoin_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key());
let msg = msgs::UnsignedChannelAnnouncement {
- features: ChannelFeatures::supported(),
+ features: ChannelFeatures::known(),
chain_hash: chain_hash,
short_channel_id: self.get_short_channel_id().unwrap(),
node_id_1: if were_node_one { our_node_id } else { self.get_their_node_id() },
return Err(ChannelError::Ignore("Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
}
- // Check self.their_channel_reserve_satoshis (the amount we must keep as
- // reserve for them to have something to claim if we misbehave)
- if self.value_to_self_msat < self.their_channel_reserve_satoshis * 1000 + amount_msat + htlc_outbound_value_msat {
- return Err(ChannelError::Ignore("Cannot send value that would put us over their reserve value"));
+ // Check self.local_channel_reserve_satoshis (the amount we must keep as
+ // reserve for the remote to have something to claim if we misbehave)
+ if self.value_to_self_msat < self.local_channel_reserve_satoshis * 1000 + amount_msat + htlc_outbound_value_msat {
+ return Err(ChannelError::Ignore("Cannot send value that would put us under local channel reserve value"));
}
// Now update local state:
self.their_dust_limit_satoshis.write(writer)?;
self.our_dust_limit_satoshis.write(writer)?;
self.their_max_htlc_value_in_flight_msat.write(writer)?;
- self.their_channel_reserve_satoshis.write(writer)?;
+ self.local_channel_reserve_satoshis.write(writer)?;
self.their_htlc_minimum_msat.write(writer)?;
self.our_htlc_minimum_msat.write(writer)?;
self.their_to_self_delay.write(writer)?;
let their_dust_limit_satoshis = Readable::read(reader)?;
let our_dust_limit_satoshis = Readable::read(reader)?;
let their_max_htlc_value_in_flight_msat = Readable::read(reader)?;
- let their_channel_reserve_satoshis = Readable::read(reader)?;
+ let local_channel_reserve_satoshis = Readable::read(reader)?;
let their_htlc_minimum_msat = Readable::read(reader)?;
let our_htlc_minimum_msat = Readable::read(reader)?;
let their_to_self_delay = Readable::read(reader)?;
their_dust_limit_satoshis,
our_dust_limit_satoshis,
their_max_htlc_value_in_flight_msat,
- their_channel_reserve_satoshis,
+ local_channel_reserve_satoshis,
their_htlc_minimum_msat,
our_htlc_minimum_msat,
their_to_self_delay,
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::blockdata::opcodes;
use bitcoin::network::constants::Network;
- use bitcoin_hashes::hex::FromHex;
+ use bitcoin::hashes::hex::FromHex;
use hex;
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys};
use util::enforcing_trait_impls::EnforcingChannelKeys;
use util::test_utils;
use util::logger::Logger;
- use secp256k1::{Secp256k1, Message, Signature, All};
- use secp256k1::key::{SecretKey,PublicKey};
- use bitcoin_hashes::sha256::Hash as Sha256;
- use bitcoin_hashes::sha256d::Hash as Sha256dHash;
- use bitcoin_hashes::hash160::Hash as Hash160;
- use bitcoin_hashes::Hash;
+ use bitcoin::secp256k1::{Secp256k1, Message, Signature, All};
+ use bitcoin::secp256k1::key::{SecretKey,PublicKey};
+ use bitcoin::hashes::sha256::Hash as Sha256;
+ use bitcoin::hashes::Hash;
+ use bitcoin::hash_types::{Txid, WPubkeyHash};
use std::sync::Arc;
use rand::{thread_rng,Rng};
fn get_destination_script(&self) -> Script {
let secp_ctx = Secp256k1::signing_only();
let channel_monitor_claim_key = SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap();
- let our_channel_monitor_claim_key_hash = Hash160::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
+ let our_channel_monitor_claim_key_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &channel_monitor_claim_key).serialize());
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script()
}
// Create Node B's channel by receiving Node A's open_channel message
let open_channel_msg = node_a_chan.get_open_channel(genesis_block(network).header.bitcoin_hash(), &&feeest);
let node_b_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[7; 32]).unwrap());
- let mut node_b_chan = Channel::<EnforcingChannelKeys>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::supported(), &open_channel_msg, 7, logger, &config).unwrap();
+ let mut node_b_chan = Channel::<EnforcingChannelKeys>::new_from_req(&&feeest, &&keys_provider, node_b_node_id, InitFeatures::known(), &open_channel_msg, 7, logger, &config).unwrap();
// Node B --> Node A: accept channel
let accept_channel_msg = node_b_chan.get_accept_channel();
- node_a_chan.accept_channel(&accept_channel_msg, &config, InitFeatures::supported()).unwrap();
+ node_a_chan.accept_channel(&accept_channel_msg, &config, InitFeatures::known()).unwrap();
// Node A --> Node B: funding created
let output_script = node_a_chan.get_funding_redeemscript();
chan.their_to_self_delay = 144;
chan.our_dust_limit_satoshis = 546;
- let funding_info = OutPoint::new(Sha256dHash::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0);
+ let funding_info = OutPoint::new(Txid::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), 0);
chan.funding_txo = Some(funding_info);
let their_pubkeys = ChannelPublicKeys {
macro_rules! test_commitment {
( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr, {
$( { $htlc_idx: expr, $their_htlc_sig_hex: expr, $our_htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
- } ) => {
+ } ) => { {
unsigned_tx = {
let mut res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
let htlcs = res.2.drain(..)
})*
assert_eq!(unsigned_tx.1.len(), per_htlc.len());
- localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey(), keys.clone(), chan.feerate_per_kw, per_htlc);
+ localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), their_signature.clone(), &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey(), keys.clone(), chan.feerate_per_kw, per_htlc);
let local_sig = chan_keys.sign_local_commitment(&localtx, &chan.secp_ctx).unwrap();
- localtx.add_local_sig(&redeemscript, local_sig);
- assert_eq!(serialize(localtx.with_valid_witness())[..],
+ assert_eq!(serialize(&localtx.add_local_sig(&redeemscript, local_sig))[..],
hex::decode($tx_hex).unwrap()[..]);
+ let htlc_sigs = chan_keys.sign_local_commitment_htlc_transactions(&localtx, chan.their_to_self_delay, &chan.secp_ctx).unwrap();
+ let mut htlc_sig_iter = localtx.per_htlc.iter().zip(htlc_sigs.iter().enumerate());
+
$({
let remote_signature = Signature::from_der(&hex::decode($their_htlc_sig_hex).unwrap()[..]).unwrap();
assert!(preimage.is_some());
}
- chan_keys.sign_htlc_transaction(&mut localtx, $htlc_idx, preimage, chan.their_to_self_delay, &chan.secp_ctx);
+ let mut htlc_sig = htlc_sig_iter.next().unwrap();
+ while (htlc_sig.1).1.is_none() { htlc_sig = htlc_sig_iter.next().unwrap(); }
+ assert_eq!((htlc_sig.0).0.transaction_output_index, Some($htlc_idx));
- assert_eq!(serialize(localtx.htlc_with_valid_witness($htlc_idx).as_ref().unwrap())[..],
+ assert_eq!(serialize(&localtx.get_signed_htlc_tx((htlc_sig.1).0, &(htlc_sig.1).1.unwrap(), &preimage, chan.their_to_self_delay))[..],
hex::decode($htlc_tx_hex).unwrap()[..]);
})*
- }
+ loop {
+ let htlc_sig = htlc_sig_iter.next();
+ if htlc_sig.is_none() { break; }
+ assert!((htlc_sig.unwrap().1).1.is_none());
+ }
+ } }
}
{