Skip to content

Commit

Permalink
Process channel disabling
Browse files Browse the repository at this point in the history
  • Loading branch information
contrun committed Oct 9, 2024
1 parent f571e4a commit b38d1dd
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 14 deletions.
68 changes: 60 additions & 8 deletions src/fiber/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ pub const FUNDING_CELL_WITNESS_LEN: usize = 16 + 32 + 64;
// is funded or not.
pub const INITIAL_COMMITMENT_NUMBER: u64 = 0;

// The channel is disabled, and no more tlcs can be added to the channel.
pub const CHANNEL_DISABLED_FLAG: u32 = 1;

#[derive(Debug)]
pub enum ChannelActorMessage {
/// Command are the messages that are sent to the channel actor to perform some action.
Expand Down Expand Up @@ -149,6 +152,7 @@ pub struct ShutdownCommand {

#[derive(Debug)]
pub struct UpdateCommand {
pub enabled: Option<bool>,
pub tlc_locktime_expiry_delta: Option<u64>,
pub tlc_minimum_value: Option<u128>,
pub tlc_maximum_value: Option<u128>,
Expand Down Expand Up @@ -428,7 +432,7 @@ where
state.handle_revoke_and_ack_message(&self.network, revoke_and_ack)?;
Ok(())
}
FiberChannelMessage::ChannelReady(channel_ready) => {
FiberChannelMessage::ChannelReady(_channel_ready) => {
let flags = match state.state {
ChannelState::AwaitingTxSignatures(flags) => {
if flags.contains(AwaitingTxSignaturesFlags::TX_SIGNATURES_SENT) {
Expand Down Expand Up @@ -987,6 +991,7 @@ where
}

let UpdateCommand {
enabled,
tlc_locktime_expiry_delta,
tlc_minimum_value,
tlc_maximum_value,
Expand All @@ -995,6 +1000,10 @@ where

let mut updated = false;

if let Some(enabled) = enabled {
updated = updated || state.update_our_enabled(enabled);
}

if let Some(delta) = tlc_locktime_expiry_delta {
updated = updated || state.update_our_locktime_expiry_delta(delta);
}
Expand Down Expand Up @@ -1239,6 +1248,18 @@ where
myself.stop(Some("PeerDisconnected".to_string()));
}
ChannelEvent::ClosingTransactionConfirmed => {
// Broadcast the channel update message which disables the channel.
let update = state.generate_disabled_channel_update(&self.network).await;

self.network
.send_message(NetworkActorMessage::new_command(
NetworkActorCommand::BroadcastMessage(
vec![state.get_remote_peer_id()],
FiberBroadcastMessage::ChannelUpdate(update),
),
))
.expect(ASSUME_NETWORK_ACTOR_ALIVE);

myself.stop(Some("ChannelClosed".to_string()));
}
}
Expand Down Expand Up @@ -1873,6 +1894,7 @@ pub struct ShutdownInfo {
// the config to the network via another ChannelUpdate message.
#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct PublicChannelInfo {
pub enabled: bool,
// The fee rate for tlc transfers. We only have these values set when
// this is a public channel. Both sides may set this value differently.
// This is a fee that is paid by the sender of the tlc.
Expand Down Expand Up @@ -1907,6 +1929,7 @@ impl PublicChannelInfo {
tlc_max_value: Some(tlc_max_value),
tlc_min_value: Some(tlc_min_value),
tlc_locktime_expiry_delta: Some(tlc_locktime_expiry_delta),
enabled: true,
..Default::default()
}
}
Expand Down Expand Up @@ -2336,19 +2359,16 @@ impl ChannelActorState {
Some(channel_announcement)
}

pub async fn generate_channel_update(
async fn do_generate_channel_update(
&mut self,
network: &ActorRef<NetworkActorMessage>,
// The function that would change the channel update parameters.
f: impl FnOnce(&mut ChannelUpdate),
) -> ChannelUpdate {
let mut channel_update = self
.get_unsigned_channel_update_message()
.expect("public channel can generate channel update message");

debug!(
"Generated unsigned channel update message: {:?}",
&channel_update
);

f(&mut channel_update);
let node_signature =
sign_network_message(network.clone(), channel_update.message_to_sign())
.await
Expand All @@ -2359,6 +2379,23 @@ impl ChannelActorState {
channel_update
}

async fn generate_channel_update(
&mut self,
network: &ActorRef<NetworkActorMessage>,
) -> ChannelUpdate {
self.do_generate_channel_update(network, |_update| {}).await
}

async fn generate_disabled_channel_update(
&mut self,
network: &ActorRef<NetworkActorMessage>,
) -> ChannelUpdate {
self.do_generate_channel_update(network, |update| {
update.channel_flags = CHANNEL_DISABLED_FLAG
})
.await
}

pub async fn generate_and_broadcast_channel_update(
&mut self,
network: &ActorRef<NetworkActorMessage>,
Expand Down Expand Up @@ -2877,6 +2914,21 @@ impl ChannelActorState {
}
}

fn get_our_enabled(&self) -> Option<bool> {
self.public_channel_info.as_ref().map(|state| state.enabled)
}

fn update_our_enabled(&mut self, enabled: bool) -> bool {
let old_value = self.get_our_enabled();
match old_value {
Some(old_value) if old_value == enabled => false,
_ => {
self.public_channel_state_mut().enabled = enabled;
true
}
}
}

fn get_our_locktime_expiry_delta(&self) -> Option<u64> {
self.public_channel_info
.as_ref()
Expand Down
20 changes: 17 additions & 3 deletions src/fiber/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::network::{get_chain_hash, SendPaymentCommand};
use super::path::NodeHeap;
use super::types::Pubkey;
use super::types::{ChannelAnnouncement, ChannelUpdate, Hash256, NodeAnnouncement};
use crate::fiber::channel::CHANNEL_DISABLED_FLAG;
use crate::fiber::path::{NodeHeapElement, ProbabilityEvaluator};
use crate::fiber::types::PaymentHopData;
use crate::invoice::CkbInvoice;
Expand Down Expand Up @@ -82,8 +83,16 @@ impl ChannelInfo {
.max(self.node2_to_node1.as_ref().map(|n| n.timestamp))
}

pub fn is_enabled(&self) -> bool {
self.node1_to_node2.is_some() && self.node2_to_node1.is_some()
// Whether this channel is explicitly disabled in either direction.
// TODO: we currently deem a channel as disabled if one direction is disabled.
// Is it possible that one direction is disabled while the other is not?
pub fn is_explicitly_disabled(&self) -> bool {
dbg!(self.node1_to_node2.as_ref(), self.node2_to_node1.as_ref());
match (&self.node1_to_node2, &self.node2_to_node1) {
(Some(update1), _) if !update1.enabled => true,
(_, Some(update2)) if !update2.enabled => true,
_ => false,
}
}

pub fn capacity(&self) -> u128 {
Expand Down Expand Up @@ -374,10 +383,12 @@ where
return Ok(());
}
}
let disabled = update.channel_flags & CHANNEL_DISABLED_FLAG == CHANNEL_DISABLED_FLAG;

*update_info = Some(ChannelUpdateInfo {
version: update.version,
timestamp: std::time::UNIX_EPOCH.elapsed().unwrap().as_millis() as u64,
enabled: true,
enabled: !disabled,
cltv_expiry_delta: update.tlc_locktime_expiry_delta,
htlc_minimum_value: update.tlc_minimum_value,
htlc_maximum_value: update.tlc_maximum_value,
Expand All @@ -390,6 +401,9 @@ where
"Processed channel update: channel {:?}, update {:?}",
&channel, &update
);
if disabled {
self.channels.remove(channel_outpoint);
}
Ok(())
}

Expand Down
5 changes: 5 additions & 0 deletions src/fiber/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1667,7 +1667,12 @@ pub struct ChannelUpdate {
#[serde_as(as = "EntityHex")]
pub channel_outpoint: OutPoint,
pub version: u64,
// Currently only the first bit is used to indicate the direction of the channel.
// If it is 0, it means this channel message is from node 1 (thus applies to tlcs
// sent from node 2 to node 1). Otherwise, it is from node 2.
pub message_flags: u32,
// Currently only the first bit is used to indicate if the channel is disabled.
// If the first bit is set, the channel is disabled.
pub channel_flags: u32,
pub tlc_locktime_expiry_delta: u64,
pub tlc_minimum_value: u128,
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ pub struct ShutdownChannelParams {
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UpdateChannelParams {
pub channel_id: Hash256,
pub enabled: Option<bool>,
#[serde_as(as = "Option<U64Hex>")]
pub tlc_locktime_expiry_delta: Option<u64>,
#[serde_as(as = "Option<U128Hex>")]
Expand Down Expand Up @@ -459,6 +460,7 @@ where
channel_id: params.channel_id,
command: ChannelCommand::Update(
UpdateCommand {
enabled: params.enabled,
tlc_locktime_expiry_delta: params.tlc_locktime_expiry_delta,
tlc_minimum_value: params.tlc_minimum_value,
tlc_maximum_value: params.tlc_maximum_value,
Expand Down
12 changes: 9 additions & 3 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,15 @@ impl NetworkGraphStateStore for Store {
.take(limit);
let mut last_key = Vec::new();
let channels = iter
.map(|(col_key, value)| {
last_key = col_key.to_vec();
serde_json::from_slice(value.as_ref()).expect("deserialize NodeInfo should be OK")
.filter_map(|(col_key, value)| {
let channel: ChannelInfo = serde_json::from_slice(value.as_ref())
.expect("deserialize ChannelInfo should be OK");
if !channel.is_explicitly_disabled() {
last_key = col_key.to_vec();
Some(channel)
} else {
None
}
})
.collect();
(channels, JsonBytes::from_bytes(last_key.into()))
Expand Down

0 comments on commit b38d1dd

Please sign in to comment.