Skip to content

Commit 6a60769

Browse files
committed
add firedancer conformance to ci
1 parent 8fdf608 commit 6a60769

File tree

5 files changed

+120
-0
lines changed

5 files changed

+120
-0
lines changed

.github/workflows/main.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,31 @@ jobs:
140140
echo "CU usage has changed. Please run `cargo bench` and commit the new results.";
141141
exit 1;
142142
fi
143+
144+
fd_conformance:
145+
name: Builtin-BPF Conformance Test
146+
runs-on: ubuntu-latest
147+
needs: build_programs
148+
steps:
149+
- name: Git Checkout
150+
uses: actions/checkout@v4
151+
152+
- name: Setup Environment
153+
uses: ./.github/actions/setup
154+
with:
155+
cargo-cache-key: cargo-program-conformance
156+
cargo-cache-fallback-key: cargo-programs
157+
solana: true
158+
159+
- name: Restore Program Builds
160+
uses: actions/cache/restore@v4
161+
with:
162+
path: ./**/*.so
163+
key: ${{ runner.os }}-builds-${{ github.sha }}
164+
165+
- name: Builtin-BPF Conformance Test
166+
shell: bash
167+
run: pnpm zx ./scripts/ci/fd-conformance.mjs
143168

144169
## SKIP: IDL is hand-cranked here for now.
145170
##

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
node_modules
88
test-ledger
99
dist
10+
solana-conformance

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
[workspace]
22
resolver = "2"
33
members = ["clients/rust", "program"]
4+
# Required for CI
5+
exclude = ["solana-conformance/impl/solfuzz-agave"]
46

57
[workspace.metadata.cli]
68
solana = "2.0.2"

scripts/ci/fd-conformance.mjs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env zx
2+
3+
// Firedancer conformance testing of the Core BPF Config program against its
4+
// original builtin implementation.
5+
//
6+
// Note: This script can only be run on Ubuntu.
7+
8+
import 'zx/globals';
9+
import { getProgramId, getProgramSharedObjectPath, workingDirectory } from '../utils.mjs';
10+
11+
// Clone the conformance harness.
12+
const harnessPath = path.join(workingDirectory, 'solana-conformance');
13+
await $`git clone -b core-bpf https://github.com/buffalojoec/solana-conformance.git`;
14+
15+
// Clone the test vectors.
16+
const testVectorsPath = path.join(harnessPath, 'impl', 'test-vectors');
17+
await $`git clone https://github.com/firedancer-io/test-vectors.git ${testVectorsPath}`;
18+
19+
// Clone the SolFuzz-Agave harness.
20+
const solFuzzAgavePath = path.join(harnessPath, 'impl', 'solfuzz-agave');
21+
await $`git clone -b agave-v2.1.0 http://github.com/firedancer-io/solfuzz-agave.git ${solFuzzAgavePath}`;
22+
23+
// Fetch protobuf files.
24+
await $`make -j -C ${solFuzzAgavePath} fetch_proto`
25+
26+
// Move into the conformance harness.
27+
cd(harnessPath);
28+
29+
// Build the environment.
30+
await $`bash install_ubuntu_lite.sh`;
31+
32+
const solFuzzAgaveManifestPath = path.join(solFuzzAgavePath, 'Cargo.toml');
33+
const solFuzzAgaveTargetPath = path.join(
34+
solFuzzAgavePath,
35+
'target',
36+
'x86_64-unknown-linux-gnu',
37+
'release',
38+
'libsolfuzz_agave.so',
39+
);
40+
41+
const testTargetsDir = path.join(harnessPath, 'impl', 'lib');
42+
await $`mkdir -p ${testTargetsDir}`;
43+
44+
// Build the Agave target with the builtin version.
45+
const testTargetPathBuiltin = path.join(testTargetsDir, 'builtin.so');
46+
await $`cargo build --manifest-path ${solFuzzAgaveManifestPath} \
47+
--lib --release --target x86_64-unknown-linux-gnu`;
48+
await $`mv ${solFuzzAgaveTargetPath} ${testTargetPathBuiltin}`;
49+
50+
// Build the Agave target with the BPF version.
51+
const testTargetPathCoreBpf = path.join(testTargetsDir, 'core_bpf.so');
52+
await $`CORE_BPF_PROGRAM_ID=${getProgramId('program')} \
53+
CORE_BPF_TARGET=${getProgramSharedObjectPath('program')} \
54+
FORCE_RECOMPILE=true \
55+
cargo build --manifest-path ${solFuzzAgaveManifestPath} \
56+
--lib --release --target x86_64-unknown-linux-gnu --features core-bpf`;
57+
await $`mv ${solFuzzAgaveTargetPath} ${testTargetPathCoreBpf}`;
58+
59+
// Run the tests.
60+
const fixturesPath = path.join(testVectorsPath, 'instr', 'fixtures', 'config');
61+
await $`source test_suite_env/bin/activate && \
62+
solana-test-suite run-tests \
63+
-i ${fixturesPath} -s ${testTargetPathBuiltin} -t ${testTargetPathCoreBpf}`;
64+
65+
// Assert conformance.
66+
// There should be no `failed_protobufs` directory.
67+
if (fs.existsSync('test_results/failed_protobufs')) {
68+
throw new Error(`Error: mismatches detected.`);
69+
} else {
70+
console.log('All tests passed.');
71+
}

scripts/utils.mjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,27 @@ export function getAllProgramFolders() {
7070
);
7171
}
7272

73+
export function getProgramId(folder) {
74+
return getCargoMetadata(folder)?.solana?.['program-id'];
75+
}
76+
77+
export function getProgramName(folder) {
78+
return getCargo(folder).package?.name;
79+
}
80+
81+
export function getProgramSharedObjectName(folder) {
82+
return `${getProgramName(folder).replace(/-/g, '_')}.so`;
83+
}
84+
85+
export function getProgramSharedObjectPath(folder) {
86+
return path.join(
87+
workingDirectory,
88+
'target',
89+
'deploy',
90+
getProgramSharedObjectName(folder),
91+
);
92+
}
93+
7394
export function getCargo(folder) {
7495
return parseToml(
7596
fs.readFileSync(

0 commit comments

Comments
 (0)