epiccash submodule -> native assets migration
What changed, and why it matters
This commit changes how the Stack Wallet app pulls in its Epic Cash cryptocurrency library. Previously, the library was included as a local Git submodule inside the project. Now, the app fetches it directly from a specific Git commit on GitHub as a 'native asset' dependency. The commit also removes the user-facing display of the Epic Cash build commit hash from the About screen and deletes the code that checked whether that commit was the latest one. This is primarily a build-system and UI cleanup change; there is no direct evidence in the diff of a security vulnerability being fixed.
Treat this as a routine build-system refactor unless additional context shows it was a security response. Verify that the pinned Git ref (dcb285b30ac4a91285a6aa4536ce24630b406d3c) of flutter_libepiccash is trustworthy and that the dependency is fetched over HTTPS with integrity checks. Consider whether removing the commit-status check reduces transparency for supply-chain verification, and decide if that check should be restored or replaced by another mechanism.
Security signals we found
Dependency source changed from local Git submodule to remote Git package pinned to a specific commit hash
Removal of runtime GitHub API commit-status verification for the Epic Cash library
Removal of user-facing commit hash transparency for the Epic Cash library build
No explicit security fix, vulnerability disclosure, or patch description in commit message
Evidence from the diff
The commit migrates flutter_libepiccash from a Git submodule (crypto_plugins/flutter_libepiccash) to a pinned Git dependency in pubspec (ref dcb285b30ac4a91285a6aa4536ce24630b406d3c). It removes the submodule entry from .gitmodules, deletes the local submodule directory reference, updates pubspec.lock and the app config template accordingly, and removes the getPluginVersion() method from the LibEpicCashInterface. UI code in about_view.dart and desktop_about_view.dart that displayed the Epic Cash build commit and its freshness status is removed, along with the GitStatus helper that queried the GitHub API to verify the commit. The actual Epic Cash wallet interface implementation is otherwise unchanged except for minor formatting.
Changed components
Stack Wallet build configuration (pubspec.yaml / pubspec.lock / app config templates)Git submodule configuration (.gitmodules)Epic Cash wallet integration interface (lib/wl_gen/interfaces/libepiccash_interface.dart)Generated Epic Cash interface implementation template (tool/wl_templates/EPIC_libepiccash_interface_impl.template.dart)About / Desktop About UI viewsGitStatus utility (lib/utilities/git_status.dart)Inspect captured patch +12 / −265
diff --git a/.gitmodules b/.gitmodules
index da71576..e69de29 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +0,0 @@
-[submodule "crypto_plugins/flutter_libepiccash"]
- path = crypto_plugins/flutter_libepiccash
- url = https://github.com/cypherstack/flutter_libepiccash.git
diff --git a/lib/pages/settings_views/global_settings_view/about_view.dart b/lib/pages/settings_views/global_settings_view/about_view.dart
index b78d940..89de18d 100644
--- a/lib/pages/settings_views/global_settings_view/about_view.dart
+++ b/lib/pages/settings_views/global_settings_view/about_view.dart
@@ -178,92 +178,7 @@ class AboutView extends ConsumerWidget {
);
},
),
- if (AppConfig.coins.whereType<Epiccash>().isNotEmpty)
- const SizedBox(height: 12),
- if (AppConfig.coins.whereType<Epiccash>().isNotEmpty)
- FutureBuilder(
- future: GitStatus.getEpicCommitStatus(),
- builder:
- (
- context,
- AsyncSnapshot<CommitStatus> snapshot,
- ) {
- CommitStatus stateOfCommit =
- CommitStatus.notLoaded;
-
- if (snapshot.connectionState ==
- ConnectionState.done &&
- snapshot.hasData) {
- stateOfCommit = snapshot.data!;
- }
-
- return RoundedWhiteContainer(
- child: Column(
- crossAxisAlignment:
- CrossAxisAlignment.stretch,
- children: [
- Text(
- "Epic Cash Build Commit",
- style: STextStyles.titleBold12(
- context,
- ),
- ),
- const SizedBox(height: 4),
- SelectableText(
- GitStatus.epicCashCommit,
- style: GitStatus.styleForStatus(
- stateOfCommit,
- context,
- ),
- ),
- ],
- ),
- );
- },
- ),
const SizedBox(height: 12),
- // if (AppConfig.coins.whereType<Monero>().isNotEmpty)
- // FutureBuilder(
- // future: GitStatus.getMoneroCommitStatus(),
- // builder: (
- // context,
- // AsyncSnapshot<CommitStatus> snapshot,
- // ) {
- // CommitStatus stateOfCommit =
- // CommitStatus.notLoaded;
- //
- // if (snapshot.connectionState ==
- // ConnectionState.done &&
- // snapshot.hasData) {
- // stateOfCommit = snapshot.data!;
- // }
- // return RoundedWhiteContainer(
- // child: Column(
- // crossAxisAlignment:
- // CrossAxisAlignment.stretch,
- // children: [
- // Text(
- // "Monero Build Commit",
- // style: STextStyles.titleBold12(context),
- // ),
- // const SizedBox(
- // height: 4,
- // ),
- // SelectableText(
- // GitStatus.moneroCommit,
- // style: GitStatus.styleForStatus(
- // stateOfCommit,
- // context,
- // ),
- // ),
- // ],
- // ),
- // );
- // },
- // ),
- // const SizedBox(
- // height: 12,
- // ),
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
diff --git a/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart b/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart
index 417c126..876e457 100644
--- a/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart
+++ b/lib/pages_desktop_specific/settings/settings_menu/desktop_about_view.dart
@@ -289,134 +289,6 @@ class DesktopAboutView extends ConsumerWidget {
),
],
),
- const SizedBox(height: 32),
- Wrap(
- spacing: 64,
- runSpacing: 32,
- children: [
- if (AppConfig.coins
- .whereType<Epiccash>()
- .isNotEmpty)
- FutureBuilder(
- future:
- GitStatus.getEpicCommitStatus(),
- builder:
- (
- context,
- AsyncSnapshot<
- CommitStatus
- >
- snapshot,
- ) {
- CommitStatus
- stateOfCommit =
- CommitStatus
- .notLoaded;
-
- if (snapshot.connectionState ==
- ConnectionState
- .done &&
- snapshot.hasData) {
- stateOfCommit =
- snapshot.data!;
- }
-
- return Column(
- mainAxisSize:
- MainAxisSize.min,
- crossAxisAlignment:
- CrossAxisAlignment
- .start,
- children: [
- Text(
- "Epic Cash Build Commit",
- style:
- STextStyles.desktopTextExtraExtraSmall(
- context,
- ).copyWith(
- color: Theme.of(context)
- .extension<
- StackColors
- >()!
- .textDark,
- ),
- ),
- const SizedBox(
- height: 2,
- ),
- SelectableText(
- GitStatus
- .epicCashCommit,
- style:
- GitStatus.styleForStatus(
- stateOfCommit,
- context,
- ),
- ),
- ],
- );
- },
- ),
-
- //if (AppConfig.coins
- // .whereType<Monero>()
- // .isNotEmpty)
- // FutureBuilder(
- // future: GitStatus
- // .getMoneroCommitStatus(),
- // builder: (
- // context,
- // AsyncSnapshot<CommitStatus>
- // snapshot,
- // ) {
- // CommitStatus stateOfCommit =
- // CommitStatus.notLoaded;
- //
- // if (snapshot.connectionState ==
- // ConnectionState
- // .done &&
- // snapshot.hasData) {
- // stateOfCommit =
- // snapshot.data!;
- // }
- // return Column(
- // mainAxisSize:
- // MainAxisSize.min,
- // crossAxisAlignment:
- // CrossAxisAlignment
- // .start,
- // children: [
- // Text(
- // "Monero Build Commit",
- // style: STextStyles
- // .desktopTextExtraExtraSmall(
- // context,
- // ).copyWith(
- // color: Theme.of(
- // context,
- // )
- // .extension<
- // StackColors>()!
- // .textDark,
- // ),
- // ),
- // const SizedBox(
- // height: 2,
- // ),
- // SelectableText(
- // GitStatus.moneroCommit,
- // style: GitStatus
- // .styleForStatus(
- // stateOfCommit,
- // context,
- // ),
- // ),
- // ],
- // );
- // },
- // ),
- ],
- ),
const SizedBox(height: 35),
Row(
children: [
diff --git a/lib/utilities/git_status.dart b/lib/utilities/git_status.dart
index e3ca70a..214f2ae 100644
--- a/lib/utilities/git_status.dart
+++ b/lib/utilities/git_status.dart
@@ -7,7 +7,6 @@ import '../../../themes/stack_colors.dart';
import '../../../utilities/logger.dart';
import '../../../utilities/text_styles.dart';
import '../app_config.dart';
-import '../wl_gen/generated/libepiccash_interface_impl.dart';
const kGithubAPI = "https://api.github.com";
const kGithubSearch = "/search/commits";
@@ -16,41 +15,10 @@ const kGithubHead = "/repos";
enum CommitStatus { isHead, isOldCommit, notACommit, notLoaded }
abstract class GitStatus {
- static String get epicCashCommit => libEpic.getPluginVersion();
// static String get moneroCommit => monero_versions.getPluginVersion();
static String get appCommitHash => AppConfig.commitHash;
- static CommitStatus? _cachedEpicStatus;
- static Future<CommitStatus> getEpicCommitStatus() async {
- if (_cachedEpicStatus != null) {
- return _cachedEpicStatus!;
- }
-
- final List<bool> results = await Future.wait([
- _doesCommitExist("cypherstack", "flutter_libepiccash", epicCashCommit),
- _isHeadCommit(
- "cypherstack",
- "flutter_libepiccash",
- "main",
- epicCashCommit,
- ),
- ]);
-
- final commitExists = results[0];
- final commitIsHead = results[1];
-
- if (commitExists && commitIsHead) {
- _cachedEpicStatus = CommitStatus.isHead;
- } else if (commitExists) {
- _cachedEpicStatus = CommitStatus.isOldCommit;
- } else {
- _cachedEpicStatus = CommitStatus.notACommit;
- }
-
- return _cachedEpicStatus!;
- }
-
//static CommitStatus? _cachedMoneroStatus;
//static Future<CommitStatus> getMoneroCommitStatus() async {
// if (_cachedMoneroStatus != null) {
diff --git a/lib/wl_gen/interfaces/libepiccash_interface.dart b/lib/wl_gen/interfaces/libepiccash_interface.dart
index cdbbb19..d6ab185 100644
--- a/lib/wl_gen/interfaces/libepiccash_interface.dart
+++ b/lib/wl_gen/interfaces/libepiccash_interface.dart
@@ -127,8 +127,6 @@ abstract class LibEpicCashInterface {
});
void updateConfig({required DynamicObject wallet, required String config});
-
- String getPluginVersion();
}
class EpicTransaction {
diff --git a/pubspec.lock b/pubspec.lock
index 7bc6867..f265786 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1020,9 +1020,11 @@ packages:
flutter_libepiccash:
dependency: "direct main"
description:
- path: "crypto_plugins/flutter_libepiccash"
- relative: true
- source: path
+ path: "."
+ ref: dcb285b30ac4a91285a6aa4536ce24630b406d3c
+ resolved-ref: dcb285b30ac4a91285a6aa4536ce24630b406d3c
+ url: "https://github.com/cypherstack/flutter_libepiccash.git"
+ source: git
version: "0.0.1"
flutter_libmwc:
dependency: "direct main"
diff --git a/scripts/app_config/templates/pubspec.template.yaml b/scripts/app_config/templates/pubspec.template.yaml
index fb2d568..074b0b7 100644
--- a/scripts/app_config/templates/pubspec.template.yaml
+++ b/scripts/app_config/templates/pubspec.template.yaml
@@ -51,7 +51,9 @@ dependencies:
# %%ENABLE_EPIC%%
# flutter_libepiccash:
-# path: ./crypto_plugins/flutter_libepiccash
+# git:
+# url: https://github.com/cypherstack/flutter_libepiccash.git
+# ref: dcb285b30ac4a91285a6aa4536ce24630b406d3c
# %%END_ENABLE_EPIC%%
# %%ENABLE_MWC%%
diff --git a/tool/wl_templates/EPIC_libepiccash_interface_impl.template.dart b/tool/wl_templates/EPIC_libepiccash_interface_impl.template.dart
index 4e78631..415c447 100644
--- a/tool/wl_templates/EPIC_libepiccash_interface_impl.template.dart
+++ b/tool/wl_templates/EPIC_libepiccash_interface_impl.template.dart
@@ -1,6 +1,5 @@
//ON
import 'package:flutter_libepiccash/epic_cash.dart' as epc;
-import 'package:flutter_libepiccash/git_versions.dart' as epic_versions;
import 'package:flutter_libepiccash/lib.dart';
import 'package:flutter_libepiccash/models/transaction.dart';
@@ -35,9 +34,8 @@ final class _LibEpicCashInterfaceImpl extends LibEpicCashInterface {
required DynamicObject wallet,
required String slateJson,
}) async {
- return (await wallet.get<EpicWallet>().txReceive(
- slateJson: slateJson,
- )).toRecord();
+ return (await wallet.get<EpicWallet>().txReceive(slateJson: slateJson))
+ .toRecord();
}
@override
@@ -45,9 +43,8 @@ final class _LibEpicCashInterfaceImpl extends LibEpicCashInterface {
required DynamicObject wallet,
required String slateJson,
}) async {
- return (await wallet.get<EpicWallet>().txFinalize(
- slateJson: slateJson,
- )).toRecord();
+ return (await wallet.get<EpicWallet>().txFinalize(slateJson: slateJson))
+ .toRecord();
}
@override
@@ -310,9 +307,6 @@ final class _LibEpicCashInterfaceImpl extends LibEpicCashInterface {
Future<void> close({required DynamicObject wallet}) {
return wallet.get<EpicWallet>().close();
}
-
- @override
- String getPluginVersion() => epic_versions.getPluginVersion();
}
//END_ON
Why this scored 25/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.