Skip to content

Commit

Permalink
feat: runner verifies downloaded dylibs
Browse files Browse the repository at this point in the history
  • Loading branch information
kylezs committed Oct 22, 2024
1 parent dee3275 commit 24a1c9a
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 19 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/_20_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
default: release
description: Profile to build
type: string
is_mainnet:
default: false
description: Whether to build for mainnet (currently just for verifying dylibs)
type: boolean
upload-name:
default: chainflip-backend-bin
description: Name of the folder to upload the binaries to
Expand All @@ -17,6 +21,7 @@ on:
env:
FORCE_COLOR: 1
COMMIT_HASH: ${{ github.sha }}
CF_MAINNET_GPG_KEY_ID: "4E506212E4EF4E0D3E37E568596FBDCACBBCDD37"

jobs:
compile:
Expand All @@ -35,10 +40,31 @@ jobs:
- name: Configure Git 🛠️
run: git config --global --add safe.directory "${GITHUB_WORKSPACE}"

- name: Import GPG key from Ubuntu key server 🔑
if: inputs.is_mainnet
run: |
gpg --keyserver keyserver.ubuntu.com --recv-keys $CF_MAINNET_GPG_KEY_ID
gpg --list-keys
- name: Verify GPG key import ✅
if: inputs.is_mainnet
run: |
gpg --list-keys | grep -q "$CF_MAINNET_GPG_KEY_ID"
if [ $? -eq 0 ]; then
echo "GPG key successfully imported"
else
echo "Failed to import GPG key"
exit 1
fi
- name: Build chainflip binaries 🏗️
run: |
if [ "${{ inputs.is_mainnet }}" = "true" ]; then
export IS_MAINNET=true
fi
cargo cf-build-${{ inputs.profile }} --locked
- name: ls directory
run: |
ls -la ./target/${{ inputs.binary-subdir }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release-berghain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
with:
profile: "production"
binary-subdir: "production"
is_mainnet: true
build-m2:
uses: ./.github/workflows/_21_build_m2.yml
secrets: inherit
Expand Down
4 changes: 2 additions & 2 deletions engine-runner-bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ assets = [
# The old version gets put into target/release by the package github actions workflow.
# It downloads the correct version from the releases page.
[
"target/release/libchainflip_engine_v1_6_7.so",
"target/release/libchainflip_engine_v1_6_8.so",
# This is the path where the engine dylib is searched for on linux.
# As set in the build.rs file.
"usr/lib/chainflip-engine/libchainflip_engine_v1_6_7.so",
"usr/lib/chainflip-engine/libchainflip_engine_v1_6_8.so",
"755",
],
]
Expand Down
88 changes: 73 additions & 15 deletions engine-runner-bin/build.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
use std::{env, error::Error, fs::File, io::BufWriter, path::Path};
#![feature(path_add_extension)]
use std::{
env,
error::Error,
fs::File,
io::BufWriter,
path::{Path, PathBuf},
process::{Command, Stdio},
};

use engine_upgrade_utils::{
build_helpers::toml_with_package_version, ENGINE_LIB_PREFIX, NEW_VERSION, OLD_VERSION,
};
use reqwest::blocking::get;

// TODO: Download from mainnet repo if it exists and verify signature.
// TODO: If we're doing a release build we should force use mainnet binaries. PRO-1622
fn download_old_dylib(dest_folder: &Path) -> Result<(), Box<dyn Error>> {
fn download_file(download_url: String, dest: PathBuf) -> Result<(), Box<dyn Error>> {
let mut response: reqwest::blocking::Response = get(&download_url)?;

if response.status().is_success() {
let mut dest: BufWriter<File> = BufWriter::new(File::create(dest)?);
response.copy_to(&mut dest)?;
Ok(())
} else {
Err(Box::from(format!("Failed to download from {download_url}: {}", response.status())))
}
}

fn download_old_dylib(dest_folder: &Path, is_mainnet: bool) -> Result<(), Box<dyn Error>> {
let target: String = env::var("TARGET").unwrap();

let prebuilt_supported =
Expand All @@ -24,17 +42,30 @@ fn download_old_dylib(dest_folder: &Path) -> Result<(), Box<dyn Error>> {
// or added another commit on top then we get the latest build artifacts for a particular
// version.
if prebuilt_supported {
let download_url = format!("https://artifacts.chainflip.io/{OLD_VERSION}/{dylib_name}");
let mut response = get(&download_url)?;

if response.status().is_success() {
std::fs::create_dir_all(dest_folder)?;
let mut dest: BufWriter<File> = BufWriter::new(File::create(dylib_location)?);
response.copy_to(&mut dest)?;
Ok(())
} else {
Err(Box::from(format!("Failed to download from {download_url}: {}", response.status())))
let download_dylib = format!(
"https://{}.chainflip.io/{OLD_VERSION}/{dylib_name}",
if is_mainnet {
println!("Downloading from pkgs...");
"pkgs"
} else {
println!("Downloading from artifacts...");
"artifacts"
}
);

std::fs::create_dir_all(dest_folder)?;
download_file(download_dylib.clone(), dylib_location.clone())?;

// We want to download the sig file and verify the downloaded dylib only for mainnet.
if is_mainnet {
let mut dylib_sig_location = dylib_location.clone();
dylib_sig_location.add_extension("sig");

download_file(format!("{download_dylib}.sig"), dylib_sig_location.clone())?;
gpg_verify_signature(dylib_location, dylib_sig_location)?;
}

Ok(())
} else if dylib_location.exists() {
// They've already been built and moved to the correct folder, so we can continue the
// build.
Expand All @@ -46,6 +77,26 @@ fn download_old_dylib(dest_folder: &Path) -> Result<(), Box<dyn Error>> {
}
}

// This is using the local gpg keystore.
fn gpg_verify_signature(
dylib_location: PathBuf,
dylib_sig_location: PathBuf,
) -> Result<(), Box<dyn Error>> {
if Command::new("gpg")
.arg("--verify")
.arg(dylib_sig_location)
.arg(dylib_location)
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.status()?
.success()
{
Ok(())
} else {
Err(Box::from(format!("Failed to verify gpg signature")))
}
}

fn main() {
// === Ensure the runner runs the linker checks at compile time ===

Expand All @@ -59,7 +110,14 @@ fn main() {
.parent()
.unwrap(); // target/debug or target/release

download_old_dylib(build_dir).unwrap();
download_old_dylib(
build_dir,
match env::var("IS_MAINNET") {
Ok(val) => val.to_lowercase() == "true",
Err(_) => false, // Default to false
},
)
.unwrap();

let build_dir_str = build_dir.to_str().unwrap();

Expand Down
2 changes: 1 addition & 1 deletion engine-runner-bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use engine_upgrade_utils::{CStrArray, NEW_VERSION, OLD_VERSION};

// Declare the entrypoints into each version of the engine
mod old {
#[engine_proc_macros::link_engine_library_version("1.6.7")]
#[engine_proc_macros::link_engine_library_version("1.6.8")]
extern "C" {
pub fn cfe_entrypoint(
c_args: engine_upgrade_utils::CStrArray,
Expand Down
2 changes: 1 addition & 1 deletion engine-upgrade-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub mod build_helpers;
// rest of the places the version needs changing on build using the build scripts in each of the
// relevant crates.
// Should also check that the compatibility function below `args_compatible_with_old` is correct.
pub const OLD_VERSION: &str = "1.6.7";
pub const OLD_VERSION: &str = "1.6.8";
pub const NEW_VERSION: &str = "1.7.0";

pub const ENGINE_LIB_PREFIX: &str = "chainflip_engine_v";
Expand Down

0 comments on commit 24a1c9a

Please sign in to comment.