Added config interface to allow users to specify channel limits 2018-10-169-redux
authorSchalk van Heerden <swvheerden@gmail.com>
Wed, 31 Oct 2018 18:51:39 +0000 (14:51 -0400)
committerMatt Corallo <git@bluematt.me>
Wed, 31 Oct 2018 19:45:30 +0000 (15:45 -0400)
fuzz/fuzz_targets/full_stack_target.rs
src/ln/channel.rs
src/ln/channelmanager.rs
src/util/config.rs [new file with mode: 0644]
src/util/mod.rs

index ecadd212d5aa99a69d950ae2673f5188e857a17e..19b3e843ae6706c7ef99d095b76b0c736b8a22c5 100644 (file)
@@ -24,6 +24,7 @@ use lightning::util::events::{EventsProvider,Event};
 use lightning::util::reset_rng_state;
 use lightning::util::logger::Logger;
 use lightning::util::sha2::Sha256;
+use lightning::util::config::UserConfig;
 
 mod utils;
 
@@ -305,7 +306,11 @@ pub fn do_test(data: &[u8], logger: &Arc<Logger>) {
        let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone(), Arc::clone(&logger));
 
        let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone() });
-       let channelmanager = ChannelManager::new(slice_to_be32(get_slice!(4)), get_slice!(1)[0] != 0, Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone()).unwrap();
+       let mut config = UserConfig::new();
+       config.channel_options.fee_proportional_millionths =  slice_to_be32(get_slice!(4));
+       config.channel_options.announced_channel = get_slice!(1)[0] != 0;
+       config.channel_limits.min_dust_limit_satoshis = 0;
+       let channelmanager = ChannelManager::new(Network::Bitcoin, fee_est.clone(), monitor.clone(), watch.clone(), broadcast.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap();
        let router = Arc::new(Router::new(PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()), watch.clone(), Arc::clone(&logger)));
 
        let peers = RefCell::new([false; 256]);
index 4ab42f75a5fab863ef88e1053456308e8325b5ef..1fbc605bb3baa34491bf0d4d034f0a3de805503f 100644 (file)
@@ -28,6 +28,7 @@ use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor};
 use util::sha2::Sha256;
 use util::logger::Logger;
 use util::errors::APIError;
+use util::config::{UserConfig,ChannelConfig};
 
 use std;
 use std::default::Default;
