diff --git a/fuzz/fuzz_targets/full_stack_target.rs b/fuzz/fuzz_targets/full_stack_target.rs index 7f6cf5e1919..a0e0dd0f700 100644 --- a/fuzz/fuzz_targets/full_stack_target.rs +++ b/fuzz/fuzz_targets/full_stack_target.rs @@ -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::configurations::UserConfig; mod utils; @@ -283,7 +284,10 @@ pub fn do_test(data: &[u8], logger: &Arc) { let monitor = channelmonitor::SimpleManyChannelMonitor::new(watch.clone(), broadcast.clone()); 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); + 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]); diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 5c04414a2da..1ec0acc317a 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -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::configurations::{UserConfig,ChannelConfig}; use std; use std::default::Default; @@ -225,18 +226,20 @@ const MULTI_STATE_FLAGS: u32 = (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::PeerDis const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; + // TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking // has been completed, and then turn into a Channel to get compiler-time enforcement of things like // 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, - announce_publicly: bool, channel_value_satoshis: u64, local_keys: ChannelKeys, @@ -391,7 +394,6 @@ impl Channel { } /// Returns a minimum channel reserve value **they** need to maintain - /// /// Guaranteed to return a value no larger than channel_value_satoshis fn get_our_channel_reserve_satoshis(channel_value_satoshis: u64) -> u64 { let (q, _) = channel_value_satoshis.overflowing_div(100); @@ -399,7 +401,14 @@ impl Channel { } fn derive_our_dust_limit_satoshis(at_open_background_feerate: u64) -> u64 { - at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000 //TODO + #[cfg(test)] + { + 547 + } + #[cfg(not(test))] + { + at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000 //TODO + } } fn derive_our_htlc_minimum_msat(_at_open_channel_feerate_per_kw: u64) -> u64 { @@ -419,13 +428,12 @@ impl Channel { } // Constructors: - pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, announce_publicly: bool, user_id: u64, logger: Arc) -> Result { + pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc, config: &UserConfig) -> Result { let chan_keys = keys_provider.get_channel_keys(false); if channel_value_satoshis >= MAX_FUNDING_SATOSHIS { return Err(APIError::APIMisuseError{err: "funding value > 2^24"}); } - if push_msat > channel_value_satoshis * 1000 { return Err(APIError::APIMisuseError{err: "push value > channel value"}); } @@ -445,12 +453,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, @@ -529,8 +537,10 @@ 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, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, require_announce: bool, allow_announce: bool, logger: Arc) -> Result { + pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc, their_node_id: PublicKey, msg: &msgs::OpenChannel, user_id: u64, logger: Arc, config : &UserConfig) -> Result { 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 { @@ -562,23 +572,48 @@ impl Channel { if msg.max_accepted_htlcs > 483 { return Err(ChannelError::Close("max_accpted_htlcs > 483")); } + //optional parameter checking + // MAY fail the channel if + 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 { + println!("{:?}", msg.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")); @@ -609,12 +644,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(), @@ -1264,7 +1299,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")); @@ -1302,16 +1337,10 @@ impl Channel { if msg.max_accepted_htlcs > 483 { 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 - + //Optional user definined limits + if msg.minimum_depth > config.channel_limits.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); self.their_dust_limit_satoshis = msg.dust_limit_satoshis; @@ -2575,6 +2604,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 @@ -2628,7 +2661,7 @@ impl Channel { } pub fn should_announce(&self) -> bool { - self.announce_publicly + self.config.announced_channel } pub fn is_outbound(&self) -> bool { @@ -2827,7 +2860,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, } } @@ -2931,7 +2964,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 { @@ -3307,11 +3340,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)?; @@ -3509,11 +3542,10 @@ impl ReadableArgs> 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)?; @@ -3676,12 +3708,11 @@ impl ReadableArgs> for Channel { Ok(Channel { user_id, - + config, channel_id, channel_state, channel_outbound, secp_ctx: Secp256k1::new(), - announce_publicly, channel_value_satoshis, local_keys, @@ -3813,6 +3844,7 @@ mod tests { #[test] fn outbound_commitment_test() { + use util::configurations::UserConfig; // Test vectors from BOLT 3 Appendix C: let feeest = TestFeeEstimator{fee_est: 15000}; let logger : Arc = Arc::new(test_utils::TestLogger::new()); @@ -3833,7 +3865,9 @@ mod tests { let keys_provider: Arc = 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; diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index f3e152b4d6f..1cdefc7559d 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -28,6 +28,7 @@ use ln::router::{Route,RouteHop}; use ln::msgs; use ln::msgs::{ChannelMessageHandler, DecodeError, HandleError}; use chain::keysinterface::KeysInterface; +use util::configurations::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, monitor: Arc, chain_monitor: Arc, tx_broadcaster: Arc, - announce_channels_publicly: bool, - fee_proportional_millionths: u32, latest_block_height: AtomicUsize, last_block_hash: Mutex, secp_ctx: Secp256k1, @@ -411,22 +411,18 @@ 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, monitor: Arc, chain_monitor: Arc, tx_broadcaster: Arc, logger: Arc, keys_manager: Arc) -> Result, secp256k1::Error> { + pub fn new(network: Network, feeest: Arc, monitor: Arc, chain_monitor: Arc, tx_broadcaster: Arc, logger: Arc,keys_manager: Arc, config : UserConfig) -> Result, 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, @@ -465,7 +461,7 @@ impl ChannelManager { /// /// Raises APIError::APIMisuseError when channel_value_satoshis > 2**24 or push_msat being greater than channel_value_satoshis * 1k pub fn create_channel(&self, their_network_key: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64) -> Result<(), APIError> { - 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(); @@ -1071,7 +1067,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()))); } @@ -1125,7 +1121,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(), }; @@ -1682,7 +1678,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(); @@ -1708,7 +1704,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()) }, @@ -2958,8 +2954,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)?; @@ -3041,6 +3035,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, + /// This is the default settings used by the channel manager to open new channels + /// This also contoins the handshake limits used when accepting new channels + pub default_config : UserConfig, /// A map from channel funding outpoints to ChannelMonitors for those channels (ie @@ -3065,8 +3062,6 @@ impl<'a, R : ::std::io::Read> ReadableArgs> 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)?; @@ -3138,9 +3133,6 @@ impl<'a, R : ::std::io::Read> ReadableArgs> for (S monitor: args.monitor, 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(), @@ -3159,6 +3151,7 @@ impl<'a, R : ::std::io::Read> ReadableArgs> 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(..) { @@ -3188,6 +3181,7 @@ mod tests { use util::errors::APIError; use util::logger::Logger; use util::ser::{Writeable, Writer, ReadableArgs}; + use util::configurations::{UserConfig}; use bitcoin::util::hash::Sha256dHash; use bitcoin::blockdata::block::{Block, BlockHeader}; @@ -4036,6 +4030,8 @@ mod tests { } fn create_network(node_count: usize) -> Vec { + use util::configurations::UserConfig; + let mut nodes = Vec::new(); let mut rng = thread_rng(); let secp_ctx = Secp256k1::new(); @@ -4052,7 +4048,9 @@ 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())); - 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(), @@ -6887,11 +6885,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(), @@ -6951,11 +6951,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(), @@ -7014,8 +7016,10 @@ mod tests { } 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) = <(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(), diff --git a/src/util/configurations.rs b/src/util/configurations.rs new file mode 100644 index 00000000000..21c9a8e3b31 --- /dev/null +++ b/src/util/configurations.rs @@ -0,0 +1,98 @@ +//! This is the config struct used by the channel and channel_manager for channel specific settings and channel handshake limits +//! ChannelHandshakeLimits sets the limits of certain variables that if they are exceeded the channel will be denied. +//! ChannelConfig is used by the channel to control its own properties, it contains defaults for a new channel but these can by changed by update messages or channel creation. +//! Changing the ChannelConfig of channel_manager after a channel was created will not change the settings in already created channels + +/// This is the main user config +/// It wraps the ChannelHandshakeLimits struct and ChannelConfig struct into a single one for channel manager. +#[derive(Clone, Debug)] +pub struct UserConfig{ + /// optional user specified channel limits, this hold information regarding handshakes of channels. + pub channel_limits : ChannelHandshakeLimits, + /// channel specific options and settings egis channel announced or not + pub channel_options : ChannelConfig, +} + +impl UserConfig { + ///default constructor, calls default ChannelOptions and default ChannelLimits constructors + pub fn new() -> Self{ + UserConfig { + channel_limits : ChannelHandshakeLimits::new(), + channel_options : ChannelConfig::new(), + } + } +} + +/// This struct contains all the optional channel limits. If these limits are breached the new channel will be denied +/// If the user wants to check a value, the value needs to be filled in, as by default most are not checked +#[derive(Copy, Clone, Debug)] +pub struct ChannelHandshakeLimits{ + /// minimum allowed satoshis when a channel is funded, this is supplied by the sender. + pub min_funding_satoshis :u64, + /// maximum allowed smallest HTLC that will be accepted by us. + pub max_htlc_minimum_msat : u64, + /// min allowed cap on outstanding HTLC. This is used to limit exposure to HTLCs. + pub min_max_htlc_value_in_flight_msat : u64, + /// max allowed satoshis that may be used as a direct payment by the peer. + pub max_channel_reserve_satoshis : u64, + /// min allowed max outstanding HTLC that can be offered. + pub min_max_accepted_htlcs : u16, + /// min allowed threshold below which outputs should not be generated. + /// These outputs are either commitment or HTLC transactions. + /// HTLCs below this amount plus HTLC transaction fees are not enforceable on-chain. + /// This reflects the reality that tiny outputs are not considered standard transactions and will not propagate through the Bitcoin network + pub min_dust_limit_satoshis : u64, + /// max allowed threshold above which outputs should not be generated. Bolt 2 mentions channel_reserve_satoshis as upper limit, but this can be a lower limit + pub max_dust_limit_satoshis : u64, + /// minimum depth to a number of blocks that is considered reasonable to avoid double-spending of the funding transaction + pub minimum_depth : u32, + /// do we force the incoming channel to match our announced channel preference + pub force_announced_channel_preference : bool, +} + +impl ChannelHandshakeLimits { +//creating max and min possible values because if they are not set, means we should not check them. +///default constructor creates limits so that they are not tested for +///min_dust_limit_satoshis is set to the network default of 546 + pub fn new() -> Self{ + ChannelHandshakeLimits { + min_funding_satoshis : 0, + max_htlc_minimum_msat : ::max_value(), + min_max_htlc_value_in_flight_msat : 0, + max_channel_reserve_satoshis : ::max_value(), + min_max_accepted_htlcs : 0, + min_dust_limit_satoshis : 546, + max_dust_limit_satoshis : ::max_value(), + minimum_depth : ::max_value(), + force_announced_channel_preference : false, + } + } +} + +/// This struct contains all the custom channel options. +#[derive(Copy, Clone, Debug)] +pub struct ChannelConfig{ + /// Amount (in millionths of a satoshi) the channel will charge per transferred satoshi. + /// This must be updated as the channel updates and can change in runtime. + pub fee_proportional_millionths : u32, + //TODO enforce non-mutability when config can change at runtime + ///Is this channel publicly announced channel or not. + ///This cannot change after channel creation. + pub announced_channel : bool, +} +impl ChannelConfig { + /// creating a struct with default values. + /// fee_proportional_millionths should be changed and updated afterwords + pub fn new() -> Self{ + ChannelConfig { + fee_proportional_millionths : 0, + announced_channel : true, + } + } +} + +//Add write and readable traits to channelconfig +impl_writeable!(ChannelConfig, 8+1, { + fee_proportional_millionths, + announced_channel +}); diff --git a/src/util/mod.rs b/src/util/mod.rs index b91b4f25d96..5cc7c501641 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -28,3 +28,6 @@ pub use self::rng::reset_rng_state; #[cfg(test)] pub(crate) mod test_utils; + +//config struct that is used to store defaults for channel handshake limits and channel settings +pub mod configurations;