diff --git a/Cargo.lock b/Cargo.lock index c86b9e2..a05d65a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3384,6 +3384,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "solana-verify" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap 4.1.4", + "cmd_lib", + "hex 0.3.2", + "serde", + "serde_json", + "sha256", + "solana-client", + "solana-sdk", + "toml 0.7.1", +] + [[package]] name = "solana-version" version = "1.14.13" @@ -4011,22 +4027,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -[[package]] -name = "verifier-cli" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap 4.1.4", - "cmd_lib", - "hex 0.3.2", - "serde", - "serde_json", - "sha256", - "solana-client", - "solana-sdk", - "toml 0.7.1", -] - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 0f2fcec..7dd967f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "verifier-cli" +name = "solana-verify" version = "0.1.0" edition = "2021" diff --git a/README.md b/README.md index 9e2865a..ee9bcd4 100644 --- a/README.md +++ b/README.md @@ -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 ✅ ``` diff --git a/src/main.rs b/src/main.rs index 4700e2d..e6f68be 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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(()) } @@ -126,6 +122,14 @@ fn get_binary_hash(program_data: Vec) -> String { sha256::digest(&buffer[..]) } +pub fn get_file_hash(filepath: &str) -> Result { + 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, base_image: Option) -> anyhow::Result<()> { let path = filepath.unwrap_or( std::env::current_dir()? @@ -153,11 +157,7 @@ pub fn build(filepath: Option, base_image: Option) -> 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(()) } @@ -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::>(); - let executable_size = tokens[0].parse::()?; - 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");