diff --git a/contrib/release/macos/Liana.app/Contents/Info.plist b/contrib/release/macos/Liana.app/Contents/Info.plist
new file mode 100644
index 00000000..46f57151
--- /dev/null
+++ b/contrib/release/macos/Liana.app/Contents/Info.plist
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+ CFBundleName
+ Liana
+
+ CFBundleDisplayName
+ Liana
+
+ CFBundleIdentifier
+ com.wizardsardine.liana
+
+ CFBundleVersion
+ VERSION_PLACEHOLDER
+
+ CFBundleShortVersionString
+ VERSION_PLACEHOLDER
+
+ CFBundlePackageType
+ APPL
+
+ CFBundleSignature
+ ????
+
+ CFBundleExecutable
+ Liana
+
+ LSMinimumSystemVersion
+ 10.15.0
+
+ CFBundleIconFile
+ Liana.icns
+
+ NSPrincipalClass
+ NSApplication
+
+ LSApplicationCategoryType
+ public.app-category.finance
+
+
+
diff --git a/contrib/release/macos/dmg_template/Liana.app/Contents/PkgInfo b/contrib/release/macos/Liana.app/Contents/PkgInfo
similarity index 100%
rename from contrib/release/macos/dmg_template/Liana.app/Contents/PkgInfo
rename to contrib/release/macos/Liana.app/Contents/PkgInfo
diff --git a/contrib/release/macos/Liana.app/Contents/Resources/Liana.icns b/contrib/release/macos/Liana.app/Contents/Resources/Liana.icns
new file mode 100644
index 00000000..5fa35a07
Binary files /dev/null and b/contrib/release/macos/Liana.app/Contents/Resources/Liana.icns differ
diff --git a/contrib/release/macos/README.md b/contrib/release/macos/README.md
new file mode 100644
index 00000000..82074e6c
--- /dev/null
+++ b/contrib/release/macos/README.md
@@ -0,0 +1,84 @@
+# MacOS packaging and distribution
+
+We distribute the application as a zipped [MacOS app bundle](https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW5).
+
+## Notes on codesigning and notarization
+
+Running a binary on a Mac that was not both codesigned **and** notarized by Apple is a pain. The
+user needs to run it. Get an error message. Go to System preferences > Security > authorize the app.
+Then try again, and finally be presented a button to open the app.
+
+In order to avoid that, we've started distributing codesigned binaries starting from version 1.0.
+This is the notes i've taken describing the stepped involved in codesigning the produced macOS
+binary on a Linux machine, for posterity. This is not cleaned up.
+
+### Bulk notes from the codesigning experiment
+
+Create an account at https://developer.apple.com.
+
+Pay to get into the developer program. Going the organization way is cumbersome. Go the personal
+way. They'll ask for a KYC (gov ID). Wait to be accepted.
+
+Go to "certificates, ids and profiles". Create a new certificate. Select a Developer ID application
+certificate to distribute apps outside of the store.
+
+(We should look into the installer feature later on. Maybe we could bundle a bitcoind there.)
+
+They ask for a "Certificate Signing Request (CSR)" that you need to generate on your Mac. I don't
+have a Mac. Generate it using OpenSSL:
+```
+openssl genrsa -out wizardsardine_liana.key 2048
+openssl req -new -sha256 -key wizardsardine_liana.key -out wizardsardine_liana_codesigning.csr -subj "/emailAddress=antoine@wizardsardine.com, CN=Antoine Poinsot, C=FR"
+```
+(Note you have no choice in the size or type of the key here, they expect a RSA(2048) key.)
+
+For the profile type select "G2 Sub-CA". We are using an Xcode newer than 11.4.1 and the codesigning
+tool we use supports the new CA.
+
+Now you get to be able to download your certificate (I've stored it as
+"antoine_devid_liana_codesigning.cer"). Thankfully `rcodesign` supports various certificate format,
+so we don't even have to convert it to PEM.
+
+Download `rcodesign`:
+```
+curl -OL https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F0.22.0/apple-codesign-0.22.0-x86_64-unknown-linux-musl.tar.gz
+tar -xzf apple-codesign-0.22.0-x86_64-unknown-linux-musl.tar.gz
+./apple-codesign-0.22.0-x86_64-unknown-linux-musl/rcodesign --help
+```
+
+Sign the packaged application using the `sign` command (mind `--code-signature-flags for the
+necessary hardened runtime):
+```
+./apple-codesign-0.22.0-x86_64-unknown-linux-musl/rcodesign sign --code-signature-flags runtime --pem-source wizardsardine_liana.key --der-source antoine_devid_liana_codesigning.cer Liana.app
+```
+You can see the chain of certificates was applied using the `diff-signatures` command against
+another bundle. The best way to verify the signature is by using the `codesign` command on a Mac.
+
+Finally, we need to notarize the app. Follow the instructions at
+https://gregoryszorc.com/docs/apple-codesign/main/apple_codesign_rcodesign.html#notarizing-and-stapling:
+- Create an API key from https://appstoreconnect.apple.com/ (and *not* a key from
+ https://developer.apple.com/account/resources/authkeys)
+- Download it and encode it into a JSON file using the `encode-app-store-connect-api-key` command
+- Use the `notary-submit` command to request notarization
+
+```
+./apple-codesign-0.22.0-x86_64-unknown-linux-musl/rcodesign notary-submit --max-wait-seconds 600 --api-key-path ./encoded_appstore_api_key.json --staple Liana.app
+```
+According to
+https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow#3087732
+this can take up to a hour. I've experienced more. You can see the status of an existing request
+using the `notary-log` command.
+
+
+-------
+
+Resources:
+- https://gist.github.com/jcward/d08b33fc3e6c5f90c18437956e5ccc35
+- https://github.com/achow101/signapple
+- https://developer.apple.com/library/archive/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919
+- https://gregoryszorc.com/docs/apple-codesign/main/index.html
+- https://www.apple.com/certificateauthority/
+- https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
+
+Resources on packaging an application for MacOS:
+- https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW5
diff --git a/contrib/release/macos/dmg_template/.background/background.tiff b/contrib/release/macos/dmg_template/.background/background.tiff
deleted file mode 100644
index 1fb088c8..00000000
Binary files a/contrib/release/macos/dmg_template/.background/background.tiff and /dev/null differ
diff --git a/contrib/release/macos/dmg_template/Liana.app/Contents/Info.plist b/contrib/release/macos/dmg_template/Liana.app/Contents/Info.plist
deleted file mode 100644
index fdf5b58b..00000000
--- a/contrib/release/macos/dmg_template/Liana.app/Contents/Info.plist
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
- LSMinimumSystemVersion
- 10.15.0
-
- LSArchitecturePriority
-
- x86_64
-
-
-
-
-
-
- CFBundlePackageType
- APPL
-
- CFBundleSupportedPlatforms
-
- MacOSX
-
-
- CFBundleShortVersionString
- VERSION_PLACEHOLDER
-
- CFBundleVersion
- VERSION_PLACEHOLDER
-
- CFBundleSignature
- ????
-
- CFBundleExecutable
- Liana
-
- CFBundleName
- Liana
-
- LSHasLocalizedDisplayName
-
-
- CFBundleIdentifier
- org.wizardsardine.liana
-
- CFBundleURLTypes
-
-
- CFBundleTypeRole
- Editor
- CFBundleURLName
- org.wizardsardine.liana
- CFBundleURLSchemes
-
- liana
-
-
-
-
- NSPrincipalClass
- NSApplication
-
- NSHighResolutionCapable
- True
-
- LSApplicationCategoryType
- public.app-category.finance
-
-
diff --git a/contrib/release/macos/gen_dstore.py b/contrib/release/macos/gen_dstore.py
deleted file mode 100644
index d9c70ad2..00000000
--- a/contrib/release/macos/gen_dstore.py
+++ /dev/null
@@ -1,51 +0,0 @@
-"""
-Script to generate a .DS_Store within the dmg folder to have a neat fancy window
-when installing the software on macOS.
-
-This was taken and adapted from the Bitcoin Core 'macdeployqtplus' script.
-https://github.com/bitcoin/bitcoin/blob/cb32328d1b80d0ccd6eb9532bd8fe4e0a4de385e/contrib/macdeploy/macdeployqtplus
-"""
-
-from ds_store import DSStore
-from mac_alias import Alias
-
-
-output_file = ".DS_Store"
-
-ds = DSStore.open(output_file, "w+")
-
-ds["."]["bwsp"] = {
- "WindowBounds": "{{300, 280}, {500, 343}}",
- "PreviewPaneVisibility": False,
-}
-
-icvp = {
- "gridOffsetX": 0.0,
- "textSize": 12.0,
- "viewOptionsVersion": 1,
- "backgroundImageAlias": b"\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00",
- "backgroundColorBlue": 1.0,
- "iconSize": 96.0,
- "backgroundColorGreen": 1.0,
- "arrangeBy": "none",
- "showIconPreview": True,
- "gridSpacing": 100.0,
- "gridOffsetY": 0.0,
- "showItemInfo": False,
- "labelOnBottom": True,
- "backgroundType": 2,
- "backgroundColorRed": 1.0,
-}
-alias = Alias().from_bytes(icvp["backgroundImageAlias"])
-alias.volume.name = "Liana"
-alias.volume.posix_path = "/Volumes/Liana"
-icvp["backgroundImageAlias"] = alias.to_bytes()
-ds["."]["icvp"] = icvp
-
-ds["."]["vSrn"] = ("long", 1)
-
-ds["Applications"]["Iloc"] = (370, 156)
-ds["Liana.app"]["Iloc"] = (128, 156)
-
-ds.flush()
-ds.close()
diff --git a/contrib/release/release.sh b/contrib/release/release.sh
index 86f00faa..179492aa 100755
--- a/contrib/release/release.sh
+++ b/contrib/release/release.sh
@@ -15,6 +15,11 @@ WINDOWS_DIR_NAME="$LIANA_PREFIX-x86_64-windows-gnu"
WINDOWS_ARCHIVE="$WINDOWS_DIR_NAME.zip"
MAC_DIR_NAME="$LIANA_PREFIX-x86_64-apple-darwin"
MAC_ARCHIVE="$MAC_DIR_NAME.tar.gz"
+MAC_CODESIGN="${MAC_CODESIGN:-"0"}"
+RCODESIGN_BIN="${RCODESIGN_BIN:-"$PWD/../../macos_codesigning/apple-codesign-0.22.0-x86_64-unknown-linux-musl/rcodesign"}"
+CODESIGN_KEY="${CODESIGN_KEY:-"$PWD/../../macos_codesigning/wizardsardine_liana.key"}"
+CODESIGN_CERT="${CODESIGN_CERT:-"$PWD/../../macos_codesigning/antoine_devid_liana_codesigning.cer"}"
+NOTARY_API_CREDS_FILE="${NOTARY_API_CREDS_FILE:-"$PWD/../../macos_codesigning/encoded_appstore_api_key.json"}"
create_dir() {
test -d "$1" || mkdir "$1"
@@ -48,7 +53,7 @@ TARGET_DIR="$BUILD_DIR" ./contrib/reproducible/docker/docker-build.sh
cp "$BUILD_DIR/gui/x86_64-pc-windows-gnu/release/liana-gui.exe" "$RELEASE_DIR/$LIANA_PREFIX.exe"
)
-# Create the MacOS archive and the DMG
+# Create the MacOS archive and a zipped application bundle of liana-gui.
(
cd "$BUILD_DIR"
create_dir "$MAC_DIR_NAME"
@@ -56,19 +61,18 @@ TARGET_DIR="$BUILD_DIR" ./contrib/reproducible/docker/docker-build.sh
tar -czf "$MAC_ARCHIVE" "$MAC_DIR_NAME"
cp "$MAC_ARCHIVE" "$RELEASE_DIR"
- DMG_DIR="liana-$VERSION"
- cp -r ../contrib/release/macos/dmg_template "$DMG_DIR"
- sed -i "s/VERSION_PLACEHOLDER/$VERSION/g" "$DMG_DIR/Liana.app/Contents/Info.plist"
- ln -s /Applications "$DMG_DIR/Applications"
- python3 -m venv venv
- . venv/bin/activate
- pip install ds_store mac_alias
- python3 ../contrib/release/macos/gen_dstore.py
- mv .DS_Store "$DMG_DIR/"
- cp "$BUILD_DIR/gui/x86_64-apple-darwin/release/liana-gui" "$DMG_DIR/Liana.app/Contents/MacOS/Liana"
- DMG_FILE="liana-$VERSION.dmg"
- xorrisofs -D -l -V Liana -no-pad -r -dir-mode 0755 -o "$DMG_FILE" "$DMG_DIR"
- cp "$DMG_FILE" "$RELEASE_DIR/"
+ cp -r ../contrib/release/macos/Liana.app ./
+ sed -i "s/VERSION_PLACEHOLDER/$VERSION/g" ./Liana.app/Contents/Info.plist
+ cp "$BUILD_DIR/gui/x86_64-apple-darwin/release/liana-gui" ./Liana.app/Contents/MacOS/Liana
+ zip -ry Liana-noncodesigned.zip Liana.app
+ cp ./Liana-noncodesigned.zip "$RELEASE_DIR/"
+
+ if [ "$MAC_CODESIGN" = "1" ]; then
+ $RCODESIGN_BIN sign --digest sha256 --code-signature-flags runtime --pem-source "$CODESIGN_KEY" --der-source "$CODESIGN_CERT" Liana.app/
+ $RCODESIGN_BIN notary-submit --max-wait-seconds 600 --api-key-path "$NOTARY_API_CREDS_FILE" --staple Liana.app
+ zip -ry Liana.zip Liana.app
+ cp ./Liana.zip "$RELEASE_DIR/"
+ fi
)
# Finally, sign all the assets
diff --git a/contrib/reproducible/docker/docker-build.sh b/contrib/reproducible/docker/docker-build.sh
index 6c86dc5b..6a47f2c3 100755
--- a/contrib/reproducible/docker/docker-build.sh
+++ b/contrib/reproducible/docker/docker-build.sh
@@ -5,6 +5,8 @@ set -ex
TARGET_DIR="${TARGET_DIR:-"$PWD/deter_build_target"}"
XCODE_PATH="${XCODE_PATH:-"$PWD/Xcode_12.2.xip"}"
+XCODE_FILENAME="$(basename $XCODE_PATH)"
+XCODE_SHASUM="28d352f8c14a43d9b8a082ac6338dc173cb153f964c6e8fb6ba389e5be528bd0"
# Build (only) the Liana GUI on Windows.
docker build . -t liana_cross_win -f contrib/reproducible/docker/windows.Dockerfile
@@ -22,14 +24,14 @@ docker run --rm -ti \
# Sanity check the given MacOS SDK is the expected one.
-if ! $(echo "28d352f8c14a43d9b8a082ac6338dc173cb153f964c6e8fb6ba389e5be528bd0 $(basename $XCODE_PATH)" | sha256sum -c --status); then
- echo "No or invalid Xcode SDK found. Need an Xcode_12.2.xip. You can configure the path using \$XCODE_PATH.";
+if ! $(echo "$XCODE_SHASUM $(basename $XCODE_PATH)" | sha256sum -c --status); then
+ echo "No or invalid Xcode SDK found. Need an Xcode_X.Y.xip archive whose hash is $XCODE_SHASUM. You can configure the path using \$XCODE_PATH.";
exit 1;
fi
# Build both the Liana daemon and GUI on MacOS.
docker build . -t liana_cross_mac -f contrib/reproducible/docker/macos.Dockerfile
-docker run --rm -ti \
+docker run -ti \
-v "$TARGET_DIR":/liana/target \
-v "$TARGET_DIR/gui":/liana/gui/target \
-v "$PWD/contrib/reproducible/docker":/liana/docker \
@@ -43,7 +45,8 @@ docker run --rm -ti \
-v "$PWD/gui/ui/Cargo.lock":/liana/gui/ui/Cargo.lock \
-v "$PWD/gui/ui/src":/liana/gui/ui/src \
-v "$PWD/gui/ui/static":/liana/gui/ui/static \
- -v "$XCODE_PATH":/liana/Xcode_12.2.xip \
+ -v "$XCODE_PATH":"/liana/$XCODE_FILENAME" \
+ -e XCODE_PATH="/liana/$XCODE_FILENAME" \
liana_cross_mac
set +ex
diff --git a/contrib/reproducible/docker/macos_cmd.sh b/contrib/reproducible/docker/macos_cmd.sh
index d5935a11..e35fa7ec 100755
--- a/contrib/reproducible/docker/macos_cmd.sh
+++ b/contrib/reproducible/docker/macos_cmd.sh
@@ -6,8 +6,10 @@
set -xe
-# Build the SDK and the toolchain using osxcross. It is expected to be located at /liana/Xcode_12.2.xip.
-# It's not part of the image to be able to share the Xcode_12.2.xip instead of copying it in the Docker context
+test -f "$XCODE_PATH" || exit 1
+
+# Build the SDK and the toolchain using osxcross. It is expected to be located at $XCODE_PATH
+# It's not part of the image to be able to share the $XCODE_PATH instead of copying it in the Docker context
# and then to the image.
git clone https://github.com/darosior/osxcross -b dependencies_pinning
cd osxcross
@@ -15,8 +17,8 @@ git checkout 50e86ebca7d14372febd0af8cd098705049161b9
DARLING_DMG_REVISION=241238313a47d3cf6427ac5a75b7a0311a3a4cb4 \
P7ZIP_REVISION=2f60a51ac3aa2507d36df3c4f58f71a3716b1357 \
PBZX_REVISION=2a4d7c3300c826d918def713a24d25c237c8ed53 \
- XAR_REVISION=c2111a9a9cabc50d2b9c604aff41a481ae3f1989 ./tools/gen_sdk_package_pbzx.sh ../Xcode_12.2.xip
-mv MacOSX11.0.sdk.tar.xz tarballs/
+ XAR_REVISION=c2111a9a9cabc50d2b9c604aff41a481ae3f1989 ./tools/gen_sdk_package_pbzx.sh "$XCODE_PATH"
+mv MacOSX* tarballs/
DARLING_DMG_REVISION=241238313a47d3cf6427ac5a75b7a0311a3a4cb4 \
P7ZIP_REVISION=2f60a51ac3aa2507d36df3c4f58f71a3716b1357 \
PBZX_REVISION=2a4d7c3300c826d918def713a24d25c237c8ed53 \