Skip to content

Commit

Permalink
chore(emergency kit): Add option to rollback channel to last stable s…
Browse files Browse the repository at this point in the history
…tate
  • Loading branch information
holzeis committed Mar 4, 2024
1 parent 97ecbe3 commit 40ca117
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 3 deletions.
44 changes: 44 additions & 0 deletions coordinator/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,50 @@ pub async fn delete_dlc_channel(
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
5 changes: 5 additions & 0 deletions coordinator/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ 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::collaborative_revert::confirm_collaborative_revert;
Expand Down Expand Up @@ -167,6 +168,10 @@ pub fn router(
"/api/admin/dlc_channels/:channel_id",
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))
.route("/api/admin/connect", post(connect_to_peer))
Expand Down
65 changes: 62 additions & 3 deletions mobile/lib/common/settings/emergency_kit_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,68 @@ class _EmergencyKitScreenState extends State<EmergencyKitScreen> {
))
],
),
const SizedBox(
height: 30,
),
const SizedBox(height: 30),
OutlinedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Are you sure?"),
content: const Text(
"Performing that action may break your app state and should only get executed after consulting with the 10101 Team."),
actions: [
TextButton(
onPressed: () => GoRouter.of(context).pop(),
child: const Text('No'),
),
TextButton(
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();
},
child: const Text('Yes'),
),
]);
});
},
style: ButtonStyle(
fixedSize: MaterialStateProperty.all(const Size(double.infinity, 50)),
iconSize: MaterialStateProperty.all<double>(20.0),
elevation: MaterialStateProperty.all<double>(0),
// this reduces the shade
side: MaterialStateProperty.all(
const BorderSide(width: 1.0, color: tenTenOnePurple)),
padding: MaterialStateProperty.all<EdgeInsetsGeometry>(
const EdgeInsets.fromLTRB(20, 12, 20, 12),
),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
backgroundColor: MaterialStateProperty.all<Color>(Colors.transparent),
),
child: const Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Icon(FontAwesomeIcons.backwardStep),
SizedBox(width: 10),
Text("Rollback channel state", style: TextStyle(fontSize: 16))
])),
const SizedBox(height: 30),
Visibility(
visible: config.network == "regtest",
child: OutlinedButton(
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 @@ -817,3 +817,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 40ca117

Please sign in to comment.