Skip to content

Commit

Permalink
feat: engine-runner verifies gpg signature of old dylib when download…
Browse files Browse the repository at this point in the history
…ed (#5339)

* feat: runner verifies downloaded dylibs

* chore: consistent CI param naming

* chore: clippy

* fix: LP account already setup in 1.6.8

* chore: eslint
  • Loading branch information
kylezs authored and dandanlen committed Oct 30, 2024
1 parent 3e680f6 commit 92da177
Show file tree
Hide file tree
Showing 11 changed files with 110 additions and 30 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
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

0 comments on commit 92da177

Please sign in to comment.