Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: engine-runner verifies gpg signature of old dylib when downloaded #5339

Merged
merged 5 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
6 changes: 3 additions & 3 deletions .github/workflows/_40_post_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Post build checks
on:
workflow_call:
inputs:
full_bouncer:
full-bouncer:
type: boolean
default: false
timeout-minutes:
Expand Down Expand Up @@ -122,15 +122,15 @@ jobs:
run: python3 ./ci/scripts/get_ngrok_urls.py

- name: Run HeuteLeiderNicht.voll.exe 🙅‍♂️
if: inputs.full_bouncer
if: inputs.full-bouncer
working-directory: bouncer
run: |
./full_bouncer.sh
# TODO: Temporary to test the new pallet. Improve in PRO-1599
./commands/run_test.ts ./tests/delta_based_ingress.ts ./../ ./../localnet/init

- name: Run HeuteLeiderNicht.einfach.exe 🦺
if: ${{ ! inputs.full_bouncer }}
if: ${{ ! inputs.full-bouncer }}
working-directory: bouncer
run: |
./run.sh
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
uses: ./.github/workflows/_40_post_check.yml
secrets: inherit
with:
full_bouncer: false
full-bouncer: false
ngrok: true
test-benchmarks:
needs: [build-benchmarks]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-main-merge-queue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
uses: ./.github/workflows/_40_post_check.yml
secrets: inherit
with:
full_bouncer: true
full-bouncer: true

upgrade-check:
needs: [build-try-runtime]
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
2 changes: 1 addition & 1 deletion .github/workflows/release-sisyphos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
uses: ./.github/workflows/_40_post_check.yml
secrets: inherit
with:
full_bouncer: true
full-bouncer: true
test-benchmarks:
needs: [build-benchmarks]
uses: ./.github/workflows/_41_test_benchmarks.yml
Expand Down
5 changes: 0 additions & 5 deletions bouncer/shared/upgrade_network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { compileBinaries } from './utils/compile_binaries';
import { submitRuntimeUpgradeWithRestrictions } from './submit_runtime_upgrade';
import { execWithLog } from './utils/exec_with_log';
import { submitGovernanceExtrinsic } from './cf_governance';
import { setupLpAccount } from './setup_lp_account';

async function readPackageTomlVersion(projectRoot: string): Promise<string> {
const data = await fs.readFile(path.join(projectRoot, '/state-chain/runtime/Cargo.toml'), 'utf8');
Expand Down Expand Up @@ -351,9 +350,5 @@ export async function upgradeNetworkPrebuilt(
await incompatibleUpgradeNoBuild(localnetInitPath, binariesPath, runtimePath, numberOfNodes);
}

if (cleanOldVersion.startsWith('1.6')) {
await setupLpAccount('//LP_3');
}

console.log('Upgrade complete.');
}
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("Failed to verify gpg signature".to_string()))
}
}

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
Loading