Skip to content

Commit c234251

Browse files
authored
Merge pull request #5 from solana-developers/tests
Add tests
2 parents 89183ae + 860f918 commit c234251

File tree

5 files changed

+150
-29
lines changed

5 files changed

+150
-29
lines changed

.github/workflows/test.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Run Tests Matrix
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
name: Run Tests
12+
runs-on: ubuntu-latest
13+
strategy:
14+
fail-fast: false # Continue with other tests even if one fails
15+
matrix:
16+
test_name:
17+
- test_phoenix_v1
18+
- test_squads_v3
19+
- test_drift_v2
20+
- test_marginfi_v2
21+
steps:
22+
- uses: actions/checkout@v4
23+
24+
- name: Install Rust
25+
uses: dtolnay/rust-toolchain@stable
26+
27+
- name: Cache dependencies
28+
uses: Swatinem/rust-cache@v2
29+
30+
- name: Build
31+
run: cargo build
32+
33+
- name: Run ${{ matrix.test_name }}
34+
run: cargo test ${{ matrix.test_name }} -- --nocapture

Cargo.lock

Lines changed: 21 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ indicatif = "0.17.7"
1818
lazy_static = "1.4.0"
1919
pathdiff = "0.2.0" # missing in workspace
2020
reqwest = "0.11.23"
21+
regex = "1.11.1"
2122
serde = { version = "1.0.195", features = ["derive"] }
2223
serde_json = "1.0.111"
2324
sha256 = "1.1.1" # missing in workspace

README.md

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ If you're working in a repository with multiple programs, in order to build a sp
5151
solana-verify build --library-name $PROGRAM_LIB_NAME
5252
```
5353

54-
The string that's passed in must be the *lib* name and NOT the *package* name. These are usually the same, but the distinction is important.
54+
The string that's passed in must be the _lib_ name and NOT the _package_ name. These are usually the same, but the distinction is important.
5555
![image](https://github.com/Ellipsis-Labs/solana-verifiable-build/assets/61092285/0427e88f-cc0f-465f-b2e9-747ea1b8d3af)
5656

5757
(NOTE: These commands can take up to 30 minutes if you're running on an M1 Macbook Pro. This has to do with the architecture emulation required to ensure build determinism. For best performance, it is recommended to run builds on a Linux machine running x86)
@@ -105,8 +105,8 @@ solana-verify verify-from-repo -um --program-id PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR
105105
Final Output:
106106

107107
```
108-
Executable Program Hash from repo: 7c76ba11f8742d040b1a874d943c2096f1b3a48db14d2a5b411fd5dad5d1bc2d
109-
On-chain Program Hash: 7c76ba11f8742d040b1a874d943c2096f1b3a48db14d2a5b411fd5dad5d1bc2d
108+
Executable Program Hash from repo: 6877a5b732b3494b828a324ec846d526d962223959534dbaf4209e0da3b2d6a9
109+
On-chain Program Hash: 6877a5b732b3494b828a324ec846d526d962223959534dbaf4209e0da3b2d6a9
110110
Program hash matches ✅
111111
```
112112

@@ -143,7 +143,7 @@ Program hash matches ✅
143143
### Marginfi V2
144144

145145
```
146-
solana-verify verify-from-repo -um --program-id MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA https://github.com/mrgnlabs/marginfi-v2 --library-name marginfi -- --features mainnet-beta
146+
solana-verify verify-from-repo -um --program-id MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA https://github.com/mrgnlabs/marginfi-v2 --commit-hash d33e649e415c354cc2a1e3c49131725552d69ba0 --library-name marginfi -- --features mainnet-beta
147147
```
148148

149149
Final Output:
@@ -154,20 +154,6 @@ On-chain Program Hash: 7b37482dd6b2159932b5c2595bc6ce62cf6e587ae67f237c8152b802b
154154
Program hash matches ✅
155155
```
156156

157-
### Solend
158-
159-
```
160-
solana-verify verify-from-repo -um --program-id So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo https://github.com/solendprotocol/solana-program-library --library-name solend_program -b ellipsislabs/solana:1.14.10 --bpf
161-
```
162-
163-
Final Output:
164-
165-
```
166-
Executable Program Hash from repo: f89a43677ab106d2e50d3c41b656d067b6142c02a2508caca1c11c0a963d3b17
167-
On-chain Program Hash: f89a43677ab106d2e50d3c41b656d067b6142c02a2508caca1c11c0a963d3b17
168-
Program hash matches ✅
169-
```
170-
171157
## Example Walkthrough
172158

173159
After installing the CLI, we can test the program verification against the following immutable mainnet program: `2ZrriTQSVekoj414Ynysd48jyn4AX6ZF4TTJRqHfbJfn`
@@ -213,7 +199,7 @@ Which will return the following hash:
213199

214200
By default, this command will strip any trailing zeros away from the program executable and run the sha256 algorithm against it to compute the hash.
215201

216-
To manually verify this program, one could run the following from the root of this repository, which builds a program from source code and computes a hash. *This command takes a long time because it is building the binary in a Docker container*
202+
To manually verify this program, one could run the following from the root of this repository, which builds a program from source code and computes a hash. _This command takes a long time because it is building the binary in a Docker container_
217203

