Skip to content

Commit

Permalink
Merge pull request #2146 from get10101/chore/add-emergency-kit-to-rol…
Browse files Browse the repository at this point in the history
…lback-channel-state

chore(emergency kit): Add option to rollback channel to last stable state
  • Loading branch information
holzeis authored Mar 4, 2024
2 parents c9dab5f + e3a68bc commit 976706a
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 5 deletions.
50 changes: 47 additions & 3 deletions coordinator/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,18 +405,18 @@ pub async fn close_channel(
}

#[derive(Debug, Deserialize)]
pub struct DeleteDlcChannel {
pub struct Confirmation {
#[serde(default, deserialize_with = "empty_string_as_none")]
i_know_what_i_am_doing: Option<bool>,
}

/// This function deletes a DLC channel from our database irreversible!
/// If you want to close a channel instead, use `close_channel`
#[instrument(skip_all, err(Debug))]
pub async fn delete_dlc_channels(
pub async fn delete_dlc_channel(
Path(channel_id_string): Path<String>,
State(state): State<Arc<AppState>>,
Query(params): Query<DeleteDlcChannel>,
Query(params): Query<Confirmation>,
) -> Result<(), AppError> {
if !params.i_know_what_i_am_doing.unwrap_or_default() {
let error_message =
Expand Down Expand Up @@ -447,6 +447,50 @@ pub async fn delete_dlc_channels(
Ok(())
}

/// This function attempts to roll back a DLC channel to the last stable state!
/// The action is irreversible, only use if you know what you are doing!
#[instrument(skip_all, err(Debug))]
pub async fn roll_back_dlc_channel(
Path(channel_id_string): Path<String>,
State(state): State<Arc<AppState>>,
Query(params): Query<Confirmation>,
) -> Result<(), AppError> {
if !params.i_know_what_i_am_doing.unwrap_or_default() {
let error_message =
"Looks like you don't know what you are doing! Go and ask your supervisor for help!";
tracing::warn!(error_message);
return Err(AppError::BadRequest(error_message.to_string()));
}

let channel_id = parse_dlc_channel_id(&channel_id_string)
.map_err(|_| AppError::BadRequest("Provided channel ID was invalid".to_string()))?;

tracing::info!(channel_id = %channel_id_string, "Attempting to roll back dlc channel to last stable state");

let channel = state
.node
.inner
.get_dlc_channel_by_id(&channel_id)
.map_err(|e| AppError::BadRequest(format!("Couldn't find channel. {e:#}")))?;
if let Channel::Signed(signed_channel) = channel {
state
.node
.inner
.roll_back_channel(&signed_channel)
.map_err(|e| {
AppError::InternalServerError(format!("Failed to roll back channel. {e:#}"))
})?
} else {
return Err(AppError::BadRequest(
"It's only possible to rollback a channel in state signed".to_string(),
));
}

tracing::info!(channel_id = %channel_id_string, "Rolled back dlc channel");

Ok(())
}

#[instrument(skip_all, err(Debug))]
pub async fn sign_message(
Path(msg): Path<String>,
Expand Down
9 changes: 7 additions & 2 deletions coordinator/src/routes.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use crate::admin::close_channel;
use crate::admin::collaborative_revert;
use crate::admin::connect_to_peer;
use crate::admin::delete_dlc_channels;
use crate::admin::delete_dlc_channel;
use crate::admin::get_balance;
use crate::admin::get_fee_rate_estimation;
use crate::admin::get_utxos;
use crate::admin::is_connected;
use crate::admin::list_dlc_channels;
use crate::admin::list_on_chain_transactions;
use crate::admin::list_peers;
use crate::admin::roll_back_dlc_channel;
use crate::admin::sign_message;
use crate::backup::SledBackup;
use crate::campaign::post_push_campaign;
Expand Down Expand Up @@ -170,7 +171,11 @@ pub fn router(
.route("/api/admin/dlc_channels", get(list_dlc_channels))
.route(
"/api/admin/dlc_channels/:channel_id",
delete(delete_dlc_channels),
delete(delete_dlc_channel),
)
.route(
"/api/admin/dlc_channels/rollback/:channel_id",
post(roll_back_dlc_channel),
)
.route("/api/admin/transactions", get(list_on_chain_transactions))
.route("/api/admin/sign/:msg", get(sign_message))
Expand Down
19 changes: 19 additions & 0 deletions mobile/lib/common/settings/emergency_kit_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,25 @@ class _EmergencyKitScreenState extends State<EmergencyKitScreen> {
goRouter.pop();
}),
const SizedBox(height: 30),
EmergencyKitButton(
icon: const Icon(FontAwesomeIcons.backwardStep),
title: "Rollback channel state",
onPressed: () async {
final messenger = ScaffoldMessenger.of(context);
final orderChangeNotifier = context.read<OrderChangeNotifier>();
final goRouter = GoRouter.of(context);

try {
await rust.api.rollBackChannelState();
await orderChangeNotifier.initialize();
showSnackBar(messenger, "Successfully rolled back channel state");
} catch (e) {
showSnackBar(messenger, "Failed to rollback channel state. Error: $e");
}

goRouter.pop();
}),
const SizedBox(height: 30),
Visibility(
visible: config.network == "regtest",
child: EmergencyKitButton(
Expand Down
7 changes: 7 additions & 0 deletions mobile/native/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,3 +819,10 @@ pub fn get_new_random_name() -> SyncReturn<String> {
pub async fn update_nickname(nickname: String) -> Result<()> {
users::update_username(nickname).await
}

pub fn roll_back_channel_state() -> Result<()> {
tracing::warn!(
"Executing emergency kit! Attempting to rollback channel state to last stable state"
);
ln_dlc::roll_back_channel_state()
}
11 changes: 11 additions & 0 deletions mobile/native/src/ln_dlc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1057,3 +1057,14 @@ fn confirmation_status_to_status_and_timestamp(

(status, timestamp.unix_timestamp() as u64)
}

pub fn roll_back_channel_state() -> Result<()> {
let node = state::get_node();

let counterparty_pubkey = config::get_coordinator_info().pubkey;
let signed_channel = node
.inner
.get_signed_channel_by_trader_id(counterparty_pubkey)?;

node.inner.roll_back_channel(&signed_channel)
}

0 comments on commit 976706a

Please sign in to comment.