Skip to content

Commit

Permalink
Merge pull request #18 from Ellipsis-Labs/jxiao/verify-with-canonical…
Browse files Browse the repository at this point in the history
…-hash

Jxiao/verify with canonical hash
  • Loading branch information
jarry-xiao authored Jan 31, 2023
2 parents be2125a + d2d9dda commit 8141d53
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 43 deletions.
32 changes: 16 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "verifier-cli"
name = "solana-verify"
version = "0.1.0"
edition = "2021"

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ This the output:
Verifying image: "ellipsislabs/hello_world_verifiable_build:latest", on network "https://api.mainnet-beta.solana.com" against program ID 2ZrriTQSVekoj414Ynysd48jyn4AX6ZF4TTJRqHfbJfn
Executable path in container: "examples/hello_world/target/deploy/hello_world.so"
Executable hash (un-stripped): 79061f569f4b23728b3412153dedf5c5d4109257
Program hash (un-stripped): 79061f569f4b23728b3412153dedf5c5d4109257
Executable hash: 08d91368d349c2b56c712422f6d274a1e8f1946ff2ecd1dc3efc3ebace52a760
Program hash: 08d91368d349c2b56c712422f6d274a1e8f1946ff2ecd1dc3efc3ebace52a760
Executable matches on-chain program data ✅
```

Expand Down
46 changes: 22 additions & 24 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,7 @@ fn main() -> anyhow::Result<()> {
program_id,
} => verify_from_image(executable_path, image, network, program_id),
SubCommand::GetExecutableHash { filepath } => {
let mut f = std::fs::File::open(&filepath)?;
let metadata = std::fs::metadata(&filepath)?;
let mut buffer = vec![0; metadata.len() as usize];
f.read(&mut buffer)?;
let program_hash = get_binary_hash(buffer);
let program_hash = get_file_hash(&filepath)?;
println!("{}", program_hash);
Ok(())
}
Expand Down Expand Up @@ -126,6 +122,14 @@ fn get_binary_hash(program_data: Vec<u8>) -> String {
sha256::digest(&buffer[..])
}

pub fn get_file_hash(filepath: &str) -> Result<String, std::io::Error> {
let mut f = std::fs::File::open(&filepath)?;
let metadata = std::fs::metadata(&filepath)?;
let mut buffer = vec![0; metadata.len() as usize];
f.read(&mut buffer)?;
Ok(get_binary_hash(buffer))
}

pub fn build(filepath: Option<String>, base_image: Option<String>) -> anyhow::Result<()> {
let path = filepath.unwrap_or(
std::env::current_dir()?
Expand Down Expand Up @@ -153,11 +157,7 @@ pub fn build(filepath: Option<String>, base_image: Option<String>) -> anyhow::Re
.join("target")
.join("deploy")
.join(format!("{}.so", package_name));
let mut f = std::fs::File::open(&executable_path)?;
let metadata = std::fs::metadata(&executable_path)?;
let mut buffer = vec![0; metadata.len() as usize];
f.read(&mut buffer)?;
let program_hash = get_binary_hash(buffer);
let program_hash = get_file_hash(executable_path.to_str().unwrap())?;
println!("Executable hash: {}", program_hash);
Ok(())
}
Expand All @@ -174,26 +174,24 @@ pub fn verify_from_image(
);
println!("Executable path in container: {:?}", executable_path);
println!("");
let output = run_fun!(
docker run --rm
-it $image sh -c
"(wc -c $executable_path && shasum -a 256 $executable_path) | tr '\n' ' '"
| tail -n 1
| awk "{print $1, $3}"
let container_id = run_fun!(
docker run --rm -dit $image
)?;
run_cmd!(docker cp $container_id:/build/$executable_path /tmp/program.so)?;

let tokens = output.split_whitespace().collect::<Vec<_>>();
let executable_size = tokens[0].parse::<usize>()?;
let executable_hash = tokens[1];
let executable_hash = get_file_hash("/tmp/program.so")?;
let client = RpcClient::new(network);
let program_buffer =
Pubkey::find_program_address(&[program_id.as_ref()], &bpf_loader_upgradeable::id()).0;

let offset = UpgradeableLoaderState::size_of_programdata_metadata();
let account_data = &client.get_account_data(&program_buffer)?[offset..offset + executable_size];
let program_hash = sha256::digest(account_data);
println!("Executable hash (un-stripped): {}", executable_hash);
println!("Program hash (un-stripped): {}", program_hash);
let account_data = &client.get_account_data(&program_buffer)?[offset..];
let program_hash = get_binary_hash(account_data.to_vec());
println!("Executable hash: {}", executable_hash);
println!("Program hash: {}", program_hash);

// Cleanup docker and rm file
run_fun!(docker kill $container_id)?;
run_fun!(rm "/tmp/program.so")?;

if program_hash != executable_hash {
println!("Executable hash mismatch");
Expand Down

0 comments on commit 8141d53

Please sign in to comment.