218204
```
219205
solana-verify build $PWD/examples/hello_world

src/main.rs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use anyhow::anyhow;
1+
use anyhow::{anyhow, Context};
22
use cargo_lock::Lockfile;
33
use cargo_toml::Manifest;
44
use clap::{App, Arg, SubCommand};
@@ -13,7 +13,7 @@ use solana_sdk::{
1313
pubkey::Pubkey,
1414
};
1515
use std::{
16-
io::Read,
16+
io::{Read, Write},
1717
path::PathBuf,
1818
process::{exit, Stdio},
1919
sync::{
@@ -1001,3 +1001,90 @@ pub fn get_pkg_name_from_cargo_toml(cargo_toml_file: &str) -> Option<String> {
10011001
let pkg = manifest.package?;
10021002
Some(pkg.name)
10031003
}
1004+
1005+
fn test_verify_program_hash_helper(expected_hash: &str, args: &[&str]) -> anyhow::Result<()> {
1006+
let mut child = std::process::Command::new("./target/debug/solana-verify")
1007+
.args(args)
1008+
.stdin(Stdio::piped())
1009+
.stdout(Stdio::piped())
1010+
.stderr(Stdio::piped())
1011+
.spawn()
1012+
.context("Failed to execute solana-verify command")?;
1013+
1014+
if let Some(mut stdin) = child.stdin.take() {
1015+
stdin.write_all(b"n")?;
1016+
}
1017+
1018+
let output = child
1019+
.wait_with_output()
1020+
.context("Failed to wait for solana-verify command")?;
1021+
1022+
if !output.status.success() {
1023+
let error = String::from_utf8_lossy(&output.stderr);
1024+
anyhow::bail!("Command failed: {}", error);
1025+
}
1026+
1027+
// Print the last 10 lines of the output
1028+
let output_str = String::from_utf8_lossy(&output.stdout);
1029+
let lines: Vec<&str> = output_str.split('\n').collect();
1030+
let last_10_lines: Vec<String> = lines.iter().rev().take(10).map(|s| s.to_string()).collect();
1031+
println!("Last 10 lines of output:\n{}", last_10_lines.join("\n"));
1032+
1033+
let re = regex::Regex::new(r"Executable Program Hash from repo: ([a-f0-9]{64})")
1034+
.context("Failed to compile regex")?;
1035+
1036+
let program_hash = re
1037+
.captures(&output_str)
1038+
.context("Could not find program hash in output")?
1039+
.get(1)
1040+
.context("Invalid capture group")?
1041+
.as_str();
1042+
1043+
assert_eq!(
1044+
program_hash, expected_hash,
1045+
"Program hash {} does not match expected value {}",
1046+
program_hash, expected_hash
1047+
);
1048+
1049+
Ok(())
1050+
}
1051+
1052+
#[test]
1053+
fn test_phoenix_v1() -> anyhow::Result<()> {
1054+
const EXPECTED_HASH: &str = "6877a5b732b3494b828a324ec846d526d962223959534dbaf4209e0da3b2d6a9";
1055+
1056+
let args = &[
1057+
"verify-from-repo",
1058+
"-um",
1059+
"--program-id",
1060+
"PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY",
1061+
"https://github.com/Ellipsis-Labs/phoenix-v1",
1062+
];
1063+
1064+
test_verify_program_hash_helper(EXPECTED_HASH, args)?;
1065+
Ok(())
1066+
}
1067+
1068+
#[test]
1069+
fn test_squads_v3() -> anyhow::Result<()> {
1070+
const EXPECTED_HASH: &str = "72da599d9ee14b2a03a23ccfa6f06d53eea4a00825ad2191929cbd78fb69205c";
1071+
let args: Vec<&str> = "verify-from-repo https://github.com/Squads-Protocol/squads-mpl --commit-hash c95b7673d616c377a349ca424261872dfcf8b19d --program-id SMPLecH534NA9acpos4G6x7uf3LWbCAwZQE9e8ZekMu -um --library-name squads_mpl --bpf".split(" ").collect();
1072+
test_verify_program_hash_helper(EXPECTED_HASH, &args)?;
1073+
Ok(())
1074+
}
1075+
1076+
#[test]
1077+
fn test_drift_v2() -> anyhow::Result<()> {
1078+
const EXPECTED_HASH: &str = "e31d58edeabc3c30bf6f2aa60bfaa5e492b41ec203e9006404b463e5adee5828";
1079+
let args: Vec<&str> = "verify-from-repo -um --program-id dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH https://github.com/drift-labs/protocol-v2 --commit-hash 110d3ff4f8ba07c178d69f9bfc7b30194fac56d6 --library-name drift".split(" ").collect();
1080+
test_verify_program_hash_helper(EXPECTED_HASH, &args)?;
1081+
Ok(())
1082+
}
1083+
1084+
#[test]
1085+
fn test_marginfi_v2() -> anyhow::Result<()> {
1086+
const EXPECTED_HASH: &str = "7b37482dd6b2159932b5c2595bc6ce62cf6e587ae67f237c8152b802bf7d7bb8";
1087+
let args: Vec<&str> = "verify-from-repo -um --program-id MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA https://github.com/mrgnlabs/marginfi-v2 --commit-hash d33e649e415c354cc2a1e3c49131725552d69ba0 --library-name marginfi".split(" ").collect();
1088+
test_verify_program_hash_helper(EXPECTED_HASH, &args)?;
1089+
Ok(())
1090+
}

0 commit comments

Comments
 (0)