Skip to content

Commit

Permalink
[bruig] add rpc config screen
Browse files Browse the repository at this point in the history
  • Loading branch information
vctt94 committed Oct 28, 2024
1 parent 59db960 commit f8b3e81
Show file tree
Hide file tree
Showing 5 changed files with 348 additions and 6 deletions.
31 changes: 29 additions & 2 deletions bruig/flutterui/bruig/lib/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class Config {
}

// replaceConfig replaces the settings that can be modified by the GUI, while
// preserving manual chages made to the config file.
// preserving manual changes made to the config file.
Future<void> replaceConfig(
String filepath, {
String? debugLevel,
Expand All @@ -250,6 +250,16 @@ Future<void> replaceConfig(
String? proxyPassword,
int? torCircuitLimit,
bool? torIsolation,
String? jsonRPCListen,
String? rpcCertPath,
String? rpcKeyPath,
String? rpcClientCApath,
String? rpcUser,
String? rpcPass,
String? rpcAuthMode,
bool? rpcIssueClientCert,
bool? rpcAllowRemoteSendTip,
double? rpcMaxRemoteSendTipAmt,
}) async {
var f = ini.Config.fromStrings(File(filepath).readAsLinesSync());

Expand All @@ -271,6 +281,11 @@ Future<void> replaceConfig(
set(section, opt, "$val");
}

void setDouble(String section, String opt, double? val) {
if (val == null) return;
set(section, opt, "$val");
}

set("log", "debuglevel", debugLevel);
setBool("log", "pings", logPings);
set("payment", "lndebuglevel", lnDebugLevel);
Expand All @@ -281,6 +296,18 @@ Future<void> replaceConfig(
setInt("default", "circuitlimit", torCircuitLimit);
setBool("default", "torisolation", torIsolation);

// RPC settings
set("clientrpc", "jsonrpclisten", jsonRPCListen);
set("clientrpc", "rpccertpath", rpcCertPath);
set("clientrpc", "rpckeypath", rpcKeyPath);
set("clientrpc", "rpcclientcapath", rpcClientCApath);
set("clientrpc", "rpcuser", rpcUser);
set("clientrpc", "rpcpass", rpcPass);
set("clientrpc", "rpcauthmode", rpcAuthMode);
setBool("clientrpc", "rpcissueclientcert", rpcIssueClientCert);
setBool("clientrpc", "rpcallowremotesendtip", rpcAllowRemoteSendTip);
setDouble("clientrpc", "rpcmaxremotesendtipamt", rpcMaxRemoteSendTipAmt);

await File(filepath).writeAsString(f.toString());
}

Expand Down Expand Up @@ -427,7 +454,7 @@ Future<Config> loadConfig(String filepath) async {
c.jsonRPCListen = getCommaList("clientrpc", "jsonrpclisten") ?? [""]; // default to [""]
c.rpcCertPath = f.get("clientrpc", "rpccertpath") ?? "";
c.rpcKeyPath = f.get("clientrpc", "rpckeypath") ?? "";
c.rpcIssueClientCert = f.get("clientrpc", "rpcissueclientcert") == "true";
c.rpcIssueClientCert = getBool("clientrpc", "rpcissueclientcert");
c.rpcClientCApath = f.get("clientrpc", "rpcclientcapath") ?? "";
c.rpcUser = f.get("clientrpc", "rpcuser") ?? "";
c.rpcPass = f.get("clientrpc", "rpcpass") ?? "";
Expand Down
36 changes: 32 additions & 4 deletions bruig/flutterui/bruig/lib/models/newconfig.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,38 @@ class NewConfigModel extends ChangeNotifier {
LNNodeType nodeType = LNNodeType.internal;
NetworkType netType = NetworkType.mainnet;

String rpcHost = "";
String tlsCertPath = "";
String macaroonPath = "";
// default properties
String serverAddr = "";
String newWalletSeed = "";
bool advancedSetup = false;

// LN configuration properties
String rpcHost = "";
String tlsCertPath = "";
String macaroonPath = "";
List<String> seedToRestore = [];
Uint8List? multichanBackupRestore;
List<ConfirmSeedWords> confirmSeedWords = [];

// Network configuration properties
String proxyAddr = "";
String proxyUser = "";
String proxyPassword = "";
int torCircuitLimit = 32;
bool torIsolation = false;

// RPC configuration properties
List<String> jsonRPCListen = [""];
String rpcCertPath = "";
String rpcKeyPath = "";
String rpcClientCApath = "";
String rpcUser = "";
String rpcPass = "";
String rpcAuthMode = "";
bool rpcIssueClientCert = false;
bool rpcAllowRemoteSendTip = false;
double rpcMaxRemoteSendTipAmt = 0.0;

Future<LNInfo> tryExternalDcrlnd(
String host, String tlsPath, String macaroonPath) async {
var res = await Golib.lnTryExternalDcrlnd(host, tlsPath, macaroonPath);
Expand All @@ -90,6 +106,18 @@ class NewConfigModel extends ChangeNotifier {
proxyPassword: proxyPassword,
circuitLimit: torCircuitLimit,
torIsolation: torIsolation,

// RPC configuration settings
jsonRPCListen: jsonRPCListen,
rpcCertPath: rpcCertPath,
rpcKeyPath: rpcKeyPath,
rpcClientCApath: rpcClientCApath,
rpcUser: rpcUser,
rpcPass: rpcPass,
rpcAuthMode: rpcAuthMode,
rpcIssueClientCert: rpcIssueClientCert,
rpcAllowRemoteSendTip: rpcAllowRemoteSendTip,
rpcMaxRemoteSendTipAmt: rpcMaxRemoteSendTipAmt,
);
await cfg.saveNewConfig(await configFileName(appArgs));
cfg = await configFromArgs(appArgs); // Reload to fill defaults.
Expand All @@ -107,7 +135,7 @@ class NewConfigModel extends ChangeNotifier {
return cfg;
}

List<ConfirmSeedWords> createConfirmSeedWords(String seed) {
List<ConfirmSeedWords> createConfirmSeedWords(String seed) {
List<ConfirmSeedWords> confirmSeedWords = [];
var seedWords = seed.trim().split(' ');
var numWords = 5;
Expand Down
202 changes: 202 additions & 0 deletions bruig/flutterui/bruig/lib/screens/config_rpc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import 'package:bruig/components/buttons.dart';
import 'package:bruig/components/confirmation_dialog.dart';
import 'package:bruig/components/text.dart';
import 'package:bruig/config.dart';
import 'package:bruig/models/newconfig.dart';
import 'package:bruig/screens/shutdown.dart';
import 'package:bruig/screens/startupscreen.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class RpcConfigScreen extends StatefulWidget {
static const String routeName = "/rpcConfig";
final NewConfigModel? newConf;
const RpcConfigScreen({this.newConf, super.key});

@override
State<RpcConfigScreen> createState() => _RpcConfigScreenState();
}

class _RpcConfigScreenState extends State<RpcConfigScreen> {
NewConfigModel? get newConfigModel => widget.newConf;
TextEditingController rpcListenCtrl = TextEditingController();
TextEditingController rpcCertPathCtrl = TextEditingController();
TextEditingController rpcKeyPathCtrl = TextEditingController();
TextEditingController rpcClientCACtrl = TextEditingController();
TextEditingController rpcUserCtrl = TextEditingController();
TextEditingController rpcPassCtrl = TextEditingController();
TextEditingController rpcAuthModeCtrl = TextEditingController();
TextEditingController rpcMaxRemoteSendTipAmtCtrl = TextEditingController();
bool rpcIssueClientCert = false;
bool rpcAllowRemoteSendTip = false;

void doRestart() {
ShutdownScreen.startShutdown(context, restart: true);
Navigator.pop(context);
}

void changeConfig() async {
await replaceConfig(
mainConfigFilename,
jsonRPCListen: rpcListenCtrl.text,
rpcCertPath: rpcCertPathCtrl.text,
rpcKeyPath: rpcKeyPathCtrl.text,
rpcClientCApath: rpcClientCACtrl.text,
rpcUser: rpcUserCtrl.text,
rpcPass: rpcPassCtrl.text,
rpcAuthMode: rpcAuthModeCtrl.text,
rpcIssueClientCert: rpcIssueClientCert,
rpcAllowRemoteSendTip: rpcAllowRemoteSendTip,
rpcMaxRemoteSendTipAmt:
double.tryParse(rpcMaxRemoteSendTipAmtCtrl.text) ?? 0,
);
if (!mounted) return;
confirmationDialog(
context,
doRestart,
"Restart App?",
"App restart is required to apply RPC settings changes.",
"Restart",
"Cancel",
onCancel: () {
Navigator.of(context).pop();
},
);
}

void confirmAcceptChanges() {
if (newConfigModel != null) {
var newConfigModel = Provider.of<NewConfigModel>(context, listen: false);
newConfigModel.jsonRPCListen =
rpcListenCtrl.text.split(',').map((addr) => addr.trim()).toList();
newConfigModel.rpcCertPath = rpcCertPathCtrl.text;
newConfigModel.rpcKeyPath = rpcKeyPathCtrl.text;
newConfigModel.rpcClientCApath = rpcClientCACtrl.text;
newConfigModel.rpcUser = rpcUserCtrl.text;
newConfigModel.rpcPass = rpcPassCtrl.text;
newConfigModel.rpcAuthMode = rpcAuthModeCtrl.text;
newConfigModel.rpcIssueClientCert = rpcIssueClientCert;
newConfigModel.rpcAllowRemoteSendTip = rpcAllowRemoteSendTip;
newConfigModel.rpcMaxRemoteSendTipAmt =
double.tryParse(rpcMaxRemoteSendTipAmtCtrl.text) ?? 0;
Navigator.of(context).pop();
return;
}

confirmationDialog(
context,
changeConfig,
onCancel: () => Navigator.of(context).pop(),
"Change Config?",
"Change RPC config? To apply the changes, the app will require a restart.",
"Accept",
"Cancel");
}

void readConfig() async {
if (newConfigModel != null) {
setState(() {
rpcListenCtrl.text = newConfigModel!.jsonRPCListen.join(", ");
rpcCertPathCtrl.text = newConfigModel!.rpcCertPath;
rpcKeyPathCtrl.text = newConfigModel!.rpcKeyPath;
rpcClientCACtrl.text = newConfigModel!.rpcClientCApath;
rpcUserCtrl.text = newConfigModel!.rpcUser;
rpcPassCtrl.text = newConfigModel!.rpcPass;
rpcAuthModeCtrl.text = newConfigModel!.rpcAuthMode;
rpcIssueClientCert = newConfigModel!.rpcIssueClientCert;
rpcAllowRemoteSendTip = newConfigModel!.rpcAllowRemoteSendTip;
rpcMaxRemoteSendTipAmtCtrl.text =
newConfigModel!.rpcMaxRemoteSendTipAmt.toString();
});
return;
}

var cfg = await loadConfig(mainConfigFilename);
setState(() {
rpcListenCtrl.text = cfg.jsonRPCListen.join(", ");
rpcCertPathCtrl.text = cfg.rpcCertPath;
rpcKeyPathCtrl.text = cfg.rpcKeyPath;
rpcClientCACtrl.text = cfg.rpcClientCApath;
rpcUserCtrl.text = cfg.rpcUser;
rpcPassCtrl.text = cfg.rpcPass;
rpcAuthModeCtrl.text = cfg.rpcAuthMode;
rpcIssueClientCert = cfg.rpcIssueClientCert;
rpcAllowRemoteSendTip = cfg.rpcAllowRemoteSendTip;
rpcMaxRemoteSendTipAmtCtrl.text = cfg.rpcMaxRemoteSendTipAmt.toString();
});
}

@override
void initState() {
super.initState();
readConfig();
}

@override
Widget build(BuildContext context) {
return StartupScreen(childrenWidth: 400, [
const Txt.H("Configure RPC Options"),
const SizedBox(height: 20),
TextField(
controller: rpcListenCtrl,
decoration: const InputDecoration(
labelText: "JSON-RPC Listen Address",
hintText: "127.0.0.1:7676")),
const SizedBox(height: 10),
TextField(
controller: rpcCertPathCtrl,
decoration: const InputDecoration(
labelText: "RPC Certificate Path", hintText: "/path/to/cert")),
const SizedBox(height: 10),
TextField(
controller: rpcKeyPathCtrl,
decoration: const InputDecoration(
labelText: "RPC Key Path", hintText: "/path/to/key")),
const SizedBox(height: 10),
TextField(
controller: rpcClientCACtrl,
decoration: const InputDecoration(
labelText: "RPC Client CA Path", hintText: "/path/to/ca")),
const SizedBox(height: 10),
TextField(
controller: rpcUserCtrl,
decoration: const InputDecoration(
labelText: "RPC Username", hintText: "rpcuser")),
const SizedBox(height: 10),
TextField(
controller: rpcPassCtrl,
decoration: const InputDecoration(
labelText: "RPC Password", hintText: "rpcpass")),
const SizedBox(height: 10),
TextField(
controller: rpcAuthModeCtrl,
decoration: const InputDecoration(
labelText: "RPC Auth Mode", hintText: "authmode")),
const SizedBox(height: 10),
TextField(
keyboardType: TextInputType.number,
controller: rpcMaxRemoteSendTipAmtCtrl,
decoration: const InputDecoration(
labelText: "Max Remote Send Tip Amount", hintText: "0.0")),
const SizedBox(height: 20),
SwitchListTile(
title: const Text("Issue Client Certificate"),
value: rpcIssueClientCert,
onChanged: (value) => setState(() => rpcIssueClientCert = value),
),
const SizedBox(height: 10),
SwitchListTile(
title: const Text("Allow Remote Send Tip"),
value: rpcAllowRemoteSendTip,
onChanged: (value) => setState(() => rpcAllowRemoteSendTip = value),
),
const SizedBox(height: 30),
Wrap(runSpacing: 10, children: [
OutlinedButton(
onPressed: confirmAcceptChanges, child: const Text("Accept")),
const SizedBox(width: 50),
CancelButton(onPressed: () => Navigator.pop(context)),
]),
]);
}
}
Loading

0 comments on commit f8b3e81

Please sign in to comment.