@@ -230,13 +231,14 @@ const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
 // calling channel_id() before we're set up or things like get_outbound_funding_signed on an
 // inbound channel.
 pub(super) struct Channel {
+       config: ChannelConfig,
+
        user_id: u64,
 
        channel_id: [u8; 32],
        channel_state: u32,
        channel_outbound: bool,
        secp_ctx: Secp256k1<secp256k1::All>,
-       announce_publicly: bool,
        channel_value_satoshis: u64,
 
        local_keys: ChannelKeys,
@@ -415,7 +417,7 @@ impl Channel {
        }
 
        // Constructors:
-       pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface>, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, announce_publicly: bool, user_id: u64, logger: Arc<Logger>) -> Result<Channel, APIError> {
+       pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface>, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel, APIError> {
                let chan_keys = keys_provider.get_channel_keys(false);
 
                if channel_value_satoshis >= MAX_FUNDING_SATOSHIS {
@@ -441,12 +443,12 @@ impl Channel {
 
                Ok(Channel {
                        user_id: user_id,
+                       config: config.channel_options.clone(),
 
                        channel_id: rng::rand_u832(),
                        channel_state: ChannelState::OurInitSent as u32,
                        channel_outbound: true,
                        secp_ctx: secp_ctx,
-                       announce_publicly: announce_publicly,
                        channel_value_satoshis: channel_value_satoshis,
 
                        local_keys: chan_keys,
@@ -526,8 +528,9 @@ impl Channel {
 
        /// Creates a new channel from a remote sides' request for one.
        /// Assumes chain_hash has already been checked and corresponds with what we expect!
-       pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface>, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, require_announce: bool, allow_announce: bool, logger: Arc<Logger>) -> Result<Channel, ChannelError> {
+       pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface>, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel, ChannelError> {
                let chan_keys = keys_provider.get_channel_keys(true);
+               let mut local_config = (*config).channel_options.clone();
 
                // Check sanity of message fields:
                if msg.funding_satoshis >= MAX_FUNDING_SATOSHIS {
@@ -560,22 +563,46 @@ impl Channel {
                        return Err(ChannelError::Close("max_accpted_htlcs > 483"));
                }
 
+               // Now check against optional parameters as set by config...
+               if msg.funding_satoshis < config.channel_limits.min_funding_satoshis {
+                       return Err(ChannelError::Close("funding satoshis is less than the user specified limit"));
+               }
+               if msg.htlc_minimum_msat > config.channel_limits.max_htlc_minimum_msat {
+                       return Err(ChannelError::Close("htlc minimum msat is higher than the user specified limit"));
+               }
+               if msg.max_htlc_value_in_flight_msat < config.channel_limits.min_max_htlc_value_in_flight_msat {
+                       return Err(ChannelError::Close("max htlc value in flight msat is less than the user specified limit"));
+               }
+               if msg.channel_reserve_satoshis > config.channel_limits.max_channel_reserve_satoshis {
+                       return Err(ChannelError::Close("channel reserve satoshis is higher than the user specified limit"));
+               }
+               if msg.max_accepted_htlcs < config.channel_limits.min_max_accepted_htlcs {
+                       return Err(ChannelError::Close("max accepted htlcs is less than the user specified limit"));
+               }
+               if msg.dust_limit_satoshis < config.channel_limits.min_dust_limit_satoshis {
+                       return Err(ChannelError::Close("dust limit satoshis is less than the user specified limit"));
+               }
+               if msg.dust_limit_satoshis > config.channel_limits.max_dust_limit_satoshis {
+                       return Err(ChannelError::Close("dust limit satoshis is greater than the user specified limit"));
+               }
+
                // 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(ChannelError::Close("Peer tried to open unannounced channel, but we require public ones"));
-               }
-               if !allow_announce && their_announce {
-                       return Err(ChannelError::Close("Peer tried to open announced channel, but we require private ones"));
+               if config.channel_limits.force_announced_channel_preference {
+                       if local_config.announced_channel != their_announce {
+                               return Err(ChannelError::Close("Peer tried to open channel but their announcement preference is different from ours"));
+                       }
                }
+               // we either accept their preference or the preferences match
+               local_config.announced_channel = their_announce;
 
                let background_feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background);
 
                let our_dust_limit_satoshis = Channel::derive_our_dust_limit_satoshis(background_feerate);
                let our_channel_reserve_satoshis = Channel::get_our_channel_reserve_satoshis(msg.funding_satoshis);
                if our_channel_reserve_satoshis < our_dust_limit_satoshis {
-                       return Err(ChannelError::Close("Suitalbe channel reserve not found. aborting"));
+                       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"));
@@ -606,12 +633,12 @@ impl Channel {
 
                let mut chan = Channel {
                        user_id: user_id,
+                       config: local_config,
 
                        channel_id: msg.temporary_channel_id,
                        channel_state: (ChannelState::OurInitSent as u32) | (ChannelState::TheirInitSent as u32),
                        channel_outbound: false,
                        secp_ctx: secp_ctx,
-                       announce_publicly: their_announce,
 
                        local_keys: chan_keys,
                        shutdown_pubkey: keys_provider.get_shutdown_pubkey(),
@@ -1262,7 +1289,7 @@ impl Channel {
 
        // Message handlers:
 
-       pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel) -> Result<(), ChannelError> {
+       pub fn accept_channel(&mut self, msg: &msgs::AcceptChannel, config: &UserConfig) -> Result<(), ChannelError> {
                // Check sanity of message fields:
                if !self.channel_outbound {
                        return Err(ChannelError::Close("Got an accept_channel message from an inbound peer"));
@@ -1298,14 +1325,28 @@ impl Channel {
                        return Err(ChannelError::Close("max_accpted_htlcs > 483"));
                }
 
-               // TODO: Optional additional constraints mentioned in the spec
-               // MAY fail the channel if
-               // funding_satoshi is too small
-               // htlc_minimum_msat too large
-               // max_htlc_value_in_flight_msat too small
-               // channel_reserve_satoshis too large
-               // max_accepted_htlcs too small
-               // dust_limit_satoshis too small
+               // Now check against optional parameters as set by config...
+               if msg.htlc_minimum_msat > config.channel_limits.max_htlc_minimum_msat {
+                       return Err(ChannelError::Close("htlc minimum msat is higher than the user specified limit"));
+               }
+               if msg.max_htlc_value_in_flight_msat < config.channel_limits.min_max_htlc_value_in_flight_msat {
+                       return Err(ChannelError::Close("max htlc value in flight msat is less than the user specified limit"));
+               }
+               if msg.channel_reserve_satoshis > config.channel_limits.max_channel_reserve_satoshis {
+                       return Err(ChannelError::Close("channel reserve satoshis is higher than the user specified limit"));
+               }
+               if msg.max_accepted_htlcs < config.channel_limits.min_max_accepted_htlcs {
+                       return Err(ChannelError::Close("max accepted htlcs is less than the user specified limit"));
+               }
+               if msg.dust_limit_satoshis < config.channel_limits.min_dust_limit_satoshis {
+                       return Err(ChannelError::Close("dust limit satoshis is less than the user specified limit"));
+               }
+               if msg.dust_limit_satoshis > config.channel_limits.max_dust_limit_satoshis {
+                       return Err(ChannelError::Close("dust limit satoshis is greater than the user specified limit"));
+               }
+               if msg.minimum_depth > config.channel_limits.max_minimum_depth {
+                       return Err(ChannelError::Close("We consider the minimum depth to be unreasonably large"));
+               }
 
                self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint);
 
@@ -2571,6 +2612,10 @@ impl Channel {
                self.channel_value_satoshis
        }
 
+       pub fn get_fee_proportional_millionths(&self) -> u32 {
+               self.config.fee_proportional_millionths
+       }
+
        #[cfg(test)]
        pub fn get_feerate(&self) -> u64 {
                self.feerate_per_kw
@@ -2624,7 +2669,7 @@ impl Channel {
        }
 
        pub fn should_announce(&self) -> bool {
-               self.announce_publicly
+               self.config.announced_channel
        }
 
        pub fn is_outbound(&self) -> bool {
@@ -2823,7 +2868,7 @@ impl Channel {
                        delayed_payment_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.delayed_payment_base_key),
                        htlc_basepoint: PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.htlc_base_key),
                        first_per_commitment_point: PublicKey::from_secret_key(&self.secp_ctx, &local_commitment_secret),
-                       channel_flags: if self.announce_publicly {1} else {0},
+                       channel_flags: if self.config.announced_channel {1} else {0},
                        shutdown_scriptpubkey: None,
                }
        }
@@ -2927,7 +2972,7 @@ impl Channel {
        /// 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> {
-               if !self.announce_publicly {
+               if !self.config.announced_channel {
                        return Err(ChannelError::Ignore("Channel is not available for public announcements"));
                }
                if self.channel_state & (ChannelState::ChannelFunded as u32) == 0 {
@@ -3303,11 +3348,11 @@ impl Writeable for Channel {
                writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
 
                self.user_id.write(writer)?;
+               self.config.write(writer)?;
 
                self.channel_id.write(writer)?;
                (self.channel_state | ChannelState::PeerDisconnected as u32).write(writer)?;
                self.channel_outbound.write(writer)?;
-               self.announce_publicly.write(writer)?;
                self.channel_value_satoshis.write(writer)?;
 
                self.local_keys.write(writer)?;
@@ -3506,11 +3551,11 @@ impl<R : ::std::io::Read> ReadableArgs<R, Arc<Logger>> for Channel {
                }
 
                let user_id = Readable::read(reader)?;
+               let config: ChannelConfig = Readable::read(reader)?;
 
                let channel_id = Readable::read(reader)?;
                let channel_state = Readable::read(reader)?;
                let channel_outbound = Readable::read(reader)?;
-               let announce_publicly = Readable::read(reader)?;
                let channel_value_satoshis = Readable::read(reader)?;
 
                let local_keys = Readable::read(reader)?;
@@ -3675,11 +3720,11 @@ impl<R : ::std::io::Read> ReadableArgs<R, Arc<Logger>> for Channel {
                Ok(Channel {
                        user_id,
 
+                       config,
                        channel_id,
                        channel_state,
                        channel_outbound,
                        secp_ctx: Secp256k1::new(),
-                       announce_publicly,
                        channel_value_satoshis,
 
                        local_keys,
@@ -3766,6 +3811,7 @@ mod tests {
        use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
        use chain::keysinterface::KeysInterface;
        use chain::transaction::OutPoint;
+       use util::config::UserConfig;
        use util::test_utils;
        use util::logger::Logger;
        use secp256k1::{Secp256k1,Message,Signature};
@@ -3832,7 +3878,9 @@ mod tests {
                let keys_provider: Arc<KeysInterface> = Arc::new(Keys { chan_keys });
 
                let their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &[42; 32]).unwrap());
-               let mut chan = Channel::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, false, 42, Arc::clone(&logger)).unwrap(); // Nothing uses their network key in this test
+               let mut config = UserConfig::new();
+               config.channel_options.announced_channel = false;
+               let mut chan = Channel::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test
                chan.their_to_self_delay = 144;
                chan.our_dust_limit_satoshis = 546;
 
index 74e0226b4be760efe6b47c75b140cc8e93a7c81a..ed69e8a033f1aed61cc14c305a80fe4793f14457 100644 (file)
@@ -28,6 +28,7 @@ use ln::router::{Route,RouteHop};
 use ln::msgs;
 use ln::msgs::{ChannelMessageHandler, DecodeError, HandleError};
 use chain::keysinterface::KeysInterface;
+use util::config::UserConfig;
 use util::{byte_utils, events, internal_traits, rng};
 use util::sha2::Sha256;
 use util::ser::{Readable, ReadableArgs, Writeable, Writer};
@@ -320,14 +321,13 @@ const ERR: () = "You need at least 32 bit pointers (well, usize, but we'll assum
 /// block_connected() to step towards your best block) upon deserialization before using the
 /// object!
 pub struct ChannelManager {
+       default_configuration: UserConfig,
        genesis_hash: Sha256dHash,
        fee_estimator: Arc<FeeEstimator>,
        monitor: Arc<ManyChannelMonitor>,
        chain_monitor: Arc<ChainWatchInterface>,
        tx_broadcaster: Arc<BroadcasterInterface>,
 
-       announce_channels_publicly: bool,
-       fee_proportional_millionths: u32,
        latest_block_height: AtomicUsize,
        last_block_hash: Mutex<Sha256dHash>,
        secp_ctx: Secp256k1<secp256k1::All>,
@@ -411,22 +411,20 @@ impl ChannelManager {
        /// This is the main "logic hub" for all channel-related actions, and implements
        /// ChannelMessageHandler.
        ///
-       /// fee_proportional_millionths is an optional fee to charge any payments routed through us.
        /// Non-proportional fees are fixed according to our risk using the provided fee estimator.
        ///
        /// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`!
-       pub fn new(fee_proportional_millionths: u32, announce_channels_publicly: bool, network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, chain_monitor: Arc<ChainWatchInterface>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>, keys_manager: Arc<KeysInterface>) -> Result<Arc<ChannelManager>, secp256k1::Error> {
+       pub fn new(network: Network, feeest: Arc<FeeEstimator>, monitor: Arc<ManyChannelMonitor>, chain_monitor: Arc<ChainWatchInterface>, tx_broadcaster: Arc<BroadcasterInterface>, logger: Arc<Logger>,keys_manager: Arc<KeysInterface>, config: UserConfig) -> Result<Arc<ChannelManager>, secp256k1::Error> {
                let secp_ctx = Secp256k1::new();
 
                let res = Arc::new(ChannelManager {
+                       default_configuration: config.clone(),
                        genesis_hash: genesis_block(network).header.bitcoin_hash(),
                        fee_estimator: feeest.clone(),
                        monitor: monitor.clone(),
                        chain_monitor,
                        tx_broadcaster,
 
-                       announce_channels_publicly,
-                       fee_proportional_millionths,
                        latest_block_height: AtomicUsize::new(0), //TODO: Get an init value
                        last_block_hash: Mutex::new(Default::default()),
                        secp_ctx,
@@ -470,7 +468,7 @@ impl ChannelManager {
                        return Err(APIError::APIMisuseError { err: "channel_value must be at least 1000 satoshis" });
                }
 
-               let channel = Channel::new_outbound(&*self.fee_estimator, &self.keys_manager, their_network_key, channel_value_satoshis, push_msat, self.announce_channels_publicly, user_id, Arc::clone(&self.logger))?;
+               let channel = Channel::new_outbound(&*self.fee_estimator, &self.keys_manager, their_network_key, channel_value_satoshis, push_msat, user_id, Arc::clone(&self.logger), &self.default_configuration)?;
                let res = channel.get_open_channel(self.genesis_hash.clone(), &*self.fee_estimator);
 
                let _ = self.total_consistency_lock.read().unwrap();
@@ -1076,7 +1074,7 @@ impl ChannelManager {
                                        if *amt_to_forward < chan.get_their_htlc_minimum_msat() { // amount_below_minimum
                                                break Some(("HTLC amount was below the htlc_minimum_msat", 0x1000 | 11, Some(self.get_channel_update(chan).unwrap())));
                                        }
-                                       let fee = amt_to_forward.checked_mul(self.fee_proportional_millionths as u64).and_then(|prop_fee| { (prop_fee / 1000000).checked_add(chan.get_our_fee_base_msat(&*self.fee_estimator) as u64) });
+                                       let fee = amt_to_forward.checked_mul(chan.get_fee_proportional_millionths() as u64).and_then(|prop_fee| { (prop_fee / 1000000).checked_add(chan.get_our_fee_base_msat(&*self.fee_estimator) as u64) });
                                        if fee.is_none() || msg.amount_msat < fee.unwrap() || (msg.amount_msat - fee.unwrap()) < *amt_to_forward { // fee_insufficient
                                                break Some(("Prior hop has deviated from specified fees parameters or origin node has obsolete ones", 0x1000 | 12, Some(self.get_channel_update(chan).unwrap())));
                                        }
@@ -1130,7 +1128,7 @@ impl ChannelManager {
                        cltv_expiry_delta: CLTV_EXPIRY_DELTA,
                        htlc_minimum_msat: chan.get_our_htlc_minimum_msat(),
                        fee_base_msat: chan.get_our_fee_base_msat(&*self.fee_estimator),
-                       fee_proportional_millionths: self.fee_proportional_millionths,
+                       fee_proportional_millionths: chan.get_fee_proportional_millionths(),
                        excess_data: Vec::new(),
                };
 
@@ -1687,7 +1685,7 @@ impl ChannelManager {
                        return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash", msg.temporary_channel_id.clone()));
                }
 
-               let channel = Channel::new_from_req(&*self.fee_estimator, &self.keys_manager, their_node_id.clone(), msg, 0, false, self.announce_channels_publicly, Arc::clone(&self.logger))
+               let channel = Channel::new_from_req(&*self.fee_estimator, &self.keys_manager, their_node_id.clone(), msg, 0, Arc::clone(&self.logger), &self.default_configuration)
                        .map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id))?;
                let mut channel_state_lock = self.channel_state.lock().unwrap();
                let channel_state = channel_state_lock.borrow_parts();
@@ -1713,7 +1711,7 @@ impl ChannelManager {
                                                //TODO: see issue #153, need a consistent behavior on obnoxious behavior from random node
                                                return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.temporary_channel_id));
                                        }
-                                       chan.accept_channel(&msg)
+                                       chan.accept_channel(&msg, &self.default_configuration)
                                                .map_err(|e| MsgHandleErrInternal::from_chan_maybe_close(e, msg.temporary_channel_id))?;
                                        (chan.get_value_satoshis(), chan.get_funding_redeemscript().to_v0_p2wsh(), chan.get_user_id())
                                },
@@ -2963,8 +2961,6 @@ impl Writeable for ChannelManager {
                writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
 
                self.genesis_hash.write(writer)?;
-               self.announce_channels_publicly.write(writer)?;
-               self.fee_proportional_millionths.write(writer)?;
                (self.latest_block_height.load(Ordering::Acquire) as u32).write(writer)?;
                self.last_block_hash.lock().unwrap().write(writer)?;
 
@@ -3046,7 +3042,9 @@ pub struct ChannelManagerReadArgs<'a> {
        /// The Logger for use in the ChannelManager and which may be used to log information during
        /// deserialization.
        pub logger: Arc<Logger>,
-
+       /// Default settings used for new channels. Any existing channels will continue to use the
+       /// runtime settings which were stored when the ChannelManager was serialized.
+       pub default_config: UserConfig,
 
        /// A map from channel funding outpoints to ChannelMonitors for those channels (ie
        /// value.get_funding_txo() should be the key).
@@ -3070,8 +3068,6 @@ impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (S
                }
 
                let genesis_hash: Sha256dHash = Readable::read(reader)?;
-               let announce_channels_publicly: bool = Readable::read(reader)?;
-               let fee_proportional_millionths: u32 = Readable::read(reader)?;
                let latest_block_height: u32 = Readable::read(reader)?;
                let last_block_hash: Sha256dHash = Readable::read(reader)?;
 
@@ -3144,8 +3140,6 @@ impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (S
                        chain_monitor: args.chain_monitor,
                        tx_broadcaster: args.tx_broadcaster,
 
-                       announce_channels_publicly,
-                       fee_proportional_millionths,
                        latest_block_height: AtomicUsize::new(latest_block_height as usize),
                        last_block_hash: Mutex::new(last_block_hash),
                        secp_ctx: Secp256k1::new(),
@@ -3164,6 +3158,7 @@ impl<'a, R : ::std::io::Read> ReadableArgs<R, ChannelManagerReadArgs<'a>> for (S
                        total_consistency_lock: RwLock::new(()),
                        keys_manager: args.keys_manager,
                        logger: args.logger,
+                       default_configuration: args.default_config,
                };
 
                for close_res in closed_channels.drain(..) {
@@ -3193,6 +3188,7 @@ mod tests {
        use util::errors::APIError;
        use util::logger::Logger;
        use util::ser::{Writeable, Writer, ReadableArgs};
+       use util::config::UserConfig;
 
        use bitcoin::util::hash::Sha256dHash;
        use bitcoin::blockdata::block::{Block, BlockHeader};
@@ -4057,7 +4053,10 @@ mod tests {
                        rng.fill_bytes(&mut seed);
                        let keys_manager = Arc::new(keysinterface::KeysManager::new(&seed, Network::Testnet, Arc::clone(&logger)));
                        let chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone()));
-                       let node = ChannelManager::new(0, true, Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger), keys_manager.clone()).unwrap();
+                       let mut config = UserConfig::new();
+                       config.channel_options.announced_channel = true;
+                       config.channel_limits.force_announced_channel_preference = false;
+                       let node = ChannelManager::new(Network::Testnet, feeest.clone(), chan_monitor.clone(), chain_monitor.clone(), tx_broadcaster.clone(), Arc::clone(&logger), keys_manager.clone(), config).unwrap();
                        let router = Router::new(PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()), chain_monitor.clone(), Arc::clone(&logger));
                        nodes.push(Node { chain_monitor, tx_broadcaster, chan_monitor, node, router, node_seed: seed,
                                network_payment_count: payment_count.clone(),
@@ -6892,11 +6891,13 @@ mod tests {
                assert!(chan_0_monitor_read.is_empty());
 
                let mut nodes_0_read = &nodes_0_serialized[..];
+               let config = UserConfig::new();
                let keys_manager = Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
                let (_, nodes_0_deserialized) = {
                        let mut channel_monitors = HashMap::new();
                        channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
                        <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+                               default_config: config,
                                keys_manager,
                                fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
                                monitor: nodes[0].chan_monitor.clone(),
@@ -6961,6 +6962,7 @@ mod tests {
                        let mut channel_monitors = HashMap::new();
                        channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
                        <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+                               default_config: UserConfig::new(),
                                keys_manager,
                                fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
                                monitor: nodes[0].chan_monitor.clone(),
@@ -7021,6 +7023,7 @@ mod tests {
                let mut nodes_0_read = &nodes_0_serialized[..];
                let keys_manager = Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
                let (_, nodes_0_deserialized) = <(Sha256dHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
+                       default_config: UserConfig::new(),
                        keys_manager,
                        fee_estimator: Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 }),
                        monitor: nodes[0].chan_monitor.clone(),
diff --git a/src/util/config.rs b/src/util/config.rs
new file mode 100644 (file)
index 0000000..a3abdbe
--- /dev/null
@@ -0,0 +1,127 @@
+//! Various user-configurable channel limits and settings which ChannelManager
+//! applies for you.
+
+/// Top-level config which holds ChannelHandshakeLimits and ChannelConfig.
+#[derive(Clone, Debug)]
+pub struct UserConfig {
+       /// Limits applied during channel creation.
+       pub channel_limits: ChannelHandshakeLimits,
+       /// Channel config which affects behavior during channel lifetime.
+       pub channel_options: ChannelConfig,
+}
+
+impl UserConfig {
+       /// Provides sane defaults for most configurations (but with 0 relay fees!)
+       pub fn new() -> Self{
+               UserConfig {
+                       channel_limits: ChannelHandshakeLimits::new(),
+                       channel_options: ChannelConfig::new(),
+               }
+       }
+}
+
+/// Optional channel limits which are applied during channel creation.
+///
+/// These limits are only applied to our counterparty's limits, not our own.
+///
+/// Use 0/<type>::max_value() as appropriate to skip checking.
+#[derive(Copy, Clone, Debug)]
+pub struct ChannelHandshakeLimits {
+       /// Minimum allowed satoshis when a channel is funded, this is supplied by the sender and so
+       /// only applies to inbound channels.
+       pub min_funding_satoshis: u64,
+       /// The remote node sets a limit on the minimum size of HTLCs we can send to them. This allows
+       /// you to limit the maximum minimum-size they can require.
+       pub max_htlc_minimum_msat: u64,
+       /// The remote node sets a limit on the maximum value of pending HTLCs to them at any given
+       /// time to limit their funds exposure to HTLCs. This allows you to set a minimum such value.
+       pub min_max_htlc_value_in_flight_msat: u64,
+       /// The remote node will require we keep a certain amount in direct payment to ourselves at all
+       /// time, ensuring that we are able to be punished if we broadcast an old state. This allows to
+       /// you limit the amount which we will have to keep to ourselves (and cannot use for HTLCs).
+       pub max_channel_reserve_satoshis: u64,
+       /// The remote node sets a limit on the maximum number of pending HTLCs to them at any given
+       /// time. This allows you to set a minimum such value.
+       pub min_max_accepted_htlcs: u16,
+       /// Outputs below a certain value will not be added to on-chain transactions. The dust value is
+       /// required to always be higher than this value so this only applies to HTLC outputs (and
+       /// potentially to-self outputs before any payments have been made).
+       /// Thus, HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain.
+       /// This setting allows you to set a minimum dust limit for their commitment transactions,
+       /// reflecting the reality that tiny outputs are not considered standard transactions and will
+       /// not propagate through the Bitcoin network.
+       /// Defaults to 546, or the current dust limit on the Bitcoin network.
+       pub min_dust_limit_satoshis: u64,
+       /// Maximum allowed threshold above which outputs will not be generated in their commitment
+       /// transactions.
+       /// HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain.
+       pub max_dust_limit_satoshis: u64,
+       /// Before a channel is usable the funding transaction will need to be confirmed by at least a
+       /// certain number of blocks, specified by the node which is not the funder (as the funder can
+       /// assume they aren't going to double-spend themselves).
+       /// This config allows you to set a limit on the maximum amount of time to wait. Defaults to
+       /// 144 blocks or roughly one day and only applies to outbound channels.
+       pub max_minimum_depth: u32,
+       /// Set to force the incoming channel to match our announced channel preference in
+       /// ChannelConfig.
+       /// Defaults to true to make the default that no announced channels are possible (which is
+       /// appropriate for any nodes which are not online very reliably).
+       pub force_announced_channel_preference: bool,
+}
+
+impl ChannelHandshakeLimits {
+       /// Provides sane defaults for most configurations.
+       ///
+       /// Most additional limits are disabled except those with which specify a default in individual
+       /// field documentation. Note that this may result in barely-usable channels, but since they
+       /// are applied mostly only to incoming channels that's not much of a problem.
+       pub fn new() -> Self {
+               ChannelHandshakeLimits {
+                       min_funding_satoshis: 0,
+                       max_htlc_minimum_msat: <u64>::max_value(),
+                       min_max_htlc_value_in_flight_msat: 0,
+                       max_channel_reserve_satoshis: <u64>::max_value(),
+                       min_max_accepted_htlcs: 0,
+                       min_dust_limit_satoshis: 546,
+                       max_dust_limit_satoshis: <u64>::max_value(),
+                       max_minimum_depth: 144,
+                       force_announced_channel_preference: true,
+               }
+       }
+}
+
+/// Options which apply on a per-channel basis and may change at runtime or based on negotiation
+/// with our counterparty.
+#[derive(Copy, Clone, Debug)]
+pub struct ChannelConfig {
+       /// Amount (in millionths of a satoshi) the channel will charge per transferred satoshi.
+       /// This may be allowed to change at runtime in a later update, however doing so must result in
+       /// update messages sent to notify all nodes of our updated relay fee.
+       pub fee_proportional_millionths: u32,
+       /// Set to announce the channel publicly and notify all nodes that they can route via this
+       /// channel.
+       ///
+       /// This should only be set to true for nodes which expect to be online reliably.
+       ///
+       /// As the node which funds a channel picks this value this will only apply for new outbound
+       /// channels unless ChannelHandshakeLimits::force_announced_channel_preferences is set.
+       ///
+       /// This cannot be changed after the initial channel handshake.
+       pub announced_channel: bool,
+}
+
+impl ChannelConfig {
+       /// Provides sane defaults for most configurations (but with zero relay fees!).
+       pub fn new() -> Self {
+               ChannelConfig {
+                       fee_proportional_millionths: 0,
+                       announced_channel: false,
+               }
+       }
+}
+
+//Add write and readable traits to channelconfig
+impl_writeable!(ChannelConfig, 8+1, {
+       fee_proportional_millionths,
+       announced_channel
+});
index b91b4f25d96fa116ea92b473e0b69c313b178919..842fbea605baba0f89e88d880f305a209c81a068 100644 (file)
@@ -15,8 +15,9 @@ pub(crate) mod ser_macros;
 #[macro_use]
 pub(crate) mod macro_logger;
 
-// Logger has to come after macro_logger for tests to build:
+// These have to come after macro_logger to build
 pub mod logger;
+pub mod config;
 
 #[cfg(feature = "fuzztarget")]
 pub mod sha2;